drm/amdkfd: Enable SQ watchpoint for gfx10
authorLancelot SIX <lancelot.six@amd.com>
Wed, 3 Apr 2024 09:21:24 +0000 (10:21 +0100)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 26 Apr 2024 21:22:44 +0000 (17:22 -0400)
There are new control registers introduced in gfx10 used to configure
hardware watchpoints triggered by SMEM instructions:
SQ_WATCH{0,1,2,3}_{CNTL_ADDR_HI,ADDR_L}.

Those registers work in a similar way as the TCP_WATCH* registers
currently used for gfx9 and above.

This patch adds support to program the SQ_WATCH registers for gfx10.

The SQ_WATCH?_CNTL.MASK field has one bit more than
TCP_WATCH?_CNTL.MASK, so SQ watchpoints can have a finer granularity
than TCP_WATCH watchpoints.  In this patch, we keep the capabilities
advertised to the debugger unchanged
(HSA_DBG_WATCH_ADDR_MASK_*_BIT_GFX10) as this reflects what both TCP and
SQ watchpoints can do and both watchpoints are configured together.

Signed-off-by: Lancelot SIX <lancelot.six@amd.com>
Reviewed-by: Jonathan Kim <jonathan.kim@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c

index 69810b3f1c63613f6686f181cdeccf5d9513c2d9..3ab6c3aa0ad1a96515741a6028f15e1130e49bdd 100644 (file)
@@ -881,6 +881,7 @@ uint32_t kgd_gfx_v10_set_wave_launch_mode(struct amdgpu_device *adev,
 }
 
 #define TCP_WATCH_STRIDE (mmTCP_WATCH1_ADDR_H - mmTCP_WATCH0_ADDR_H)
+#define SQ_WATCH_STRIDE (mmSQ_WATCH1_ADDR_H - mmSQ_WATCH0_ADDR_H)
 uint32_t kgd_gfx_v10_set_address_watch(struct amdgpu_device *adev,
                                        uint64_t watch_address,
                                        uint32_t watch_address_mask,
@@ -889,55 +890,93 @@ uint32_t kgd_gfx_v10_set_address_watch(struct amdgpu_device *adev,
                                        uint32_t debug_vmid,
                                        uint32_t inst)
 {
+       /* SQ_WATCH?_ADDR_* and TCP_WATCH?_ADDR_* are programmed with the
+        * same values.
+        */
        uint32_t watch_address_high;
        uint32_t watch_address_low;
-       uint32_t watch_address_cntl;
-
-       watch_address_cntl = 0;
+       uint32_t tcp_watch_address_cntl;
+       uint32_t sq_watch_address_cntl;
 
        watch_address_low = lower_32_bits(watch_address);
        watch_address_high = upper_32_bits(watch_address) & 0xffff;
 
-       watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+       tcp_watch_address_cntl = 0;
+       tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl,
                        TCP_WATCH0_CNTL,
                        VMID,
                        debug_vmid);
-       watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+       tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl,
                        TCP_WATCH0_CNTL,
                        MODE,
                        watch_mode);
-       watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+       tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl,
                        TCP_WATCH0_CNTL,
                        MASK,
                        watch_address_mask >> 7);
 
+       sq_watch_address_cntl = 0;
+       sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl,
+                       SQ_WATCH0_CNTL,
+                       VMID,
+                       debug_vmid);
+       sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl,
+                       SQ_WATCH0_CNTL,
+                       MODE,
+                       watch_mode);
+       sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl,
+                       SQ_WATCH0_CNTL,
+                       MASK,
+                       watch_address_mask >> 6);
+
        /* Turning off this watch point until we set all the registers */
-       watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+       tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl,
                        TCP_WATCH0_CNTL,
                        VALID,
                        0);
-
        WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
                        (watch_id * TCP_WATCH_STRIDE)),
-                       watch_address_cntl);
+                       tcp_watch_address_cntl);
+
+       sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl,
+                       SQ_WATCH0_CNTL,
+                       VALID,
+                       0);
+       WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_CNTL) +
+                       (watch_id * SQ_WATCH_STRIDE)),
+                       sq_watch_address_cntl);
 
+       /* Program {TCP,SQ}_WATCH?_ADDR* */
        WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_H) +
                        (watch_id * TCP_WATCH_STRIDE)),
                        watch_address_high);
-
        WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_L) +
                        (watch_id * TCP_WATCH_STRIDE)),
                        watch_address_low);
 
+       WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_ADDR_H) +
+                       (watch_id * SQ_WATCH_STRIDE)),
+                       watch_address_high);
+       WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_ADDR_L) +
+                       (watch_id * SQ_WATCH_STRIDE)),
+                       watch_address_low);
+
        /* Enable the watch point */
-       watch_address_cntl = REG_SET_FIELD(watch_address_cntl,
+       tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl,
                        TCP_WATCH0_CNTL,
                        VALID,
                        1);
-
        WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) +
                        (watch_id * TCP_WATCH_STRIDE)),
-                       watch_address_cntl);
+                       tcp_watch_address_cntl);
+
+       sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl,
+                       SQ_WATCH0_CNTL,
+                       VALID,
+                       1);
+       WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_CNTL) +
+                       (watch_id * SQ_WATCH_STRIDE)),
+                       sq_watch_address_cntl);
 
        return 0;
 }
@@ -953,8 +992,14 @@ uint32_t kgd_gfx_v10_clear_address_watch(struct amdgpu_device *adev,
                        (watch_id * TCP_WATCH_STRIDE)),
                        watch_address_cntl);
 
+       WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_CNTL) +
+                       (watch_id * SQ_WATCH_STRIDE)),
+                       watch_address_cntl);
+
        return 0;
 }
+#undef TCP_WATCH_STRIDE
+#undef SQ_WATCH_STRIDE
 
 
 /* kgd_gfx_v10_get_iq_wait_times: Returns the mmCP_IQ_WAIT_TIME1/2 values