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....@amd.com>
---
 .../drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c    | 71 +++++++++++++++----
 1 file changed, 58 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
index 69810b3f1c63..3ab6c3aa0ad1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
@@ -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

base-commit: fd1be4972efe2c3f1183404572c34e2b5549c07e
-- 
2.34.1

Reply via email to