Commit bd31e502 authored by Lancelot SIX's avatar Lancelot SIX Committed by Alex Deucher
Browse files

drm/amdkfd: Enable SQ watchpoint for gfx10



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: default avatarLancelot SIX <lancelot.six@amd.com>
Reviewed-by: default avatarJonathan Kim <jonathan.kim@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 59d99deb
Loading
Loading
Loading
Loading
+58 −13
Original line number Diff line number Diff line
@@ -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