Igt-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: vitaly prosyak <vprosyak@amd.com>
To: Jesse Zhang <Jesse.Zhang@amd.com>, igt-dev@lists.freedesktop.org
Cc: Vitaly Prosyak <vitaly.prosyak@amd.com>,
	Alex Deucher <alexander.deucher@amd.com>,
	Christian Koenig <christian.koenig@amd.com>
Subject: Re: [PATCH i-g-t] tests/amdgpu/amd_deadlock: add gfx bad-opcode non-zero-count reset test
Date: Wed, 29 Jul 2026 21:15:50 -0400	[thread overview]
Message-ID: <84aceadf-b76c-4237-b666-7e47d59485cb@amd.com> (raw)
In-Reply-To: <20260729063923.892313-1-Jesse.Zhang@amd.com>

LGTM

Reviewed-by Vitaly Prosyak  <vitaly.prosyak@amd.com>

On 2026-07-29 02:38, Jesse Zhang wrote:
> Add amdgpu-gfx-priv-fault-badcount-umq: a gfx user-queue bad opcode (0xf2)
> whose PACKET3 header carries a non-zero count field but no body. The pipe HW
> cannot find the packet end and stalls mid-packet, so a per-queue (vmid) reset
> cannot recover it -- only a gfx pipe reset can (once that FW support lands).
> Until then the case escalates to a full GPU reset.
>
> Add a priv_fault_badcount_hang IP-block hook to emit the packet.
>
> Signed-off-by: Jesse Zhang <jesse.zhang@amd.com>
> ---
>  lib/amdgpu/amd_deadlock_helpers.c | 80 +++++++++++++++++++++++++++++++
>  lib/amdgpu/amd_deadlock_helpers.h |  4 ++
>  lib/amdgpu/amd_ip_blocks.h        | 11 +++++
>  lib/amdgpu/amd_ip_blocks_ex.c     | 24 ++++++++++
>  tests/amdgpu/amd_deadlock.c       |  9 ++++
>  5 files changed, 128 insertions(+)
>
> diff --git a/lib/amdgpu/amd_deadlock_helpers.c b/lib/amdgpu/amd_deadlock_helpers.c
> index 71c82aa91..1ce46422f 100644
> --- a/lib/amdgpu/amd_deadlock_helpers.c
> +++ b/lib/amdgpu/amd_deadlock_helpers.c
> @@ -529,6 +529,16 @@ static void gfx_ring_emit_priv_inst_hang(
>  	ring_context->pm4_dw = i;
>  }
>  
> +static void gfx_ring_emit_priv_fault_badcount_hang(
> +	const struct amdgpu_ip_block_version *ip_block,
> +	struct amdgpu_ring_context *ring_context)
> +{
> +	uint32_t i = 0;
> +
> +	ip_block->funcs->priv_fault_badcount_hang(ip_block->funcs, ring_context, &i);
> +	ring_context->pm4_dw = i;
> +}
> +
>  /*
>   * Fault a user queue with an invalid opcode followed by an endless wait: the
>   * bad opcode raises the gfx priv-fault interrupt and the wait hangs the queue
> @@ -600,6 +610,76 @@ void amdgpu_priv_fault_ring_helper(amdgpu_device_handle device_handle, unsigned
>  	}
>  }
>  
> +/*
> + * Fault a user queue with a bad opcode carrying a non-zero count field and no
> + * body: the pipe HW cannot find the packet end and stalls mid-packet, so a
> + * per-queue (vmid) reset cannot recover it -- only a gfx pipe reset can (once
> + * that FW support is ready). Until then the case escalates to a full GPU reset.
> + */
> +void amdgpu_priv_fault_badcount_ring_helper(amdgpu_device_handle device_handle, unsigned int ip_type,
> +					    struct pci_addr *pci, bool user_queue)
> +{
> +	const struct amdgpu_ip_block_version *ip_block;
> +	const int write_length = 128;
> +	const int pm4_dw = 256;
> +	struct amdgpu_ring_context *ring_context;
> +	int r = 0;
> +
> +	ip_block = get_ip_block(device_handle, ip_type);
> +	ring_context = calloc(1, sizeof(*ring_context));
> +	igt_assert(ring_context);
> +
> +	if (user_queue) {
> +		ip_block->funcs->userq_create(device_handle, ring_context, ip_type);
> +	} else {
> +		r = amdgpu_cs_ctx_create(device_handle, &ring_context->context_handle);
> +		igt_assert_eq(r, 0);
> +	}
> +
> +	ring_context->write_length = write_length;
> +	ring_context->pm4 = calloc(pm4_dw, sizeof(*ring_context->pm4));
> +	ring_context->pm4_size = pm4_dw;
> +	ring_context->res_cnt = 1;
> +	ring_context->ring_id = 0;
> +	ring_context->user_queue = user_queue;
> +	igt_assert(ring_context->pm4);
> +
> +	r = amdgpu_bo_alloc_and_map_sync(device_handle,
> +				    ring_context->write_length * sizeof(uint32_t),
> +				    4096, AMDGPU_GEM_DOMAIN_GTT,
> +				    AMDGPU_GEM_CREATE_CPU_GTT_USWC,
> +				    AMDGPU_VM_MTYPE_UC,
> +				    &ring_context->bo,
> +				    (void **)&ring_context->bo_cpu,
> +				    &ring_context->bo_mc,
> +				    &ring_context->va_handle,
> +				    ring_context->timeline_syncobj_handle,
> +				    ++ring_context->point, user_queue);
> +	igt_assert_eq(r, 0);
> +	if (user_queue) {
> +		r = amdgpu_timeline_syncobj_wait(device_handle,
> +			ring_context->timeline_syncobj_handle,
> +			ring_context->point);
> +		igt_assert_eq(r, 0);
> +	}
> +
> +	memset((void *)ring_context->bo_cpu, 0, ring_context->write_length * sizeof(uint32_t));
> +	ring_context->resources[0] = ring_context->bo;
> +
> +	gfx_ring_emit_priv_fault_badcount_hang(ip_block, ring_context);
> +
> +	amdgpu_test_exec_cs_helper(device_handle, ip_block->type, ring_context, 0);
> +
> +	amdgpu_bo_unmap_and_free(ring_context->bo, ring_context->va_handle, ring_context->bo_mc,
> +				 ring_context->write_length * sizeof(uint32_t));
> +	if (user_queue) {
> +		ip_block->funcs->userq_destroy(device_handle, ring_context, ip_type);
> +	} else {
> +		free(ring_context->pm4);
> +		free(ring_context);
> +	}
> +}
> +
>  /*
>   * Fault a user queue with a privileged INDIRECT_BUFFER (priv-instruction fault)
>   * followed by an endless wait: the privileged IB launch raises a fault interrupt
> diff --git a/lib/amdgpu/amd_deadlock_helpers.h b/lib/amdgpu/amd_deadlock_helpers.h
> index 69c321ef6..0fd5eb59a 100644
> --- a/lib/amdgpu/amd_deadlock_helpers.h
> +++ b/lib/amdgpu/amd_deadlock_helpers.h
> @@ -42,6 +42,10 @@ void
>  amdgpu_priv_fault_ring_helper(amdgpu_device_handle device_handle, unsigned int ip_type,
>  			      struct pci_addr *pci, bool user_queue);
>  
> +void
> +amdgpu_priv_fault_badcount_ring_helper(amdgpu_device_handle device_handle, unsigned int ip_type,
> +				       struct pci_addr *pci, bool user_queue);
> +
>  void
>  amdgpu_priv_inst_ring_helper(amdgpu_device_handle device_handle, unsigned int ip_type,
>  			     struct pci_addr *pci, bool user_queue);
> diff --git a/lib/amdgpu/amd_ip_blocks.h b/lib/amdgpu/amd_ip_blocks.h
> index 427010c2d..40a9735be 100644
> --- a/lib/amdgpu/amd_ip_blocks.h
> +++ b/lib/amdgpu/amd_ip_blocks.h
> @@ -460,6 +460,17 @@ struct amdgpu_ip_funcs {
>  		uint32_t *pm4_dw
>  	);
>  
> +	/*
> +	 * Emit a bad opcode with a non-zero count field and no body: the pipe HW
> +	 * cannot find the packet end and stalls mid-packet, so a per-queue (vmid)
> +	 * reset cannot recover it -- only a gfx pipe reset can.
> +	 */
> +	int (*priv_fault_badcount_hang)(
> +		const struct amdgpu_ip_funcs *func,
> +		const struct amdgpu_ring_context *context,
> +		uint32_t *pm4_dw
> +	);
> +
>  };
>  
>  extern const struct amdgpu_ip_block_version gfx_v6_0_ip_block;
> diff --git a/lib/amdgpu/amd_ip_blocks_ex.c b/lib/amdgpu/amd_ip_blocks_ex.c
> index 4655d9dcc..ad384ec33 100644
> --- a/lib/amdgpu/amd_ip_blocks_ex.c
> +++ b/lib/amdgpu/amd_ip_blocks_ex.c
> @@ -228,6 +228,10 @@ static int gfx_ring_priv_inst_hang(const struct amdgpu_ip_funcs *func,
>  				   const struct amdgpu_ring_context *ring_context,
>  				   uint32_t *pm4_dw);
>  
> +static int gfx_ring_priv_fault_badcount_hang(const struct amdgpu_ip_funcs *func,
> +					     const struct amdgpu_ring_context *ring_context,
> +					     uint32_t *pm4_dw);
> +
>  void amd_ip_blocks_ex_init(struct amdgpu_ip_funcs *funcs)
>  {
>  	funcs->gfx_program_compute = gfx_program_compute_default;
> @@ -240,6 +244,7 @@ void amd_ip_blocks_ex_init(struct amdgpu_ip_funcs *funcs)
>  	funcs->wait_reg_mem_hang = gfx_ring_wait_reg_mem_hang;
>  	funcs->priv_fault_hang = gfx_ring_priv_fault_hang;
>  	funcs->priv_inst_hang = gfx_ring_priv_inst_hang;
> +	funcs->priv_fault_badcount_hang = gfx_ring_priv_fault_badcount_hang;
>  
>  	switch (funcs->family_id) {
>  	case AMDGPU_FAMILY_RV:
> @@ -358,3 +363,22 @@ gfx_ring_priv_fault_hang(const struct amdgpu_ip_funcs *func,
>  	return 0;
>  }
>  
> +/*
> + * Emit a bad opcode (0xf2) with a non-zero count field and no body: the header
> + * claims a body that is never submitted, so the pipe HW cannot find the packet
> + * end and stalls mid-packet. A per-queue (vmid) reset cannot process it; only a
> + * gfx pipe reset can (once that FW support is ready).
> + */
> +static int
> +gfx_ring_priv_fault_badcount_hang(const struct amdgpu_ip_funcs *func,
> +				  const struct amdgpu_ring_context *ring_context,
> +				  uint32_t *pm4_dw)
> +{
> +	uint32_t i = *pm4_dw;
> +
> +	ring_context->pm4[i++] = PACKET3(0xf2, 0x3fff);
> +	*pm4_dw = i;
> +
> +	return 0;
> +}
> +
> diff --git a/tests/amdgpu/amd_deadlock.c b/tests/amdgpu/amd_deadlock.c
> index 1d729eeb4..d66a58859 100644
> --- a/tests/amdgpu/amd_deadlock.c
> +++ b/tests/amdgpu/amd_deadlock.c
> @@ -265,6 +265,15 @@ int igt_main()
>  		}
>  	}
>  
> +	igt_describe("Test-gfx-user-queue-bad-opcode-with-nonzero-count-recovers-via-gfx-pipe-reset");
> +	igt_subtest_with_dynamic("amdgpu-gfx-priv-fault-badcount-umq") {
> +		if (enable_test && userq_arr_cap[AMD_IP_GFX] &&
> +			is_reset_enable(AMD_IP_GFX, AMDGPU_RESET_TYPE_PER_QUEUE, &pci)) {
> +			igt_dynamic_f("amdgpu-gfx-priv-fault-badcount-umq")
> +			amdgpu_priv_fault_badcount_ring_helper(device, AMDGPU_HW_IP_GFX, &pci, true);
> +		}
> +	}
> +
>  	igt_describe("Test-per-queue-reset-recovery-of-a-gfx-user-queue-privileged-instruction-fault");
>  	igt_subtest_with_dynamic("amdgpu-gfx-priv-inst-umq") {
>  		if (enable_test && userq_arr_cap[AMD_IP_GFX] &&

      parent reply	other threads:[~2026-07-30  1:16 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-29  6:38 [PATCH i-g-t] tests/amdgpu/amd_deadlock: add gfx bad-opcode non-zero-count reset test Jesse Zhang
2026-07-29  7:45 ` ✓ i915.CI.BAT: success for " Patchwork
2026-07-29  8:35 ` ✓ Xe.CI.FULL: " Patchwork
2026-07-29 10:01 ` ✗ i915.CI.Full: failure " Patchwork
2026-07-30  1:15 ` vitaly prosyak [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=84aceadf-b76c-4237-b666-7e47d59485cb@amd.com \
    --to=vprosyak@amd.com \
    --cc=Jesse.Zhang@amd.com \
    --cc=alexander.deucher@amd.com \
    --cc=christian.koenig@amd.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=vitaly.prosyak@amd.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox