From: sashiko-bot@kernel.org
To: "Arvind Yadav" <arvind.yadav@intel.com>, intel-xe@lists.freedesktop.org
Subject: Re: [PATCH v2 3/3] CI-ONLY:Defer VM teardown until exec queue cleanup
Date: Fri, 13 Nov 2026 08:32:10 +0000 [thread overview]
Message-ID: <sashiko-outbox-212412@kernel.org> (raw)
In-Reply-To: <20261113073549.352746-4-arvind.yadav@intel.com>
Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [High] drm/xe: premature kill of vm->q clears PTEs of in-flight binds
- [High] drm/xe: deferred VM teardown outlives xe_pci_remove() workqueue
flush
- [Low] drm/xe: contradictory commit message and dead waitqueue in
xe_vm_close_and_put_deferred()
--
commit c496c9217a8a101f1f9d443912a6732a3a1def2a
Author: Arvind Yadav <arvind.yadav@intel.com>
CI-ONLY:Defer VM teardown until exec queue cleanup
This commit tracks the exec queues using a VM and defers tearing down VM
mappings on file close and VM destroy until asynchronous exec queue
cleanup completes.
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index e6e53912448f2..f5228c3c3ef64 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
[ ... ]
> @@ -2093,6 +2086,140 @@ void xe_vm_close_and_put(struct xe_vm *vm)
> xe_vm_put(vm);
> }
>
> +static void vm_close_work_func(struct work_struct *w)
> +{
> + struct xe_vm *vm = container_of(w, struct xe_vm, close.work);
> + struct xe_device *xe = vm->xe;
> + int idx;
> +
> + /* Keep the VM and device alive until the PM and unplug guards unwind. */
> + xe_vm_get(vm);
> +
> + if (drm_dev_enter(&xe->drm, &idx)) {
> + xe_pm_runtime_get(xe);
> + xe_vm_close_and_put(vm);
> + xe_pm_runtime_put(xe);
> + drm_dev_exit(idx);
> + } else {
> + /*
> + * The device is gone. Drop the VM without a runtime PM reference.
> + * xe_vm_close() guards its own register access.
> + */
> + xe_vm_close_and_put(vm);
> + }
> +
> + xe_vm_put(vm);
> +}
> +
> +/**
> + * xe_vm_kill_bind_queues() - Kill and release the VM bind queue
> + * @vm: The VM whose bind queue should be stopped
> + *
> + * Callers must serialize teardown of @vm. Later calls are harmless because
> + * the first call clears the VM bind queue pointer.
> + */
> +void xe_vm_kill_bind_queues(struct xe_vm *vm)
> +{
> + struct xe_exec_queue *q;
> + int i;
> +
> + if (!vm->q)
> + return;
> +
> + down_write(&vm->lock);
> + q = vm->q;
> + vm->q = NULL;
> + xe_exec_queue_last_fence_put(q, vm);
> + for_each_tlb_inval(q, i)
> + xe_exec_queue_tlb_inval_last_fence_put(q, vm, i);
> + up_write(&vm->lock);
> +
> + xe_exec_queue_kill(q);
> + xe_exec_queue_put(q);
> +}
[Severity: High]
Does killing vm->q before xe_vm_close() waits for pending BOOKKEEP fences
cause in-flight page-table binds on vm->q to clear PTEs instead of
populating them?
Previously, xe_vm_close_and_put() called xe_vm_close() first, which waited
on DMA_RESV_USAGE_BOOKKEEP before killing vm->q. Now xe_vm_destroy_ioctl()
and xe_file_close() call xe_vm_kill_bind_queues() while default-queue bind
jobs (queued via xe_cpu_bind_update_pgtables_job() waiting on an in-sync or
BO kernel fence) and user exec queues are still active. When a queued PT
bind job's dependencies later signal on the killed vm->q,
guc_exec_queue_run_job() passes killed_or_banned_or_wedged_or_error = true
to run_pt_job() -> xe_cpu_bind_update_pgtables_execute():
drivers/gpu/drm/xe/xe_cpu_bind.c:xe_cpu_bind_update_pgtables_execute() {
...
if (pt_op->bind && !force_clear)
ops->populate(tile, &update->pt_bo->vmap,
update);
else
ops->clear(vm, tile, &update->pt_bo->vmap,
update);
...
}
The bind job clears the page table entries and signals its completion
fence, leaving active user exec queues on the VM executing against cleared
mappings.
> +
> +/**
> + * xe_vm_add_close_queue() - Track an exec queue using the VM
> + * @vm: The VM used by the exec queue
> + *
> + * The queue is tracked until its asynchronous destruction completes.
> + */
> +void xe_vm_add_close_queue(struct xe_vm *vm)
> +{
> + atomic_inc(&vm->close.num_exec_queues);
> +}
> +
> +/**
> + * xe_vm_remove_close_queue() - Stop tracking an exec queue
> + * @vm: The VM used by the exec queue
> + *
> + * If this is the last tracked queue and VM close was deferred, schedule
> + * the deferred VM close.
> + */
> +void xe_vm_remove_close_queue(struct xe_vm *vm)
> +{
> + bool queue_close = false;
> +
> + if (!atomic_dec_and_test(&vm->close.num_exec_queues))
> + return;
> +
> + wake_up_all(&vm->close.wq);
> +
> + spin_lock(&vm->close.lock);
> + if (vm->close.deferred) {
> + vm->close.deferred = false;
> + queue_close = true;
> + }
> + spin_unlock(&vm->close.lock);
> +
> + if (queue_close)
> + xe_destroy_wq_queue(&vm->close.work);
> +}
[Severity: High]
Can deferred VM close and destruction outlive xe_pci_remove() when
xe_file_close() defers teardown onto xe_destroy_wq?
Because xe_file_close() passes a zero timeout to
xe_vm_close_and_put_deferred(), closing a DRM file returns while VMs remain
open with pinned page-table BOs and active userptr/SVM DMA mappings. When
the last exec queue is freed from a worker on xe_destroy_wq,
xe_vm_remove_close_queue() queues vm->close.work onto xe_destroy_wq, and
vm_close_work_func() -> xe_vm_put() -> xe_vm_free() then queues
vm->destroy_work onto xe_destroy_wq.
During PCI removal, xe_pci_remove() runs xe_bo_pci_dev_remove_all() inside
xe_device_remove() before flushing xe_destroy_wq, and then calls
xe_destroy_wq_flush() (a single flush_workqueue() call, which only waits
for work already queued at the start of the flush, not chain-queued work
items). As a result, vm_close_work_func() and vm_destroy_work_func() can
run after xe_bo_pci_dev_remove_all(), xe_pm_fini(), pci_dma_cleanup() and
devres teardown have already completed.
> +
> +/**
> + * xe_vm_close_and_put_deferred() - Close a VM immediately or defer the close
> + * @vm: The VM reference to consume
> + * @timeout: Maximum time to wait for VM queues, in jiffies
> + *
> + * The VM must already be marked closing, and callers must serialize teardown.
> + * Release the VM-owned bind queues before waiting for queue cleanup. Callers
> + * may release them earlier to start cleanup for several VMs before waiting.
> + *
> + * If queues remain after @timeout, keep the mappings and finish VM close
> + * after the last tracked queue is freed. This consumes the caller's VM
> + * reference on both the immediate and deferred paths.
> + *
> + * Return: %true if VM close was deferred, or %false if it completed now.
> + */
> +bool xe_vm_close_and_put_deferred(struct xe_vm *vm, unsigned long timeout)
> +{
> + bool queue_close = false;
> +
> + /* Drop VM-owned queue references before waiting for their final free. */
> + xe_vm_kill_bind_queues(vm);
> +
> + if (!atomic_read(&vm->close.num_exec_queues) ||
> + wait_event_timeout(vm->close.wq,
> + !atomic_read(&vm->close.num_exec_queues),
> + timeout)) {
> + xe_vm_close_and_put(vm);
> + return false;
> + }
[Severity: Low]
This isn't a runtime bug, but both callers of
xe_vm_close_and_put_deferred() (xe_file_close() and xe_vm_destroy_ioctl())
pass timeout = 0, so wait_event_timeout() never waits and vm->close.wq and
the timeout parameter are unused. Also, the fourth paragraph of the commit
message still states that file close uses a five-second wait budget across
all VMs while holding the runtime-PM reference, contradicting the later
paragraphs and the v3 code.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261113073549.352746-1-arvind.yadav@intel.com?part=3
next prev parent reply other threads:[~2026-11-13 8:32 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 7:35 [PATCH v2 0/3] CI-ONLY Fix VM teardown and migration queue recovery Arvind Yadav
2026-11-13 7:35 ` [PATCH v2 1/3] CI_ONLY: Hold a device reference across deferred VM Arvind Yadav
2026-11-13 7:48 ` sashiko-bot
2026-11-13 7:35 ` [PATCH v2 2/3] CI_ONLY Mark VMs as closing before queue cleanup Arvind Yadav
2026-11-13 7:51 ` sashiko-bot
2026-11-13 7:35 ` [PATCH v2 3/3] CI-ONLY:Defer VM teardown until exec " Arvind Yadav
2026-11-13 8:32 ` sashiko-bot [this message]
2026-11-13 7:43 ` ✗ CI.checkpatch: warning for CI-ONLY Fix VM teardown and migration queue recovery (rev2) Patchwork
2026-11-13 7:45 ` ✓ CI.KUnit: success " Patchwork
2026-11-13 8:16 ` ✓ Xe.CI.BAT: " Patchwork
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=sashiko-outbox-212412@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=arvind.yadav@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=sashiko-reviews@lists.linux.dev \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.