mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 02:17:36 -04:00
drm/xe/pt: prevent invalid cursor access for purged BOs
During a page table walk for binding, xe_pt_stage_bind() explicitly
skips initializing the xe_res_cursor for purged BOs, treating them
similarly to NULL VMAs by only setting the cursor size.
However, xe_pt_hugepte_possible() and xe_pt_scan_64K() did not check
if the BO was purged before attempting to walk the cursor using
xe_res_dma() and xe_res_next(). Because the cursor was left
uninitialized for purged BOs, this falls through and triggers
warnings like:
WARNING: drivers/gpu/drm/xe/xe_res_cursor.h:274 at xe_res_next
Fix this by explicitly checking if the BO is purged in both
xe_pt_hugepte_possible() and xe_pt_scan_64K(), returning early just
as we do for NULL VMAs, avoiding the invalid cursor accesses entirely.
As a precaution, also zero-initialize the cursor in xe_pt_stage_bind()
to ensure we don't pass garbage data into the page table walkers
if we ever hit a similar edge case in the future.
Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/8418
Fixes: ad9843aac9 ("drm/xe/madvise: Implement purgeable buffer object support")
Assisted-by: Copilot:gemini-3.1-pro-preview
Reported-by: Matthew Schwartz <matthew.schwartz@linux.dev>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Arvind Yadav <arvind.yadav@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Tested-by: Matthew Schwartz <matthew.schwartz@linux.dev>
Link: https://patch.msgid.link/20260625152054.450125-8-matthew.auld@intel.com
(cherry picked from commit 4c7b9c6ece32440e5a435a92076d049450cd2d2e)
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
This commit is contained in:
committed by
Thomas Hellström
parent
b5c55015d4
commit
8a0fb57675
@@ -433,6 +433,7 @@ xe_pt_insert_entry(struct xe_pt_stage_bind_walk *xe_walk, struct xe_pt *parent,
|
||||
static bool xe_pt_hugepte_possible(u64 addr, u64 next, unsigned int level,
|
||||
struct xe_pt_stage_bind_walk *xe_walk)
|
||||
{
|
||||
struct xe_bo *bo = xe_vma_bo(xe_walk->vma);
|
||||
u64 size, dma;
|
||||
|
||||
if (level > MAX_HUGEPTE_LEVEL)
|
||||
@@ -446,8 +447,8 @@ static bool xe_pt_hugepte_possible(u64 addr, u64 next, unsigned int level,
|
||||
if (next - xe_walk->va_curs_start > xe_walk->curs->size)
|
||||
return false;
|
||||
|
||||
/* null VMA's do not have dma addresses */
|
||||
if (xe_vma_is_null(xe_walk->vma))
|
||||
/* null VMA's and purged BO's do not have dma addresses */
|
||||
if (xe_vma_is_null(xe_walk->vma) || (bo && xe_bo_is_purged(bo)))
|
||||
return true;
|
||||
|
||||
/* if we are clearing page table, no dma addresses*/
|
||||
@@ -468,6 +469,7 @@ static bool xe_pt_hugepte_possible(u64 addr, u64 next, unsigned int level,
|
||||
static bool
|
||||
xe_pt_scan_64K(u64 addr, u64 next, struct xe_pt_stage_bind_walk *xe_walk)
|
||||
{
|
||||
struct xe_bo *bo = xe_vma_bo(xe_walk->vma);
|
||||
struct xe_res_cursor curs = *xe_walk->curs;
|
||||
|
||||
if (!IS_ALIGNED(addr, SZ_64K))
|
||||
@@ -476,8 +478,8 @@ xe_pt_scan_64K(u64 addr, u64 next, struct xe_pt_stage_bind_walk *xe_walk)
|
||||
if (next > xe_walk->l0_end_addr)
|
||||
return false;
|
||||
|
||||
/* null VMA's do not have dma addresses */
|
||||
if (xe_vma_is_null(xe_walk->vma))
|
||||
/* null VMA's and purged BO's do not have dma addresses */
|
||||
if (xe_vma_is_null(xe_walk->vma) || (bo && xe_bo_is_purged(bo)))
|
||||
return true;
|
||||
|
||||
xe_res_next(&curs, addr - xe_walk->va_curs_start);
|
||||
@@ -708,7 +710,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
|
||||
{
|
||||
struct xe_device *xe = tile_to_xe(tile);
|
||||
struct xe_bo *bo = xe_vma_bo(vma);
|
||||
struct xe_res_cursor curs;
|
||||
struct xe_res_cursor curs = {};
|
||||
struct xe_vm *vm = xe_vma_vm(vma);
|
||||
struct xe_pt_stage_bind_walk xe_walk = {
|
||||
.base = {
|
||||
|
||||
Reference in New Issue
Block a user