From: sashiko-bot@kernel.org
To: "Tejas Upadhyay" <tejas.upadhyay@intel.com>
Cc: intel-xe@lists.freedesktop.org
Subject: Re: [PATCH V19 09/15] drm/xe/vram: Add VRAM page offline fault handler
Date: Mon, 31 Aug 2026 08:37:17 +0000 [thread overview]
Message-ID: <20260831083718.148581F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260831064942.315720-26-tejas.upadhyay@intel.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [Critical] TOCTOU race allows eviction of the BO and destruction of innocent data
- [High] Deadlock via shrinker when allocating with GFP_KERNEL under vram_mgr->lock
- [High] Unconditional BO unpin and lack of state rollback causes reference count corruption
- [High] Use-After-Free via lockless access to exec_queue pointer
- [Medium] Failed page reservations are permanently silenced, allowing continued hardware faults
- [Medium] Faulty physical pages escape offlining when their owning BO is being freed
--
commit e00d08042f6e028303a11bd3305d790b12e07011
Author: Tejas Upadhyay <tejas.upadhyay@intel.com>
Subject: drm/xe/vram: Add VRAM page offline fault handler
This commit adds core VRAM page offlining logic to handle hardware-reported
faulty physical addresses. It introduces functions to purge BOs, verify
previously processed pages, reserve faulty buddy blocks, and map addresses to
VRAM regions.
> diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
> index 1253989a8d06a..e5994c14487d3 100644
> --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
> +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
[ ... ]
> @@ -572,3 +578,263 @@ u64 xe_ttm_vram_get_avail(struct ttm_resource_manager *man)
[ ... ]
> +static int xe_ttm_vram_purge_page(struct xe_device *xe, struct xe_bo *bo)
> +{
[ ... ]
> + xe_bo_lock(bo, false);
> + q = READ_ONCE(bo->q);
> + /* Ban exec queue if BO is lrc */
> + if (q && xe_exec_queue_get_unless_zero(q)) {
[Severity: High]
Is this lockless access to the exec queue susceptible to a use-after-free?
When xe_ttm_vram_purge_page() reads the queue pointer locklessly, it appears
possible for a concurrent destruction path like xe_lrc_finish() to clear the
pointer and synchronously free the queue via xe_exec_queue_destroy().
If this thread resumes after the free but before the RCU grace period, it
might try to read the refcount of a freed object in
xe_exec_queue_get_unless_zero().
> + /* ban queue */
> + q_to_put = q;
> + }
> +
> + if (bo->purgeable.state == XE_MADV_PURGEABLE_PURGED) {
> + /* Already purged by shrinker during unlocked window — nothing to do */
> + xe_bo_unlock(bo);
> + goto out;
> + }
> +
> + xe_bo_set_purgeable_state(bo, XE_MADV_PURGEABLE_DONTNEED);
> + ttm_bo_unmap_virtual(&bo->ttm); /* nuke CPU mmap + VRAM IO mappings */
> + if (xe_bo_is_pinned(bo))
> + xe_bo_unpin(bo);
> + ret = xe_ttm_bo_purge(&bo->ttm, &ctx);
> + xe_bo_unlock(bo);
[Severity: High]
Could this unconditional unpin corrupt the reference count if the purge
operation fails?
In xe_ttm_vram_purge_page(), if the BO was concurrently pinned multiple times
(for instance, by the display subsystem), dropping a single pin leaves the
count above zero.
Consequently, xe_ttm_bo_purge() will fail during validation and return an
error. Since the state and pin count are not rolled back on this failure
path, the legitimate owner might later unpin the BO, causing an underflow
panic.
[ ... ]
> +static int xe_ttm_vram_reserve_page_at_addr(struct xe_device *xe, u64 addr,
> + struct xe_ttm_vram_mgr *vram_mgr, struct gpu_buddy *mm)
> +{
> + struct xe_ttm_vram_offline_resource *pos, *n;
> + struct xe_ttm_vram_offline_resource *nentry;
> + struct ttm_buffer_object *tbo = NULL;
> + struct xe_bo *pbo_to_put = NULL;
> + struct gpu_buddy_block *block;
> + u64 size = SZ_4K;
> + int ret = 0;
> +
> + scoped_guard(mutex, &vram_mgr->lock) {
> + if (xe_ttm_vram_page_already_processed(vram_mgr, addr))
> + return -EEXIST;
> + block = gpu_buddy_allocated_addr_to_block(mm, addr);
> + if (WARN_ON(IS_ERR(block)))
> + return PTR_ERR(block);
> +
> + nentry = kzalloc_obj(*nentry);
[Severity: High]
Will this allocation risk a direct reclaim deadlock under memory pressure?
The xe_ttm_vram_reserve_page_at_addr() function acquires vram_mgr->lock and
then performs an implicit GFP_KERNEL allocation via kzalloc_obj().
If this allocation blocks and triggers direct reclaim, the GEM shrinker could
attempt to evict a VRAM BO. That eviction path will call
xe_ttm_vram_mgr_del(), which tries to acquire the same vram_mgr->lock,
resulting in an AB-BA deadlock.
> + if (!nentry)
> + return -ENOMEM;
> + INIT_LIST_HEAD(&nentry->blocks);
> + nentry->status = XE_PAGE_RESERVE_PENDING;
> + nentry->addr = addr;
> +
> + if (block) {
> + struct xe_bo *pbo;
> +
> + if (!block->private) {
> + /* Race: another thread just reserved this block */
> + kfree(nentry);
> + return -EEXIST;
> + }
> + tbo = block->private;
> + pbo = ttm_to_xe_bo(tbo);
> +
> + /* Get reference safely - BO may have zero refcount */
> + if (!xe_bo_get_unless_zero(pbo)) {
> + kfree(nentry);
> + return -ENOENT;
> + }
[Severity: Medium]
Does returning early here allow the corrupted physical page to escape back to
the global free pool?
If xe_bo_get_unless_zero() fails in xe_ttm_vram_reserve_page_at_addr(), the
owning BO is already being destroyed.
By freeing the tracking entry and returning without recording the faulty
address in the offlined or queued lists, the memory manager might
subsequently reallocate these corrupted buddy blocks to a new, innocent BO.
[ ... ]
> + if (block) {
> + struct xe_bo *pbo = ttm_to_xe_bo(tbo);
> +
> + /*
> + * Purge BO containing address - reference held from above.
> + * Note: brief window between purge (freeing blocks) and re-reserve
> + * below. If another allocation claims the block, buddy_alloc fails
> + * and the status will be shown as failed reservation.
> + */
> + ret = xe_ttm_vram_purge_page(xe, pbo);
> + xe_bo_put(pbo);
[Severity: Critical]
Is there a race condition during the unlocked window that could lead to data
destruction?
Since vram_mgr->lock is dropped before xe_ttm_vram_purge_page() is called in
xe_ttm_vram_reserve_page_at_addr(), the memory manager might concurrently
evict this BO to system memory and reuse its VRAM blocks for a completely
different BO.
When execution resumes, xe_ttm_vram_purge_page() would blindly destroy the
original BO that now safely resides in system memory. Furthermore, the new BO
occupying the faulty VRAM wouldn't be purged, and the subsequent buddy
allocation would fail.
> + if (ret)
> + drm_warn(&xe->drm, "Purge failed at addr:0x%llx, ret:%d\n", addr, ret);
> + }
> +
> + scoped_guard(mutex, &vram_mgr->lock) {
> + ret = xe_ttm_vram_buddy_alloc(vram_mgr, addr, addr + size,
> + size, size, &nentry->blocks,
> + GPU_BUDDY_RANGE_ALLOCATION,
> + NULL, &nentry->used_visible_size);
> + if (ret) {
> + drm_warn(&xe->drm,
> + "Could not reserve page at addr:0x%llx, ret:%d\n",
> + addr, ret);
> + nentry->status = XE_PAGE_RESERVE_FAIL;
> + return ret;
> + }
[Severity: Medium]
What happens to the faulty address if xe_ttm_vram_buddy_alloc() fails?
In this error path in xe_ttm_vram_reserve_page_at_addr(), the code returns
early without removing the tracking entry from the queued_pages list.
If the hardware later faults on this exact same physical address,
xe_ttm_vram_page_already_processed() will incorrectly report it as already
handled. This permanently blacklists the faulty page from future offlining
attempts.
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831064942.315720-17-tejas.upadhyay@intel.com?part=9
next prev parent reply other threads:[~2026-08-31 8:37 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-31 6:49 [PATCH V19 00/15] Add memory page offlining support Tejas Upadhyay
2026-08-31 6:49 ` [PATCH V19 01/15] drm/xe: Link VRAM object with gpu buddy Tejas Upadhyay
2026-08-31 6:49 ` [PATCH V19 02/15] drm/xe: Link LRC BO and its execution Queue Tejas Upadhyay
2026-08-31 7:24 ` sashiko-bot
2026-08-31 6:49 ` [PATCH V19 03/15] drm/xe: Export xe_ttm_bo_purge() Tejas Upadhyay
2026-09-02 0:33 ` Matthew Brost
2026-08-31 6:49 ` [PATCH V19 04/15] drm/xe: Handle NULL resource and allow purging of VRAM pages Tejas Upadhyay
2026-08-31 6:52 ` Ghimiray, Himal Prasad
2026-08-31 7:42 ` sashiko-bot
2026-08-31 6:49 ` [PATCH V19 05/15] drm/xe/bo: Make xe_bo_is_user() public Tejas Upadhyay
2026-08-31 6:49 ` [PATCH V19 06/15] drm/xe: Guard teardown paths against purged BOs Tejas Upadhyay
2026-08-31 6:53 ` Ghimiray, Himal Prasad
2026-08-31 8:03 ` sashiko-bot
2026-09-01 5:05 ` Upadhyay, Tejas
2026-08-31 6:49 ` [PATCH V19 07/15] drm/xe/vram: Extract buddy alloc and free helpers Tejas Upadhyay
2026-08-31 8:08 ` sashiko-bot
2026-09-01 5:10 ` Upadhyay, Tejas
2026-08-31 6:49 ` [PATCH V19 08/15] drm/xe/vram: Add page offline data structures and lifecycle Tejas Upadhyay
2026-08-31 6:49 ` [PATCH V19 09/15] drm/xe/vram: Add VRAM page offline fault handler Tejas Upadhyay
2026-08-31 6:57 ` Ghimiray, Himal Prasad
2026-08-31 8:37 ` sashiko-bot [this message]
2026-09-01 5:48 ` Upadhyay, Tejas
2026-08-31 6:49 ` [PATCH V19 10/15] drm/xe/configfs: Add disable_vram_page_offline attribute Tejas Upadhyay
2026-08-31 8:45 ` sashiko-bot
2026-09-01 5:25 ` Upadhyay, Tejas
2026-08-31 6:49 ` [PATCH V19 11/15] drm/xe/ras: Cache disable_vram_page_offline policy at init Tejas Upadhyay
2026-08-31 9:02 ` sashiko-bot
2026-09-01 5:22 ` Upadhyay, Tejas
2026-08-31 6:49 ` [PATCH V19 12/15] drm/xe/vram: Check disable_vram_page_offline policy in fault handler Tejas Upadhyay
2026-08-31 6:49 ` [PATCH V19 13/15] drm/xe: Expose bad VRAM pages via debugfs Tejas Upadhyay
2026-08-31 6:55 ` Ghimiray, Himal Prasad
2026-08-31 9:18 ` sashiko-bot
2026-09-01 5:13 ` Upadhyay, Tejas
2026-08-31 6:49 ` [PATCH V19 14/15] drm/xe/uapi: Expose ban reason in EXEC_QUEUE_GET_PROPERTY_BAN Tejas Upadhyay
2026-08-31 9:40 ` sashiko-bot
2026-09-01 9:40 ` Upadhyay, Tejas
2026-08-31 6:49 ` [PATCH V19 15/15] drm/xe: Add fault-inject based VRAM page offline injection Tejas Upadhyay
2026-08-31 6:54 ` Ghimiray, Himal Prasad
2026-08-31 11:53 ` ✓ CI.KUnit: success for Add memory page offlining support (rev22) Patchwork
2026-08-31 13:28 ` ✓ Xe.CI.BAT: " Patchwork
2026-08-31 13:58 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-08-31 14:04 ` [PATCH V19 00/15] Add memory page offlining support Rodrigo Vivi
2026-08-31 14:58 ` Matthew Brost
2026-09-01 4:09 ` Upadhyay, Tejas
2026-08-31 17:44 ` ✓ CI.KUnit: success for Add memory page offlining support (rev23) Patchwork
2026-08-31 18:32 ` ✓ Xe.CI.BAT: " Patchwork
2026-08-31 22:22 ` ✗ Xe.CI.FULL: failure " 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=20260831083718.148581F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=tejas.upadhyay@intel.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