xref: /aosp_15_r20/external/mesa3d/src/amd/common/ac_pm4.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2012 Advanced Micro Devices, Inc.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker  */
6*61046927SAndroid Build Coastguard Worker 
7*61046927SAndroid Build Coastguard Worker #include "ac_debug.h"
8*61046927SAndroid Build Coastguard Worker #include "ac_gpu_info.h"
9*61046927SAndroid Build Coastguard Worker #include "ac_pm4.h"
10*61046927SAndroid Build Coastguard Worker 
11*61046927SAndroid Build Coastguard Worker #include "sid.h"
12*61046927SAndroid Build Coastguard Worker 
13*61046927SAndroid Build Coastguard Worker #include <string.h>
14*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
15*61046927SAndroid Build Coastguard Worker 
16*61046927SAndroid Build Coastguard Worker static bool
opcode_is_pairs(unsigned opcode)17*61046927SAndroid Build Coastguard Worker opcode_is_pairs(unsigned opcode)
18*61046927SAndroid Build Coastguard Worker {
19*61046927SAndroid Build Coastguard Worker    return opcode == PKT3_SET_CONTEXT_REG_PAIRS ||
20*61046927SAndroid Build Coastguard Worker           opcode == PKT3_SET_SH_REG_PAIRS ||
21*61046927SAndroid Build Coastguard Worker           opcode == PKT3_SET_UCONFIG_REG_PAIRS;
22*61046927SAndroid Build Coastguard Worker }
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker static bool
opcode_is_pairs_packed(unsigned opcode)25*61046927SAndroid Build Coastguard Worker opcode_is_pairs_packed(unsigned opcode)
26*61046927SAndroid Build Coastguard Worker {
27*61046927SAndroid Build Coastguard Worker    return opcode == PKT3_SET_CONTEXT_REG_PAIRS_PACKED ||
28*61046927SAndroid Build Coastguard Worker           opcode == PKT3_SET_SH_REG_PAIRS_PACKED ||
29*61046927SAndroid Build Coastguard Worker           opcode == PKT3_SET_SH_REG_PAIRS_PACKED_N;
30*61046927SAndroid Build Coastguard Worker }
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker static bool
is_privileged_reg(const struct ac_pm4_state * state,unsigned reg)33*61046927SAndroid Build Coastguard Worker is_privileged_reg(const struct ac_pm4_state *state, unsigned reg)
34*61046927SAndroid Build Coastguard Worker {
35*61046927SAndroid Build Coastguard Worker    const struct radeon_info *info = state->info;
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker    if (info->gfx_level >= GFX10 && info->gfx_level <= GFX10_3)
38*61046927SAndroid Build Coastguard Worker       return reg == R_008D04_SQ_THREAD_TRACE_BUF0_SIZE ||
39*61046927SAndroid Build Coastguard Worker              reg == R_008D00_SQ_THREAD_TRACE_BUF0_BASE ||
40*61046927SAndroid Build Coastguard Worker              reg == R_008D14_SQ_THREAD_TRACE_MASK ||
41*61046927SAndroid Build Coastguard Worker              reg == R_008D18_SQ_THREAD_TRACE_TOKEN_MASK ||
42*61046927SAndroid Build Coastguard Worker              reg == R_008D1C_SQ_THREAD_TRACE_CTRL;
43*61046927SAndroid Build Coastguard Worker 
44*61046927SAndroid Build Coastguard Worker    if (info->gfx_level >= GFX6 && info->gfx_level <= GFX8)
45*61046927SAndroid Build Coastguard Worker       return reg == R_009100_SPI_CONFIG_CNTL;
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker    return false;
48*61046927SAndroid Build Coastguard Worker }
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker static unsigned
pairs_packed_opcode_to_regular(unsigned opcode)51*61046927SAndroid Build Coastguard Worker pairs_packed_opcode_to_regular(unsigned opcode)
52*61046927SAndroid Build Coastguard Worker {
53*61046927SAndroid Build Coastguard Worker    switch (opcode) {
54*61046927SAndroid Build Coastguard Worker    case PKT3_SET_CONTEXT_REG_PAIRS_PACKED:
55*61046927SAndroid Build Coastguard Worker       return PKT3_SET_CONTEXT_REG;
56*61046927SAndroid Build Coastguard Worker    case PKT3_SET_SH_REG_PAIRS_PACKED:
57*61046927SAndroid Build Coastguard Worker       return PKT3_SET_SH_REG;
58*61046927SAndroid Build Coastguard Worker    default:
59*61046927SAndroid Build Coastguard Worker       unreachable("invalid packed opcode");
60*61046927SAndroid Build Coastguard Worker    }
61*61046927SAndroid Build Coastguard Worker }
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker static unsigned
regular_opcode_to_pairs(struct ac_pm4_state * state,unsigned opcode)64*61046927SAndroid Build Coastguard Worker regular_opcode_to_pairs(struct ac_pm4_state *state, unsigned opcode)
65*61046927SAndroid Build Coastguard Worker {
66*61046927SAndroid Build Coastguard Worker    const struct radeon_info *info = state->info;
67*61046927SAndroid Build Coastguard Worker 
68*61046927SAndroid Build Coastguard Worker    switch (opcode) {
69*61046927SAndroid Build Coastguard Worker    case PKT3_SET_CONTEXT_REG:
70*61046927SAndroid Build Coastguard Worker       return info->has_set_context_pairs_packed ? PKT3_SET_CONTEXT_REG_PAIRS_PACKED :
71*61046927SAndroid Build Coastguard Worker              info->has_set_context_pairs ? PKT3_SET_CONTEXT_REG_PAIRS : opcode;
72*61046927SAndroid Build Coastguard Worker    case PKT3_SET_SH_REG:
73*61046927SAndroid Build Coastguard Worker       return info->has_set_sh_pairs_packed ? PKT3_SET_SH_REG_PAIRS_PACKED :
74*61046927SAndroid Build Coastguard Worker              info->has_set_sh_pairs ? PKT3_SET_SH_REG_PAIRS : opcode;
75*61046927SAndroid Build Coastguard Worker    case PKT3_SET_UCONFIG_REG:
76*61046927SAndroid Build Coastguard Worker       return info->has_set_uconfig_pairs ? PKT3_SET_UCONFIG_REG_PAIRS : opcode;
77*61046927SAndroid Build Coastguard Worker    }
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker    return opcode;
80*61046927SAndroid Build Coastguard Worker }
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker static bool
packed_next_is_reg_offset_pair(struct ac_pm4_state * state)83*61046927SAndroid Build Coastguard Worker packed_next_is_reg_offset_pair(struct ac_pm4_state *state)
84*61046927SAndroid Build Coastguard Worker {
85*61046927SAndroid Build Coastguard Worker    return (state->ndw - state->last_pm4) % 3 == 2;
86*61046927SAndroid Build Coastguard Worker }
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker static bool
packed_next_is_reg_value1(struct ac_pm4_state * state)89*61046927SAndroid Build Coastguard Worker packed_next_is_reg_value1(struct ac_pm4_state *state)
90*61046927SAndroid Build Coastguard Worker {
91*61046927SAndroid Build Coastguard Worker    return (state->ndw - state->last_pm4) % 3 == 1;
92*61046927SAndroid Build Coastguard Worker }
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker static bool
packed_prev_is_reg_value0(struct ac_pm4_state * state)95*61046927SAndroid Build Coastguard Worker packed_prev_is_reg_value0(struct ac_pm4_state *state)
96*61046927SAndroid Build Coastguard Worker {
97*61046927SAndroid Build Coastguard Worker    return packed_next_is_reg_value1(state);
98*61046927SAndroid Build Coastguard Worker }
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker static unsigned
get_packed_reg_dw_offsetN(struct ac_pm4_state * state,unsigned index)101*61046927SAndroid Build Coastguard Worker get_packed_reg_dw_offsetN(struct ac_pm4_state *state, unsigned index)
102*61046927SAndroid Build Coastguard Worker {
103*61046927SAndroid Build Coastguard Worker    unsigned i = state->last_pm4 + 2 + (index / 2) * 3;
104*61046927SAndroid Build Coastguard Worker    assert(i < state->ndw);
105*61046927SAndroid Build Coastguard Worker    return (state->pm4[i] >> ((index % 2) * 16)) & 0xffff;
106*61046927SAndroid Build Coastguard Worker }
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker static unsigned
get_packed_reg_valueN_idx(struct ac_pm4_state * state,unsigned index)109*61046927SAndroid Build Coastguard Worker get_packed_reg_valueN_idx(struct ac_pm4_state *state, unsigned index)
110*61046927SAndroid Build Coastguard Worker {
111*61046927SAndroid Build Coastguard Worker    unsigned i = state->last_pm4 + 2 + (index / 2) * 3 + 1 + (index % 2);
112*61046927SAndroid Build Coastguard Worker    assert(i < state->ndw);
113*61046927SAndroid Build Coastguard Worker    return i;
114*61046927SAndroid Build Coastguard Worker }
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker static unsigned
get_packed_reg_valueN(struct ac_pm4_state * state,unsigned index)117*61046927SAndroid Build Coastguard Worker get_packed_reg_valueN(struct ac_pm4_state *state, unsigned index)
118*61046927SAndroid Build Coastguard Worker {
119*61046927SAndroid Build Coastguard Worker    return state->pm4[get_packed_reg_valueN_idx(state, index)];
120*61046927SAndroid Build Coastguard Worker }
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker static unsigned
get_packed_reg_count(struct ac_pm4_state * state)123*61046927SAndroid Build Coastguard Worker get_packed_reg_count(struct ac_pm4_state *state)
124*61046927SAndroid Build Coastguard Worker {
125*61046927SAndroid Build Coastguard Worker    int body_size = state->ndw - state->last_pm4 - 2;
126*61046927SAndroid Build Coastguard Worker    assert(body_size > 0 && body_size % 3 == 0);
127*61046927SAndroid Build Coastguard Worker    return (body_size / 3) * 2;
128*61046927SAndroid Build Coastguard Worker }
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker void
ac_pm4_finalize(struct ac_pm4_state * state)131*61046927SAndroid Build Coastguard Worker ac_pm4_finalize(struct ac_pm4_state *state)
132*61046927SAndroid Build Coastguard Worker {
133*61046927SAndroid Build Coastguard Worker    if (opcode_is_pairs_packed(state->last_opcode)) {
134*61046927SAndroid Build Coastguard Worker       unsigned reg_count = get_packed_reg_count(state);
135*61046927SAndroid Build Coastguard Worker       unsigned reg_dw_offset0 = get_packed_reg_dw_offsetN(state, 0);
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker       if (state->packed_is_padded)
138*61046927SAndroid Build Coastguard Worker          reg_count--;
139*61046927SAndroid Build Coastguard Worker 
140*61046927SAndroid Build Coastguard Worker       bool all_consecutive = true;
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker       /* If the whole packed SET packet only sets consecutive registers, rewrite the packet
143*61046927SAndroid Build Coastguard Worker        * to be unpacked to make it shorter.
144*61046927SAndroid Build Coastguard Worker        *
145*61046927SAndroid Build Coastguard Worker        * This also eliminates the invalid scenario when the packed SET packet sets only
146*61046927SAndroid Build Coastguard Worker        * 2 registers and the register offsets are equal due to padding.
147*61046927SAndroid Build Coastguard Worker        */
148*61046927SAndroid Build Coastguard Worker       for (unsigned i = 1; i < reg_count; i++) {
149*61046927SAndroid Build Coastguard Worker          if (reg_dw_offset0 != get_packed_reg_dw_offsetN(state, i) - i) {
150*61046927SAndroid Build Coastguard Worker             all_consecutive = false;
151*61046927SAndroid Build Coastguard Worker             break;
152*61046927SAndroid Build Coastguard Worker          }
153*61046927SAndroid Build Coastguard Worker       }
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker       if (all_consecutive) {
156*61046927SAndroid Build Coastguard Worker          assert(state->ndw - state->last_pm4 == 2 + 3 * (reg_count + state->packed_is_padded) / 2);
157*61046927SAndroid Build Coastguard Worker          state->pm4[state->last_pm4] = PKT3(pairs_packed_opcode_to_regular(state->last_opcode),
158*61046927SAndroid Build Coastguard Worker                                             reg_count, 0);
159*61046927SAndroid Build Coastguard Worker          state->pm4[state->last_pm4 + 1] = reg_dw_offset0;
160*61046927SAndroid Build Coastguard Worker          for (unsigned i = 0; i < reg_count; i++)
161*61046927SAndroid Build Coastguard Worker             state->pm4[state->last_pm4 + 2 + i] = get_packed_reg_valueN(state, i);
162*61046927SAndroid Build Coastguard Worker          state->ndw = state->last_pm4 + 2 + reg_count;
163*61046927SAndroid Build Coastguard Worker          state->last_opcode = PKT3_SET_SH_REG;
164*61046927SAndroid Build Coastguard Worker       } else {
165*61046927SAndroid Build Coastguard Worker          /* Set reg_va_low_idx to where the shader address is stored in the pm4 state. */
166*61046927SAndroid Build Coastguard Worker          if (state->debug_sqtt &&
167*61046927SAndroid Build Coastguard Worker              (state->last_opcode == PKT3_SET_SH_REG_PAIRS_PACKED ||
168*61046927SAndroid Build Coastguard Worker               state->last_opcode == PKT3_SET_SH_REG_PAIRS_PACKED_N)) {
169*61046927SAndroid Build Coastguard Worker             if (state->packed_is_padded)
170*61046927SAndroid Build Coastguard Worker                reg_count++; /* Add this back because we only need to record the last write. */
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker             for (int i = reg_count - 1; i >= 0; i--) {
173*61046927SAndroid Build Coastguard Worker                unsigned reg_offset = SI_SH_REG_OFFSET + get_packed_reg_dw_offsetN(state, i) * 4;
174*61046927SAndroid Build Coastguard Worker 
175*61046927SAndroid Build Coastguard Worker                if (strstr(ac_get_register_name(state->info->gfx_level,
176*61046927SAndroid Build Coastguard Worker                                                state->info->family, reg_offset),
177*61046927SAndroid Build Coastguard Worker                           "SPI_SHADER_PGM_LO_")) {
178*61046927SAndroid Build Coastguard Worker                   state->spi_shader_pgm_lo_reg = reg_offset;
179*61046927SAndroid Build Coastguard Worker                   break;
180*61046927SAndroid Build Coastguard Worker                }
181*61046927SAndroid Build Coastguard Worker             }
182*61046927SAndroid Build Coastguard Worker          }
183*61046927SAndroid Build Coastguard Worker 
184*61046927SAndroid Build Coastguard Worker          /* If it's a packed SET_SH packet, use the *_N variant when possible. */
185*61046927SAndroid Build Coastguard Worker          if (state->last_opcode == PKT3_SET_SH_REG_PAIRS_PACKED && reg_count <= 14) {
186*61046927SAndroid Build Coastguard Worker             state->pm4[state->last_pm4] &= PKT3_IT_OPCODE_C;
187*61046927SAndroid Build Coastguard Worker             state->pm4[state->last_pm4] |= PKT3_IT_OPCODE_S(PKT3_SET_SH_REG_PAIRS_PACKED_N);
188*61046927SAndroid Build Coastguard Worker          }
189*61046927SAndroid Build Coastguard Worker       }
190*61046927SAndroid Build Coastguard Worker    }
191*61046927SAndroid Build Coastguard Worker 
192*61046927SAndroid Build Coastguard Worker    if (state->debug_sqtt && state->last_opcode == PKT3_SET_SH_REG) {
193*61046927SAndroid Build Coastguard Worker       /* Set reg_va_low_idx to where the shader address is stored in the pm4 state. */
194*61046927SAndroid Build Coastguard Worker       unsigned reg_count = PKT_COUNT_G(state->pm4[state->last_pm4]);
195*61046927SAndroid Build Coastguard Worker       unsigned reg_base_offset = SI_SH_REG_OFFSET + state->pm4[state->last_pm4 + 1] * 4;
196*61046927SAndroid Build Coastguard Worker 
197*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < reg_count; i++) {
198*61046927SAndroid Build Coastguard Worker          if (strstr(ac_get_register_name(state->info->gfx_level,
199*61046927SAndroid Build Coastguard Worker                                          state->info->family, reg_base_offset + i * 4),
200*61046927SAndroid Build Coastguard Worker                     "SPI_SHADER_PGM_LO_")) {
201*61046927SAndroid Build Coastguard Worker             state->spi_shader_pgm_lo_reg = reg_base_offset + i * 4;
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker             break;
204*61046927SAndroid Build Coastguard Worker          }
205*61046927SAndroid Build Coastguard Worker       }
206*61046927SAndroid Build Coastguard Worker    }
207*61046927SAndroid Build Coastguard Worker }
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker void
ac_pm4_cmd_begin(struct ac_pm4_state * state,unsigned opcode)210*61046927SAndroid Build Coastguard Worker ac_pm4_cmd_begin(struct ac_pm4_state *state, unsigned opcode)
211*61046927SAndroid Build Coastguard Worker {
212*61046927SAndroid Build Coastguard Worker    ac_pm4_finalize(state);
213*61046927SAndroid Build Coastguard Worker 
214*61046927SAndroid Build Coastguard Worker    assert(state->max_dw);
215*61046927SAndroid Build Coastguard Worker    assert(state->ndw < state->max_dw);
216*61046927SAndroid Build Coastguard Worker    assert(opcode <= 254);
217*61046927SAndroid Build Coastguard Worker    state->last_opcode = opcode;
218*61046927SAndroid Build Coastguard Worker    state->last_pm4 = state->ndw++;
219*61046927SAndroid Build Coastguard Worker    state->packed_is_padded = false;
220*61046927SAndroid Build Coastguard Worker }
221*61046927SAndroid Build Coastguard Worker 
222*61046927SAndroid Build Coastguard Worker void
ac_pm4_cmd_add(struct ac_pm4_state * state,uint32_t dw)223*61046927SAndroid Build Coastguard Worker ac_pm4_cmd_add(struct ac_pm4_state *state, uint32_t dw)
224*61046927SAndroid Build Coastguard Worker {
225*61046927SAndroid Build Coastguard Worker    assert(state->max_dw);
226*61046927SAndroid Build Coastguard Worker    assert(state->ndw < state->max_dw);
227*61046927SAndroid Build Coastguard Worker    state->pm4[state->ndw++] = dw;
228*61046927SAndroid Build Coastguard Worker    state->last_opcode = 255; /* invalid opcode */
229*61046927SAndroid Build Coastguard Worker }
230*61046927SAndroid Build Coastguard Worker 
231*61046927SAndroid Build Coastguard Worker static bool
need_reset_filter_cam(const struct ac_pm4_state * state)232*61046927SAndroid Build Coastguard Worker need_reset_filter_cam(const struct ac_pm4_state *state)
233*61046927SAndroid Build Coastguard Worker {
234*61046927SAndroid Build Coastguard Worker    const struct radeon_info *info = state->info;
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker    /* All SET_*_PAIRS* packets on the gfx queue must set RESET_FILTER_CAM. */
237*61046927SAndroid Build Coastguard Worker    if (!state->is_compute_queue &&
238*61046927SAndroid Build Coastguard Worker        (opcode_is_pairs(state->last_opcode) ||
239*61046927SAndroid Build Coastguard Worker         opcode_is_pairs_packed(state->last_opcode)))
240*61046927SAndroid Build Coastguard Worker       return true;
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker    const uint32_t last_reg = state->last_reg << 2;
243*61046927SAndroid Build Coastguard Worker 
244*61046927SAndroid Build Coastguard Worker    if (info->gfx_level >= GFX11 && !state->is_compute_queue &&
245*61046927SAndroid Build Coastguard Worker        (last_reg + CIK_UCONFIG_REG_OFFSET == R_0367A4_SQ_THREAD_TRACE_BUF0_SIZE ||
246*61046927SAndroid Build Coastguard Worker         last_reg + CIK_UCONFIG_REG_OFFSET == R_0367A0_SQ_THREAD_TRACE_BUF0_BASE ||
247*61046927SAndroid Build Coastguard Worker         last_reg + CIK_UCONFIG_REG_OFFSET == R_0367B4_SQ_THREAD_TRACE_MASK ||
248*61046927SAndroid Build Coastguard Worker         last_reg + CIK_UCONFIG_REG_OFFSET == R_0367B8_SQ_THREAD_TRACE_TOKEN_MASK ||
249*61046927SAndroid Build Coastguard Worker         last_reg + CIK_UCONFIG_REG_OFFSET == R_0367B0_SQ_THREAD_TRACE_CTRL))
250*61046927SAndroid Build Coastguard Worker       return true;
251*61046927SAndroid Build Coastguard Worker 
252*61046927SAndroid Build Coastguard Worker    return false;
253*61046927SAndroid Build Coastguard Worker }
254*61046927SAndroid Build Coastguard Worker 
255*61046927SAndroid Build Coastguard Worker void
ac_pm4_cmd_end(struct ac_pm4_state * state,bool predicate)256*61046927SAndroid Build Coastguard Worker ac_pm4_cmd_end(struct ac_pm4_state *state, bool predicate)
257*61046927SAndroid Build Coastguard Worker {
258*61046927SAndroid Build Coastguard Worker    unsigned count;
259*61046927SAndroid Build Coastguard Worker    count = state->ndw - state->last_pm4 - 2;
260*61046927SAndroid Build Coastguard Worker    /* All SET_*_PAIRS* packets on the gfx queue must set RESET_FILTER_CAM. */
261*61046927SAndroid Build Coastguard Worker    bool reset_filter_cam = need_reset_filter_cam(state);
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker    state->pm4[state->last_pm4] = PKT3(state->last_opcode, count, predicate) |
264*61046927SAndroid Build Coastguard Worker                                  PKT3_RESET_FILTER_CAM_S(reset_filter_cam);
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker    if (opcode_is_pairs_packed(state->last_opcode)) {
267*61046927SAndroid Build Coastguard Worker       if (packed_prev_is_reg_value0(state)) {
268*61046927SAndroid Build Coastguard Worker          /* Duplicate the first register at the end to make the number of registers aligned to 2. */
269*61046927SAndroid Build Coastguard Worker          ac_pm4_set_reg_custom(state, get_packed_reg_dw_offsetN(state, 0) * 4,
270*61046927SAndroid Build Coastguard Worker                                get_packed_reg_valueN(state, 0),
271*61046927SAndroid Build Coastguard Worker                                state->last_opcode, 0);
272*61046927SAndroid Build Coastguard Worker          state->packed_is_padded = true;
273*61046927SAndroid Build Coastguard Worker       }
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker       state->pm4[state->last_pm4 + 1] = get_packed_reg_count(state);
276*61046927SAndroid Build Coastguard Worker    }
277*61046927SAndroid Build Coastguard Worker }
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker void
ac_pm4_set_reg_custom(struct ac_pm4_state * state,unsigned reg,uint32_t val,unsigned opcode,unsigned idx)280*61046927SAndroid Build Coastguard Worker ac_pm4_set_reg_custom(struct ac_pm4_state *state, unsigned reg, uint32_t val,
281*61046927SAndroid Build Coastguard Worker                       unsigned opcode, unsigned idx)
282*61046927SAndroid Build Coastguard Worker {
283*61046927SAndroid Build Coastguard Worker    bool is_packed = opcode_is_pairs_packed(opcode);
284*61046927SAndroid Build Coastguard Worker    reg >>= 2;
285*61046927SAndroid Build Coastguard Worker 
286*61046927SAndroid Build Coastguard Worker    assert(state->max_dw);
287*61046927SAndroid Build Coastguard Worker    assert(state->ndw + 2 <= state->max_dw);
288*61046927SAndroid Build Coastguard Worker 
289*61046927SAndroid Build Coastguard Worker    if (is_packed) {
290*61046927SAndroid Build Coastguard Worker       assert(idx == 0);
291*61046927SAndroid Build Coastguard Worker 
292*61046927SAndroid Build Coastguard Worker       if (opcode != state->last_opcode) {
293*61046927SAndroid Build Coastguard Worker          ac_pm4_cmd_begin(state, opcode); /* reserve space for the header */
294*61046927SAndroid Build Coastguard Worker          state->ndw++; /* reserve space for the register count, it will be set at the end */
295*61046927SAndroid Build Coastguard Worker       }
296*61046927SAndroid Build Coastguard Worker    } else if (opcode_is_pairs(opcode)) {
297*61046927SAndroid Build Coastguard Worker       assert(idx == 0);
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker       if (opcode != state->last_opcode)
300*61046927SAndroid Build Coastguard Worker          ac_pm4_cmd_begin(state, opcode);
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker       state->pm4[state->ndw++] = reg;
303*61046927SAndroid Build Coastguard Worker    } else if (opcode != state->last_opcode || reg != (state->last_reg + 1) ||
304*61046927SAndroid Build Coastguard Worker               idx != state->last_idx) {
305*61046927SAndroid Build Coastguard Worker       ac_pm4_cmd_begin(state, opcode);
306*61046927SAndroid Build Coastguard Worker       state->pm4[state->ndw++] = reg | (idx << 28);
307*61046927SAndroid Build Coastguard Worker    }
308*61046927SAndroid Build Coastguard Worker 
309*61046927SAndroid Build Coastguard Worker    assert(reg <= UINT16_MAX);
310*61046927SAndroid Build Coastguard Worker    state->last_reg = reg;
311*61046927SAndroid Build Coastguard Worker    state->last_idx = idx;
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker    if (is_packed) {
314*61046927SAndroid Build Coastguard Worker       if (state->packed_is_padded) {
315*61046927SAndroid Build Coastguard Worker          /* The packet is padded, which means the first register is written redundantly again
316*61046927SAndroid Build Coastguard Worker           * at the end. Remove it, so that we can replace it with this register.
317*61046927SAndroid Build Coastguard Worker           */
318*61046927SAndroid Build Coastguard Worker          state->packed_is_padded = false;
319*61046927SAndroid Build Coastguard Worker          state->ndw--;
320*61046927SAndroid Build Coastguard Worker       }
321*61046927SAndroid Build Coastguard Worker 
322*61046927SAndroid Build Coastguard Worker       if (packed_next_is_reg_offset_pair(state)) {
323*61046927SAndroid Build Coastguard Worker          state->pm4[state->ndw++] = reg;
324*61046927SAndroid Build Coastguard Worker       } else if (packed_next_is_reg_value1(state)) {
325*61046927SAndroid Build Coastguard Worker          /* Set the second register offset in the high 16 bits. */
326*61046927SAndroid Build Coastguard Worker          state->pm4[state->ndw - 2] &= 0x0000ffff;
327*61046927SAndroid Build Coastguard Worker          state->pm4[state->ndw - 2] |= reg << 16;
328*61046927SAndroid Build Coastguard Worker       }
329*61046927SAndroid Build Coastguard Worker    }
330*61046927SAndroid Build Coastguard Worker 
331*61046927SAndroid Build Coastguard Worker    state->pm4[state->ndw++] = val;
332*61046927SAndroid Build Coastguard Worker    ac_pm4_cmd_end(state, false);
333*61046927SAndroid Build Coastguard Worker }
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker static void
ac_pm4_set_privileged_reg(struct ac_pm4_state * state,unsigned reg,uint32_t val)336*61046927SAndroid Build Coastguard Worker ac_pm4_set_privileged_reg(struct ac_pm4_state *state, unsigned reg, uint32_t val)
337*61046927SAndroid Build Coastguard Worker {
338*61046927SAndroid Build Coastguard Worker    assert(reg >= SI_CONFIG_REG_OFFSET && reg < SI_CONFIG_REG_END);
339*61046927SAndroid Build Coastguard Worker 
340*61046927SAndroid Build Coastguard Worker    ac_pm4_cmd_add(state, PKT3(PKT3_COPY_DATA, 4, 0));
341*61046927SAndroid Build Coastguard Worker    ac_pm4_cmd_add(state, COPY_DATA_SRC_SEL(COPY_DATA_IMM) | COPY_DATA_DST_SEL(COPY_DATA_PERF));
342*61046927SAndroid Build Coastguard Worker    ac_pm4_cmd_add(state, val);
343*61046927SAndroid Build Coastguard Worker    ac_pm4_cmd_add(state, 0); /* unused */
344*61046927SAndroid Build Coastguard Worker    ac_pm4_cmd_add(state, reg >> 2);
345*61046927SAndroid Build Coastguard Worker    ac_pm4_cmd_add(state, 0); /* unused */
346*61046927SAndroid Build Coastguard Worker }
347*61046927SAndroid Build Coastguard Worker 
ac_pm4_set_reg(struct ac_pm4_state * state,unsigned reg,uint32_t val)348*61046927SAndroid Build Coastguard Worker void ac_pm4_set_reg(struct ac_pm4_state *state, unsigned reg, uint32_t val)
349*61046927SAndroid Build Coastguard Worker {
350*61046927SAndroid Build Coastguard Worker    const unsigned original_reg = reg;
351*61046927SAndroid Build Coastguard Worker    unsigned opcode;
352*61046927SAndroid Build Coastguard Worker 
353*61046927SAndroid Build Coastguard Worker    if (reg >= SI_CONFIG_REG_OFFSET && reg < SI_CONFIG_REG_END) {
354*61046927SAndroid Build Coastguard Worker       opcode = PKT3_SET_CONFIG_REG;
355*61046927SAndroid Build Coastguard Worker       reg -= SI_CONFIG_REG_OFFSET;
356*61046927SAndroid Build Coastguard Worker 
357*61046927SAndroid Build Coastguard Worker    } else if (reg >= SI_SH_REG_OFFSET && reg < SI_SH_REG_END) {
358*61046927SAndroid Build Coastguard Worker       opcode = PKT3_SET_SH_REG;
359*61046927SAndroid Build Coastguard Worker       reg -= SI_SH_REG_OFFSET;
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker    } else if (reg >= SI_CONTEXT_REG_OFFSET && reg < SI_CONTEXT_REG_END) {
362*61046927SAndroid Build Coastguard Worker       opcode = PKT3_SET_CONTEXT_REG;
363*61046927SAndroid Build Coastguard Worker       reg -= SI_CONTEXT_REG_OFFSET;
364*61046927SAndroid Build Coastguard Worker 
365*61046927SAndroid Build Coastguard Worker    } else if (reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END) {
366*61046927SAndroid Build Coastguard Worker       opcode = PKT3_SET_UCONFIG_REG;
367*61046927SAndroid Build Coastguard Worker       reg -= CIK_UCONFIG_REG_OFFSET;
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker    } else {
370*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "mesa: Invalid register offset %08x!\n", reg);
371*61046927SAndroid Build Coastguard Worker       return;
372*61046927SAndroid Build Coastguard Worker    }
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker    if (is_privileged_reg(state, original_reg)) {
375*61046927SAndroid Build Coastguard Worker       ac_pm4_set_privileged_reg(state, original_reg, val);
376*61046927SAndroid Build Coastguard Worker    } else {
377*61046927SAndroid Build Coastguard Worker       opcode = regular_opcode_to_pairs(state, opcode);
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker       ac_pm4_set_reg_custom(state, reg, val, opcode, 0);
380*61046927SAndroid Build Coastguard Worker    }
381*61046927SAndroid Build Coastguard Worker }
382*61046927SAndroid Build Coastguard Worker 
383*61046927SAndroid Build Coastguard Worker void
ac_pm4_set_reg_idx3(struct ac_pm4_state * state,unsigned reg,uint32_t val)384*61046927SAndroid Build Coastguard Worker ac_pm4_set_reg_idx3(struct ac_pm4_state *state, unsigned reg, uint32_t val)
385*61046927SAndroid Build Coastguard Worker {
386*61046927SAndroid Build Coastguard Worker    if (state->info->uses_kernel_cu_mask) {
387*61046927SAndroid Build Coastguard Worker       assert(state->info->gfx_level >= GFX10);
388*61046927SAndroid Build Coastguard Worker       ac_pm4_set_reg_custom(state, reg - SI_SH_REG_OFFSET, val, PKT3_SET_SH_REG_INDEX, 3);
389*61046927SAndroid Build Coastguard Worker    } else {
390*61046927SAndroid Build Coastguard Worker       ac_pm4_set_reg(state, reg, val);
391*61046927SAndroid Build Coastguard Worker    }
392*61046927SAndroid Build Coastguard Worker }
393*61046927SAndroid Build Coastguard Worker 
394*61046927SAndroid Build Coastguard Worker void
ac_pm4_clear_state(struct ac_pm4_state * state,const struct radeon_info * info,bool debug_sqtt,bool is_compute_queue)395*61046927SAndroid Build Coastguard Worker ac_pm4_clear_state(struct ac_pm4_state *state, const struct radeon_info *info,
396*61046927SAndroid Build Coastguard Worker                    bool debug_sqtt, bool is_compute_queue)
397*61046927SAndroid Build Coastguard Worker {
398*61046927SAndroid Build Coastguard Worker    state->info = info;
399*61046927SAndroid Build Coastguard Worker    state->debug_sqtt = debug_sqtt;
400*61046927SAndroid Build Coastguard Worker    state->ndw = 0;
401*61046927SAndroid Build Coastguard Worker    state->is_compute_queue = is_compute_queue;
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker    if (!state->max_dw)
404*61046927SAndroid Build Coastguard Worker       state->max_dw = ARRAY_SIZE(state->pm4);
405*61046927SAndroid Build Coastguard Worker }
406*61046927SAndroid Build Coastguard Worker 
407*61046927SAndroid Build Coastguard Worker struct ac_pm4_state *
ac_pm4_create_sized(const struct radeon_info * info,bool debug_sqtt,unsigned max_dw,bool is_compute_queue)408*61046927SAndroid Build Coastguard Worker ac_pm4_create_sized(const struct radeon_info *info, bool debug_sqtt,
409*61046927SAndroid Build Coastguard Worker                     unsigned max_dw, bool is_compute_queue)
410*61046927SAndroid Build Coastguard Worker {
411*61046927SAndroid Build Coastguard Worker    struct ac_pm4_state *pm4;
412*61046927SAndroid Build Coastguard Worker    unsigned size;
413*61046927SAndroid Build Coastguard Worker 
414*61046927SAndroid Build Coastguard Worker    max_dw = MAX2(max_dw, ARRAY_SIZE(pm4->pm4));
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker    size = sizeof(*pm4) + 4 * (max_dw - ARRAY_SIZE(pm4->pm4));
417*61046927SAndroid Build Coastguard Worker 
418*61046927SAndroid Build Coastguard Worker    pm4 = (struct ac_pm4_state *)calloc(1, size);
419*61046927SAndroid Build Coastguard Worker    if (pm4) {
420*61046927SAndroid Build Coastguard Worker       pm4->max_dw = max_dw;
421*61046927SAndroid Build Coastguard Worker       ac_pm4_clear_state(pm4, info, debug_sqtt, is_compute_queue);
422*61046927SAndroid Build Coastguard Worker    }
423*61046927SAndroid Build Coastguard Worker    return pm4;
424*61046927SAndroid Build Coastguard Worker }
425*61046927SAndroid Build Coastguard Worker 
426*61046927SAndroid Build Coastguard Worker void
ac_pm4_free_state(struct ac_pm4_state * state)427*61046927SAndroid Build Coastguard Worker ac_pm4_free_state(struct ac_pm4_state *state)
428*61046927SAndroid Build Coastguard Worker {
429*61046927SAndroid Build Coastguard Worker    if (!state)
430*61046927SAndroid Build Coastguard Worker       return;
431*61046927SAndroid Build Coastguard Worker 
432*61046927SAndroid Build Coastguard Worker    free(state);
433*61046927SAndroid Build Coastguard Worker }
434