xe_gem_object_free() calls __xe_bo_vunmap() without holding the BO
reservation. The last GEM reference does not exclude TTM eviction,
which takes a separate reference on the TTM BO.

Eviction can free the resource while ttm_bo_kunmap() is using it.
ttm_mem_io_free() can then clear bus.addr and bus.offset in the freed
resource. This is consistent with the 16 zeroed bytes reported by
SLUB for a resource freed by xe_ttm_vram_mgr_del() during eviction.

Move the final unmap to xe_ttm_bo_release_notify(). It runs when the
TTM BO refcount reaches zero, so eviction and swapout can no longer
take a reference, and before TTM frees the resource and backing pages.

Also unmap real Xe BOs under the reservation lock in xe_bo_shrink().
When the GEM refcount is already zero, the shrinker can purge the BO
without calling xe_bo_move_notify(). Unmapping before the reclaim
branches prevents pages from being freed while the kernel mapping
remains active, including for BOs already in SYSTEM placement.
Skip TTM ghost objects, which do not contain the Xe mapping fields.

v2:
 - Unmap real Xe BOs under the reservation lock before shrinking.
   (Sashiko)

Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
Cc: Matthew Brost <[email protected]>
Cc: Thomas Hellström <[email protected]>
Cc: Himal Prasad Ghimiray <[email protected]>
Cc: Rodrigo Vivi <[email protected]>
Signed-off-by: Arvind Yadav <[email protected]>
---
 drivers/gpu/drm/xe/xe_bo.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index 42a6aa1a2e4a..0793ed59a90a 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -1454,6 +1454,10 @@ long xe_bo_shrink(struct ttm_operation_ctx *ctx, struct 
ttm_buffer_object *bo,
        if (!xe_bo_eviction_valuable(bo, &place))
                return -EBUSY;
 
+       /* Shrinking can free pages without calling xe_bo_move_notify(). */
+       if (xe_bo_is_xe_bo(bo))
+               xe_bo_vunmap(xe_bo);
+
        if (!xe_bo_is_xe_bo(bo) || !xe_bo_get_unless_zero(xe_bo))
                return xe_bo_shrink_purge(ctx, bo, scanned);
 
@@ -1866,6 +1870,12 @@ static void xe_ttm_bo_release_notify(struct 
ttm_buffer_object *ttm_bo)
        bo = ttm_to_xe_bo(ttm_bo);
        xe_assert(xe_bo_device(bo), !(bo->created && 
kref_read(&ttm_bo->base.refcount)));
 
+       /*
+        * The TTM BO refcount is zero, so eviction and swapout cannot
+        * take a reference. Unmap before TTM frees the backing store.
+        */
+       __xe_bo_vunmap(bo);
+
        if (!xe_ttm_bo_lock_in_destructor(ttm_bo))
                return;
 
@@ -2056,7 +2066,6 @@ static void xe_gem_object_free(struct drm_gem_object *obj)
         * driver ttm callbacks is allowed to use the ttm_buffer_object
         * refcount directly if needed.
         */
-       __xe_bo_vunmap(gem_to_xe_bo(obj));
        ttm_bo_fini(container_of(obj, struct ttm_buffer_object, base));
 }
 
-- 
2.43.0

Reply via email to