From: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
To: Matthew Brost <matthew.brost@intel.com>, intel-xe@lists.freedesktop.org
Cc: himal.prasad.ghimiray@intel.com
Subject: Re: [PATCH v4] drm/xe: Make VMA tile_present, tile_invalidated access rules clear
Date: Tue, 03 Jun 2025 12:06:46 +0200 [thread overview]
Message-ID: <ca525dc1e2be1e69e06b22fd446996e43b2d7f38.camel@linux.intel.com> (raw)
In-Reply-To: <20250602164412.1912293-1-matthew.brost@intel.com>
On Mon, 2025-06-02 at 09:44 -0700, Matthew Brost wrote:
> Document VMA tile_invalidated access rules, use READ_ONCE /
> WRITE_ONCE
> for opportunistic checks of tile_present and tile_invalidated, move
> tile_invalidated state change from page fault handler to PT code
> under
> the correct locks, and add lockdep asserts to TLB invalidation paths.
>
> v2:
> - Assert VM dma-resv lock rather than BO in zap PTEs
> v3:
> - Back to BO's dma-resv lock, adjust documentation
> v4:
> - Add WRITE_ONCE in xe_vm_invalidate_vma (Thomas)
> - Change lockdep assert for userptr in xe_vm_invalidate_vma (CI)
> - Take userptr notifier lock in read mode in xe_vm_userptr_pin
> before
> calling xe_vm_invalidate_vma (CI)
>
> Signed-off-by: Matthew Brost <matthew.brost@intel.com>
> Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> ---
> drivers/gpu/drm/xe/xe_gt_pagefault.c | 11 +++++++----
> drivers/gpu/drm/xe/xe_pt.c | 16 +++++++++++++---
> drivers/gpu/drm/xe/xe_vm.c | 19 +++++++++++++++----
> drivers/gpu/drm/xe/xe_vm_types.h | 11 +++++++++--
> 4 files changed, 44 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c
> b/drivers/gpu/drm/xe/xe_gt_pagefault.c
> index 7a8f87709e39..05fbc83c64b7 100644
> --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
> +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
> @@ -68,8 +68,12 @@ static bool access_is_atomic(enum access_type
> access_type)
>
> static bool vma_is_valid(struct xe_tile *tile, struct xe_vma *vma)
> {
> - return BIT(tile->id) & vma->tile_present &&
> - !(BIT(tile->id) & vma->tile_invalidated);
> + /*
> + * Advisory only check whether the VMA currently has a valid
> mapping,
> + * READ_ONCE pairs with WRITE_ONCE in xe_pt.c
> + */
> + return BIT(tile->id) & READ_ONCE(vma->tile_present) &&
> + !(BIT(tile->id) & READ_ONCE(vma->tile_invalidated));
> }
>
>
> @@ -121,7 +125,7 @@ static int handle_vma_pagefault(struct xe_gt *gt,
> struct xe_vma *vma,
>
> trace_xe_vma_pagefault(vma);
>
> - /* Check if VMA is valid */
> + /* Check if VMA is valid, opportunistic check only */
> if (vma_is_valid(tile, vma) && !atomic)
> return 0;
>
> @@ -158,7 +162,6 @@ static int handle_vma_pagefault(struct xe_gt *gt,
> struct xe_vma *vma,
>
> dma_fence_wait(fence, false);
> dma_fence_put(fence);
> - vma->tile_invalidated &= ~BIT(tile->id);
>
> unlock_dma_resv:
> drm_exec_fini(&exec);
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index c9c41fbe125c..f39d5cc9f411 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -907,6 +907,11 @@ bool xe_pt_zap_ptes(struct xe_tile *tile, struct
> xe_vma *vma)
> struct xe_pt *pt = xe_vma_vm(vma)->pt_root[tile->id];
> u8 pt_mask = (vma->tile_present & ~vma->tile_invalidated);
>
> + if (xe_vma_bo(vma))
> + xe_bo_assert_held(xe_vma_bo(vma));
> + else if (xe_vma_is_userptr(vma))
> + lockdep_assert_held(&xe_vma_vm(vma)-
> >userptr.notifier_lock);
> +
> if (!(pt_mask & BIT(tile->id)))
> return false;
>
> @@ -2191,10 +2196,15 @@ static void bind_op_commit(struct xe_vm *vm,
> struct xe_tile *tile,
> DMA_RESV_USAGE_KERNEL :
> DMA_RESV_USAGE_BOOKKEEP);
> }
> - vma->tile_present |= BIT(tile->id);
> - vma->tile_staged &= ~BIT(tile->id);
> + /* All WRITE_ONCE pair with READ_ONCE in xe_gt_pagefault.c
> */
> + WRITE_ONCE(vma->tile_present, vma->tile_present | BIT(tile-
> >id));
> if (invalidate_on_bind)
> - vma->tile_invalidated |= BIT(tile->id);
> + WRITE_ONCE(vma->tile_invalidated,
> + vma->tile_invalidated | BIT(tile->id));
> + else
> + WRITE_ONCE(vma->tile_invalidated,
> + vma->tile_invalidated & ~BIT(tile->id));
> + vma->tile_staged &= ~BIT(tile->id);
> if (xe_vma_is_userptr(vma)) {
> lockdep_assert_held_read(&vm-
> >userptr.notifier_lock);
> to_userptr_vma(vma)->userptr.initial_bind = true;
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 7140d8856bad..18f967ce1f1a 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -732,7 +732,9 @@ int xe_vm_userptr_pin(struct xe_vm *vm)
>
> DMA_RESV_USAGE_BOOKKEEP,
> false,
> MAX_SCHEDULE_TIMEOUT);
>
> + down_read(&vm->userptr.notifier_lock);
> err = xe_vm_invalidate_vma(&uvma->vma);
> + up_read(&vm->userptr.notifier_lock);
Hm. Why are we calling xe_vm_invalidate_vma() here to begin with? Isn't
the reason we end up here that the userptr was already invalidated?
> xe_vm_unlock(vm);
> if (err)
> break;
> @@ -3853,6 +3855,7 @@ void xe_vm_unlock(struct xe_vm *vm)
> int xe_vm_invalidate_vma(struct xe_vma *vma)
> {
> struct xe_device *xe = xe_vma_vm(vma)->xe;
> + struct xe_vm *vm = xe_vma_vm(vma);
> struct xe_tile *tile;
> struct xe_gt_tlb_invalidation_fence
> fence[XE_MAX_TILES_PER_DEVICE * XE_MAX_GT_PER_TILE];
> @@ -3864,17 +3867,24 @@ int xe_vm_invalidate_vma(struct xe_vma *vma)
> xe_assert(xe, !xe_vma_is_cpu_addr_mirror(vma));
> trace_xe_vma_invalidate(vma);
>
> - vm_dbg(&xe_vma_vm(vma)->xe->drm,
> + vm_dbg(&vm->xe->drm,
> "INVALIDATE: addr=0x%016llx, range=0x%016llx",
> xe_vma_start(vma), xe_vma_size(vma));
>
> - /* Check that we don't race with page-table updates */
> + /*
> + * Check that we don't race with page-table updates,
> tile_invalidated
> + * update is safe
> + */
> if (IS_ENABLED(CONFIG_PROVE_LOCKING)) {
> if (xe_vma_is_userptr(vma)) {
> + lockdep_assert(lockdep_is_held_type(&vm-
> >userptr.notifier_lock, 0) ||
> + (lockdep_is_held_type(&vm-
> >userptr.notifier_lock, 1) &&
> + lockdep_is_held(&xe_vm_resv(
> vm)->lock.base)));
> +
> WARN_ON_ONCE(!mmu_interval_check_retry
> (&to_userptr_vma(vma)-
> >userptr.notifier,
> to_userptr_vma(vma)-
> >userptr.notifier_seq));
> -
> WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)),
> + WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_r
> esv(vm),
>
> DMA_RESV_USAGE_BOOKKEEP));
>
> } else {
> @@ -3914,7 +3924,8 @@ int xe_vm_invalidate_vma(struct xe_vma *vma)
> for (id = 0; id < fence_id; ++id)
> xe_gt_tlb_invalidation_fence_wait(&fence[id]);
>
> - vma->tile_invalidated = vma->tile_mask;
> + /* WRITE_ONCE pair with READ_ONCE in xe_gt_pagefault.c */
> + WRITE_ONCE(vma->tile_invalidated, vma->tile_mask);
>
> return ret;
> }
> diff --git a/drivers/gpu/drm/xe/xe_vm_types.h
> b/drivers/gpu/drm/xe/xe_vm_types.h
> index 0e1318a15c9e..4275f71a74dd 100644
> --- a/drivers/gpu/drm/xe/xe_vm_types.h
> +++ b/drivers/gpu/drm/xe/xe_vm_types.h
> @@ -100,14 +100,21 @@ struct xe_vma {
> struct work_struct destroy_work;
> };
>
> - /** @tile_invalidated: VMA has been invalidated */
> + /**
> + * @tile_invalidated: Tile mask of binding are invalidated
> for this VMA.
> + * protected by BO's resv and for userptrs, vm-
> >userptr.notifier_lock in
> + * write mode for writing or vm->userptr.notifier_lock in
> read mode and
> + * the vm->resv. For stable reading, BO's resv or useptr
s/userptr/useptr/
> + * vm->userptr.notifier_lock in read mode is required. Can
> be
> + * opportunisticly read with READ_ONCE outside of locks.
opportunistically
> + */
> u8 tile_invalidated;
>
> /** @tile_mask: Tile mask of where to create binding for
> this VMA */
> u8 tile_mask;
>
> /**
> - * @tile_present: GT mask of binding are present for this
> VMA.
> + * @tile_present: Tile mask of binding are present for this
> VMA.
> * protected by vm->lock, vm->resv and for userptrs,
> * vm->userptr.notifier_lock for writing. Needs either for
> reading,
> * but if reading is done under the vm->lock only, it needs
> to be held
Otherwise RB holds.
/Thomas
next prev parent reply other threads:[~2025-06-03 10:07 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-02 16:44 [PATCH v4] drm/xe: Make VMA tile_present, tile_invalidated access rules clear Matthew Brost
2025-06-02 16:47 ` ✓ CI.Patch_applied: success for drm/xe: Make VMA tile_present, tile_invalidated access rules clear (rev4) Patchwork
2025-06-02 16:47 ` ✓ CI.checkpatch: " Patchwork
2025-06-02 16:49 ` ✓ CI.KUnit: " Patchwork
2025-06-02 16:59 ` ✓ CI.Build: " Patchwork
2025-06-02 17:02 ` ✓ CI.Hooks: " Patchwork
2025-06-02 17:03 ` ✓ CI.checksparse: " Patchwork
2025-06-03 5:45 ` ✓ Xe.CI.BAT: " Patchwork
2025-06-03 7:45 ` ✗ Xe.CI.Full: failure " Patchwork
2025-06-03 10:06 ` Thomas Hellström [this message]
2025-06-03 16:31 ` [PATCH v4] drm/xe: Make VMA tile_present, tile_invalidated access rules clear Matthew Brost
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=ca525dc1e2be1e69e06b22fd446996e43b2d7f38.camel@linux.intel.com \
--to=thomas.hellstrom@linux.intel.com \
--cc=himal.prasad.ghimiray@intel.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=matthew.brost@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 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.