Allow single-stepping a wave that is selected by HW ID. Signed-off-by: Nicolai Hähnle <nicolai.haehnle@xxxxxxx> --- src/lib/sq_cmd_halt_waves.c | 75 ++++++++++++++++++++++++++++++++----- src/umr.h | 1 + 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src/lib/sq_cmd_halt_waves.c b/src/lib/sq_cmd_halt_waves.c index 841b1d3..9a0ae69 100644 --- a/src/lib/sq_cmd_halt_waves.c +++ b/src/lib/sq_cmd_halt_waves.c @@ -17,45 +17,51 @@ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: Tom St Denis <tom.stdenis@xxxxxxx> * */ #include "umr.h" +static struct umr_reg *find_sq_cmd(struct umr_asic *asic) +{ + // SQ_CMD is not present on SI + if (asic->family == FAMILY_SI) + return 0; + + struct umr_reg *reg = umr_find_reg_data_by_ip_by_instance(asic, "gfx", asic->options.vm_partition, + asic->family >= FAMILY_GFX11 ? "regSQ_CMD" : "mmSQ_CMD"); + if (!reg) + asic->err_msg("[BUG]: Cannot find SQ_CMD register in umr_sq_cmd_halt_waves()\n"); + return reg; +} + /** * umr_sq_cmd_halt_waves - Attempt to halt or resume waves * * @mode: Use UMR_SQ_CMD_HALT to halt waves and * UMR_SQ_CMD_RESUME to resume waves. */ int umr_sq_cmd_halt_waves(struct umr_asic *asic, enum umr_sq_cmd_halt_resume mode) { struct umr_reg *reg; uint32_t value; uint64_t addr; struct { uint32_t se, sh, instance, use_grbm; } grbm; - // SQ_CMD is not present on SI - if (asic->family == FAMILY_SI) - return 0; - - reg = umr_find_reg_data_by_ip_by_instance(asic, "gfx", asic->options.vm_partition, - asic->family >= FAMILY_GFX11 ? "regSQ_CMD" : "mmSQ_CMD"); - if (!reg) { - asic->err_msg("[BUG]: Cannot find SQ_CMD register in umr_sq_cmd_halt_waves()\n"); + reg = find_sq_cmd(asic); + if (!reg) return -1; - } // compose value if (asic->family == FAMILY_CIK) { value = umr_bitslice_compose_value(asic, reg, "CMD", mode == UMR_SQ_CMD_HALT ? 1 : 2); // SETHALT } else { value = umr_bitslice_compose_value(asic, reg, "CMD", 1); // SETHALT value |= umr_bitslice_compose_value(asic, reg, "DATA", mode == UMR_SQ_CMD_HALT ? 1 : 0); } value |= umr_bitslice_compose_value(asic, reg, "MODE", 1); // BROADCAST @@ -76,10 +82,61 @@ int umr_sq_cmd_halt_waves(struct umr_asic *asic, enum umr_sq_cmd_halt_resume mod asic->reg_funcs.write_reg(asic, addr, value, reg->type); /* restore whatever the user had picked */ asic->options.use_bank = grbm.use_grbm; asic->options.bank.grbm.se = grbm.se; asic->options.bank.grbm.sh = grbm.sh; asic->options.bank.grbm.instance = grbm.instance; return 0; } + +/** + * umr_sq_cmd_singlestep - Attempt to single-step a single wave + * + * The wave is assumed to be halted. + */ +int umr_sq_cmd_singlestep(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t wgp, uint32_t simd, uint32_t wave) +{ + struct umr_reg *reg; + uint32_t value; + uint64_t addr; + struct { + uint32_t se, sh, instance, use_grbm; + } grbm; + + if (asic->family < FAMILY_NV) + return -1; // Only supported on gfx10+ + + reg = find_sq_cmd(asic); + if (!reg) + return -1; + + // compose value + value = umr_bitslice_compose_value(asic, reg, "CMD", 8); // SINGLE_STEP + value |= umr_bitslice_compose_value(asic, reg, "MODE", 0); // single wave + value |= umr_bitslice_compose_value(asic, reg, "WAVE_ID", wave); + + /* copy grbm options to restore later */ + grbm.use_grbm = asic->options.use_bank; + grbm.se = asic->options.bank.grbm.se; + grbm.sh = asic->options.bank.grbm.sh; + grbm.instance = asic->options.bank.grbm.instance; + + /* set GRBM banking options */ + asic->options.use_bank = 1; + asic->options.bank.grbm.se = se; + asic->options.bank.grbm.sh = sh; + asic->options.bank.grbm.instance = (wgp << 2) | simd; + + // compose address + addr = reg->addr * 4; + asic->reg_funcs.write_reg(asic, addr, value, reg->type); + + /* restore whatever the user had picked */ + asic->options.use_bank = grbm.use_grbm; + asic->options.bank.grbm.se = grbm.se; + asic->options.bank.grbm.sh = grbm.sh; + asic->options.bank.grbm.instance = grbm.instance; + + return 0; +} diff --git a/src/umr.h b/src/umr.h index 616b9cc..8981986 100644 --- a/src/umr.h +++ b/src/umr.h @@ -1466,20 +1466,21 @@ uint64_t umr_bitslice_compose_value_by_name_by_ip_by_instance(struct umr_asic *a // bank switching uint64_t umr_apply_bank_selection_address(struct umr_asic *asic); // select a GRBM_GFX_IDX int umr_grbm_select_index(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t instance); int umr_srbm_select_index(struct umr_asic *asic, uint32_t me, uint32_t pipe, uint32_t queue, uint32_t vmid); // halt/resume SQ waves int umr_sq_cmd_halt_waves(struct umr_asic *asic, enum umr_sq_cmd_halt_resume mode); +int umr_sq_cmd_singlestep(struct umr_asic *asic, uint32_t se, uint32_t sh, uint32_t wgp, uint32_t simd, uint32_t wave); /* IB/ring decoding/dumping/etc */ enum umr_ring_type { UMR_RING_PM4, UMR_RING_PM4_LITE, UMR_RING_SDMA, UMR_RING_MES, UMR_RING_GUESS, UMR_RING_UNK=0xFF, // if unknown -- 2.40.0