Commit 69a8c3ae authored by Jonathan Kim's avatar Jonathan Kim Committed by Alex Deucher
Browse files

drm/amdkfd: apply trap workaround for gfx11



Due to a HW bug, waves in only half the shader arrays can enter trap.

When starting a debug session, relocate all waves to the first shader
array of each shader engine and mask off the 2nd shader array as
unavailable.

When ending a debug session, re-enable the 2nd shader array per
shader engine.

User CU masking per queue cannot be guaranteed to remain functional
if requested during debugging (e.g. user cu mask requests only 2nd shader
array as an available resource leading to zero HW resources available)
nor can runtime be alerted of any of these changes during execution.

Make user CU masking and debugging mutual exclusive with respect to
availability.

If the debugger tries to attach to a process with a user cu masked
queue, return the runtime status as enabled but busy.

If the debugger tries to attach and fails to reallocate queue waves to
the first shader array of each shader engine, return the runtime status
as enabled but with an error.

In addition, like any other mutli-process debug supported devices,
disable trap temporary setup per-process to avoid performance impact from
setup overhead.

Signed-off-by: default avatarJonathan Kim <jonathan.kim@amd.com>
Reviewed-by: default avatarFelix Kuehling <felix.kuehling@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 21889582
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -219,6 +219,8 @@ struct mes_add_queue_input {
	uint32_t        gws_size;
	uint64_t	tba_addr;
	uint64_t	tma_addr;
	uint32_t	trap_en;
	uint32_t	skip_process_ctx_clear;
	uint32_t	is_kfd_process;
	uint32_t	is_aql_queue;
	uint32_t	queue_size;
+2 −5
Original line number Diff line number Diff line
@@ -202,17 +202,14 @@ static int mes_v11_0_add_hw_queue(struct amdgpu_mes *mes,
	mes_add_queue_pkt.gws_size = input->gws_size;
	mes_add_queue_pkt.trap_handler_addr = input->tba_addr;
	mes_add_queue_pkt.tma_addr = input->tma_addr;
	mes_add_queue_pkt.trap_en = input->trap_en;
	mes_add_queue_pkt.skip_process_ctx_clear = input->skip_process_ctx_clear;
	mes_add_queue_pkt.is_kfd_process = input->is_kfd_process;

	/* For KFD, gds_size is re-used for queue size (needed in MES for AQL queues) */
	mes_add_queue_pkt.is_aql_queue = input->is_aql_queue;
	mes_add_queue_pkt.gds_size = input->queue_size;

	if (!(((adev->mes.sched_version & AMDGPU_MES_VERSION_MASK) >= 4) &&
		  (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(11, 0, 0)) &&
		  (adev->ip_versions[GC_HWIP][0] <= IP_VERSION(11, 0, 3))))
		mes_add_queue_pkt.trap_en = 1;

	/* For KFD, gds_size is re-used for queue size (needed in MES for AQL queues) */
	mes_add_queue_pkt.is_aql_queue = input->is_aql_queue;
	mes_add_queue_pkt.gds_size = input->queue_size;
+0 −2
Original line number Diff line number Diff line
@@ -537,8 +537,6 @@ static int kfd_ioctl_set_cu_mask(struct file *filp, struct kfd_process *p,
		goto out;
	}

	minfo.update_flag = UPDATE_FLAG_CU_MASK;

	mutex_lock(&p->mutex);

	retval = pqm_update_mqd(&p->pqm, args->queue_id, &minfo);
+57 −0
Original line number Diff line number Diff line
@@ -24,6 +24,57 @@
#include "kfd_device_queue_manager.h"
#include <linux/file.h>

static int kfd_dbg_set_queue_workaround(struct queue *q, bool enable)
{
	struct mqd_update_info minfo = {0};
	int err;

	if (!q)
		return 0;

	if (KFD_GC_VERSION(q->device) < IP_VERSION(11, 0, 0) ||
	    KFD_GC_VERSION(q->device) >= IP_VERSION(12, 0, 0))
		return 0;

	if (enable && q->properties.is_user_cu_masked)
		return -EBUSY;

	minfo.update_flag = enable ? UPDATE_FLAG_DBG_WA_ENABLE : UPDATE_FLAG_DBG_WA_DISABLE;

	q->properties.is_dbg_wa = enable;
	err = q->device->dqm->ops.update_queue(q->device->dqm, q, &minfo);
	if (err)
		q->properties.is_dbg_wa = false;

	return err;
}

static int kfd_dbg_set_workaround(struct kfd_process *target, bool enable)
{
	struct process_queue_manager *pqm = &target->pqm;
	struct process_queue_node *pqn;
	int r = 0;

	list_for_each_entry(pqn, &pqm->queues, process_queue_list) {
		r = kfd_dbg_set_queue_workaround(pqn->q, enable);
		if (enable && r)
			goto unwind;
	}

	return 0;

unwind:
	list_for_each_entry(pqn, &pqm->queues, process_queue_list)
		kfd_dbg_set_queue_workaround(pqn->q, false);

	if (enable)
		target->runtime_info.runtime_state = r == -EBUSY ?
				DEBUG_RUNTIME_STATE_ENABLED_BUSY :
				DEBUG_RUNTIME_STATE_ENABLED_ERROR;

	return r;
}

static int kfd_dbg_set_mes_debug_mode(struct kfd_process_device *pdd)
{
	uint32_t spi_dbg_cntl = pdd->spi_dbg_override | pdd->spi_dbg_launch_mode;
@@ -77,6 +128,8 @@ static void kfd_dbg_trap_deactivate(struct kfd_process *target, bool unwind, int
		else
			kfd_dbg_set_mes_debug_mode(pdd);
	}

	kfd_dbg_set_workaround(target, false);
}

int kfd_dbg_trap_disable(struct kfd_process *target)
@@ -111,6 +164,10 @@ static int kfd_dbg_trap_activate(struct kfd_process *target)
{
	int i, r = 0;

	r = kfd_dbg_set_workaround(target, true);
	if (r)
		return r;

	for (i = 0; i < target->n_pdds; i++) {
		struct kfd_process_device *pdd = target->pdds[i];

+2 −1
Original line number Diff line number Diff line
@@ -31,7 +31,8 @@ int kfd_dbg_trap_enable(struct kfd_process *target, uint32_t fd,
			uint32_t *runtime_info_size);
static inline bool kfd_dbg_is_per_vmid_supported(struct kfd_node *dev)
{
	return KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 2);
	return KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 2) ||
	       KFD_GC_VERSION(dev) >= IP_VERSION(11, 0, 0);
}

/*
Loading