Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6186f4d authored by Yair Shachar's avatar Yair Shachar Committed by Oded Gabbay
Browse files

drm/radeon: Add H/W debugger kfd->kgd functions



This patch adds new interface functions to the kfd2kgd interface file. The
new functions allow to perform H/W debugger operations by writing to GPU
registers.

Signed-off-by: default avatarYair Shachar <yair.shachar@amd.com>
Signed-off-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
parent f761d8bd
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -163,6 +163,19 @@ struct kfd2kgd_calls {
	int (*hqd_sdma_destroy)(struct kgd_dev *kgd, void *mqd,
				unsigned int timeout);

	int (*address_watch_disable)(struct kgd_dev *kgd);
	int (*address_watch_execute)(struct kgd_dev *kgd,
					unsigned int watch_point_id,
					uint32_t cntl_val,
					uint32_t addr_hi,
					uint32_t addr_lo);
	int (*wave_control_execute)(struct kgd_dev *kgd,
					uint32_t gfx_index_val,
					uint32_t sq_cmd);
	uint32_t (*address_watch_get_offset)(struct kgd_dev *kgd,
					unsigned int watch_point_id,
					unsigned int reg_offset);

	uint16_t (*get_fw_version)(struct kgd_dev *kgd,
				enum kgd_engine_type type);
};
+55 −1
Original line number Diff line number Diff line
@@ -149,10 +149,30 @@

#define KFD_CIK_SDMA_QUEUE_OFFSET		0x200

#define SQ_IND_INDEX					0x8DE0
#define SQ_CMD						0x8DEC
#define SQ_IND_DATA					0x8DE4

/*
 * The TCP_WATCHx_xxxx addresses that are shown here are in dwords,
 * and that's why they are multiplied by 4
 */
#define TCP_WATCH0_ADDR_H				(0x32A0*4)
#define TCP_WATCH1_ADDR_H				(0x32A3*4)
#define TCP_WATCH2_ADDR_H				(0x32A6*4)
#define TCP_WATCH3_ADDR_H				(0x32A9*4)
#define TCP_WATCH0_ADDR_L				(0x32A1*4)
#define TCP_WATCH1_ADDR_L				(0x32A4*4)
#define TCP_WATCH2_ADDR_L				(0x32A7*4)
#define TCP_WATCH3_ADDR_L				(0x32AA*4)
#define TCP_WATCH0_CNTL					(0x32A2*4)
#define TCP_WATCH1_CNTL					(0x32A5*4)
#define TCP_WATCH2_CNTL					(0x32A8*4)
#define TCP_WATCH3_CNTL					(0x32AB*4)

#define CPC_INT_CNTL					0xC2D0

#define CP_HQD_IQ_RPTR					0xC970u
#define AQL_ENABLE					(1U << 0)
#define SDMA0_RLC0_RB_CNTL				0xD400u
#define	SDMA_RB_VMID(x)					(x << 24)
#define	SDMA0_RLC0_RB_BASE				0xD404u
@@ -186,4 +206,38 @@
#define	SDMA0_CNTL					0xD010
#define	SDMA1_CNTL					0xD810

enum {
	MAX_TRAPID = 8,		/* 3 bits in the bitfield.  */
	MAX_WATCH_ADDRESSES = 4
};

enum {
	ADDRESS_WATCH_REG_ADDR_HI = 0,
	ADDRESS_WATCH_REG_ADDR_LO,
	ADDRESS_WATCH_REG_CNTL,
	ADDRESS_WATCH_REG_MAX
};

enum {				/*  not defined in the CI/KV reg file  */
	ADDRESS_WATCH_REG_CNTL_ATC_BIT = 0x10000000UL,
	ADDRESS_WATCH_REG_CNTL_DEFAULT_MASK = 0x00FFFFFF,
	ADDRESS_WATCH_REG_ADDLOW_MASK_EXTENSION = 0x03000000,
	/* extend the mask to 26 bits in order to match the low address field */
	ADDRESS_WATCH_REG_ADDLOW_SHIFT = 6,
	ADDRESS_WATCH_REG_ADDHIGH_MASK = 0xFFFF
};

union TCP_WATCH_CNTL_BITS {
	struct {
		uint32_t mask:24;
		uint32_t vmid:4;
		uint32_t atc:1;
		uint32_t mode:2;
		uint32_t valid:1;
	} bitfields, bits;
	uint32_t u32All;
	signed int i32All;
	float f32All;
};

#endif
+113 −0
Original line number Diff line number Diff line
@@ -34,6 +34,13 @@

#define CIK_PIPE_PER_MEC	(4)

static const uint32_t watchRegs[MAX_WATCH_ADDRESSES * ADDRESS_WATCH_REG_MAX] = {
	TCP_WATCH0_ADDR_H, TCP_WATCH0_ADDR_L, TCP_WATCH0_CNTL,
	TCP_WATCH1_ADDR_H, TCP_WATCH1_ADDR_L, TCP_WATCH1_CNTL,
	TCP_WATCH2_ADDR_H, TCP_WATCH2_ADDR_L, TCP_WATCH2_CNTL,
	TCP_WATCH3_ADDR_H, TCP_WATCH3_ADDR_L, TCP_WATCH3_CNTL
};

struct kgd_mem {
	struct radeon_bo *bo;
	uint64_t gpu_addr;
@@ -79,6 +86,18 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type,
static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd);
static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
				unsigned int timeout);
static int kgd_address_watch_disable(struct kgd_dev *kgd);
static int kgd_address_watch_execute(struct kgd_dev *kgd,
					unsigned int watch_point_id,
					uint32_t cntl_val,
					uint32_t addr_hi,
					uint32_t addr_lo);
static int kgd_wave_control_execute(struct kgd_dev *kgd,
					uint32_t gfx_index_val,
					uint32_t sq_cmd);
static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
					unsigned int watch_point_id,
					unsigned int reg_offset);

static const struct kfd2kgd_calls kfd2kgd = {
	.init_gtt_mem_allocation = alloc_gtt_mem,
@@ -96,6 +115,10 @@ static const struct kfd2kgd_calls kfd2kgd = {
	.hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied,
	.hqd_destroy = kgd_hqd_destroy,
	.hqd_sdma_destroy = kgd_hqd_sdma_destroy,
	.address_watch_disable = kgd_address_watch_disable,
	.address_watch_execute = kgd_address_watch_execute,
	.wave_control_execute = kgd_wave_control_execute,
	.address_watch_get_offset = kgd_address_watch_get_offset,
	.get_fw_version = get_fw_version
};

@@ -665,6 +688,96 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd,
	return 0;
}

static int kgd_address_watch_disable(struct kgd_dev *kgd)
{
	union TCP_WATCH_CNTL_BITS cntl;
	unsigned int i;

	cntl.u32All = 0;

	cntl.bitfields.valid = 0;
	cntl.bitfields.mask = ADDRESS_WATCH_REG_CNTL_DEFAULT_MASK;
	cntl.bitfields.atc = 1;

	/* Turning off this address until we set all the registers */
	for (i = 0; i < MAX_WATCH_ADDRESSES; i++)
		write_register(kgd,
				watchRegs[i * ADDRESS_WATCH_REG_MAX +
					ADDRESS_WATCH_REG_CNTL],
				cntl.u32All);

	return 0;
}

static int kgd_address_watch_execute(struct kgd_dev *kgd,
					unsigned int watch_point_id,
					uint32_t cntl_val,
					uint32_t addr_hi,
					uint32_t addr_lo)
{
	union TCP_WATCH_CNTL_BITS cntl;

	cntl.u32All = cntl_val;

	/* Turning off this watch point until we set all the registers */
	cntl.bitfields.valid = 0;
	write_register(kgd,
			watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX +
				ADDRESS_WATCH_REG_CNTL],
			cntl.u32All);

	write_register(kgd,
			watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX +
				ADDRESS_WATCH_REG_ADDR_HI],
			addr_hi);

	write_register(kgd,
			watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX +
				ADDRESS_WATCH_REG_ADDR_LO],
			addr_lo);

	/* Enable the watch point */
	cntl.bitfields.valid = 1;

	write_register(kgd,
			watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX +
				ADDRESS_WATCH_REG_CNTL],
			cntl.u32All);

	return 0;
}

static int kgd_wave_control_execute(struct kgd_dev *kgd,
					uint32_t gfx_index_val,
					uint32_t sq_cmd)
{
	struct radeon_device *rdev = get_radeon_device(kgd);
	uint32_t data;

	mutex_lock(&rdev->grbm_idx_mutex);

	write_register(kgd, GRBM_GFX_INDEX, gfx_index_val);
	write_register(kgd, SQ_CMD, sq_cmd);

	/*  Restore the GRBM_GFX_INDEX register  */

	data = INSTANCE_BROADCAST_WRITES | SH_BROADCAST_WRITES |
		SE_BROADCAST_WRITES;

	write_register(kgd, GRBM_GFX_INDEX, data);

	mutex_unlock(&rdev->grbm_idx_mutex);

	return 0;
}

static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd,
					unsigned int watch_point_id,
					unsigned int reg_offset)
{
	return watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + reg_offset];
}

static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type)
{
	struct radeon_device *rdev = (struct radeon_device *) kgd;