Allow single-stepping a wave that is selected by HW ID.

Signed-off-by: Nicolai Hähnle <nicolai.haeh...@amd.com>
---
 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.stde...@amd.com>
  *
  */
 #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

Reply via email to