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] &&
prev 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