On Thu, Jun 18, 2026 at 04:08:58PM +0800, Honglei Huang wrote: > From: Honglei Huang <[email protected]> > > drm_gpusvm_pages_flags currently mixes two status: > - MM / virtual-address state: whether the range has been (partially) > unmapped by the Linux MM, these follow the lifetime of the VMA and > are a single per VA range fact. > - Device mapping state: has_devmem_pages and has_dma_mapping, > which describe the current page mapping status held by device > itself. > > Keeping both on the pages object blurs the semantics of the > abstraction of pages and VA range. So move the MM state flags onto the > range, and keep drm_gpusvm_pages_flags strictly for mapping state. > > - Introduce drm_gpusvm_range_flags { migrate_devmem, unmapped, > partial_unmap } on drm_gpusvm_range. > - Shrink drm_gpusvm_pages_flags to just has_devmem_pages and > has_dma_mapping. > > Side effect: drivers now need to check the unmap flags in the driver > itself to avoid handling the unmapped pages. > > Mirror that bit onto drm_gpusvm_pages so the framework can > still short circuit drm_gpusvm_get_pages() under the notifier lock, and > make drm_gpusvm_range_set_unmapped() propagate it to the backing pages. > This follows Matt's review fixup for the v0 series; see the Link below. > > Suggested-by: Matthew Brost <[email protected]>
Reviewed-by: Matthew Brost <[email protected]> > Link: > https://gitlab.freedesktop.org/mbrost/xe-kernel-driver-svn-perf-6-15-2025/-/commit/623f6a50c037d9e44f6c9fbe6859a0ba7ad50177 > Signed-off-by: Honglei Huang <[email protected]> > --- > drivers/gpu/drm/drm_gpusvm.c | 21 ++++++++++++++++++--- > drivers/gpu/drm/xe/xe_svm.c | 11 ++++++----- > include/drm/drm_gpusvm.h | 30 +++++++++++++++++++++++++----- > 3 files changed, 49 insertions(+), 13 deletions(-) > > diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c > index 958cb605aed..df900553f21 100644 > --- a/drivers/gpu/drm/drm_gpusvm.c > +++ b/drivers/gpu/drm/drm_gpusvm.c > @@ -641,7 +641,7 @@ drm_gpusvm_range_alloc(struct drm_gpusvm *gpusvm, > range->itree.last = ALIGN(fault_addr + 1, chunk_size) - 1; > INIT_LIST_HEAD(&range->entry); > range->pages.notifier_seq = LONG_MAX; > - range->pages.flags.migrate_devmem = migrate_devmem ? 1 : 0; > + range->flags.migrate_devmem = migrate_devmem ? 1 : 0; > > return range; > } > @@ -1784,20 +1784,35 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_has_mapping); > /** > * drm_gpusvm_range_set_unmapped() - Mark a GPU SVM range as unmapped > * @range: Pointer to the GPU SVM range structure. > + * @pages: Pointer to the GPU SVM pages structure(s). > + * @pages_count: Number of GPU SVM pages structure(s) passed in. > * @mmu_range: Pointer to the MMU notifier range structure. > * > * This function marks a GPU SVM range as unmapped and sets the > partial_unmap flag > * if the range partially falls within the provided MMU notifier range. > */ > void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range, > + struct drm_gpusvm_pages *pages, > + unsigned int pages_count, > const struct mmu_notifier_range *mmu_range) > { > + unsigned int i; > + > lockdep_assert_held_write(&range->gpusvm->notifier_lock); > > - range->pages.flags.unmapped = true; > + range->flags.unmapped = true; > + for (i = 0; i < pages_count; ++i) { > + struct drm_gpusvm_pages_flags flags = { > + .__flags = pages[i].flags.__flags, > + }; > + > + flags.unmapped = true; > + /* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */ > + WRITE_ONCE(pages[i].flags.__flags, flags.__flags); > + } > if (drm_gpusvm_range_start(range) < mmu_range->start || > drm_gpusvm_range_end(range) > mmu_range->end) > - range->pages.flags.partial_unmap = true; > + range->flags.partial_unmap = true; > } > EXPORT_SYMBOL_GPL(drm_gpusvm_range_set_unmapped); > > diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c > index e1651e70c8f..63da149f3b7 100644 > --- a/drivers/gpu/drm/xe/xe_svm.c > +++ b/drivers/gpu/drm/xe/xe_svm.c > @@ -134,7 +134,8 @@ xe_svm_garbage_collector_add_range(struct xe_vm *vm, > struct xe_svm_range *range, > > range_debug(range, "GARBAGE COLLECTOR ADD"); > > - drm_gpusvm_range_set_unmapped(&range->base, mmu_range); > + drm_gpusvm_range_set_unmapped(&range->base, &range->base.pages, 1, > + mmu_range); > > spin_lock(&vm->svm.garbage_collector.lock); > if (list_empty(&range->garbage_collector_link)) > @@ -166,7 +167,7 @@ xe_svm_range_notifier_event_begin(struct xe_vm *vm, > struct drm_gpusvm_range *r, > range_debug(range, "NOTIFIER"); > > /* Skip if already unmapped or if no binding exist */ > - if (range->base.pages.flags.unmapped || !range->tile_present) > + if (range->base.flags.unmapped || !range->tile_present) > return 0; > > range_debug(range, "NOTIFIER - EXECUTE"); > @@ -1136,7 +1137,7 @@ bool xe_svm_range_needs_migrate_to_vram(struct > xe_svm_range *range, struct xe_vm > struct xe_vm *vm = range_to_vm(&range->base); > u64 range_size = xe_svm_range_size(range); > > - if (!range->base.pages.flags.migrate_devmem || !dpagemap) > + if (!range->base.flags.migrate_devmem || !dpagemap) > return false; > > xe_assert(vm->xe, IS_DGFX(vm->xe)); > @@ -1248,7 +1249,7 @@ static int __xe_svm_handle_pagefault(struct xe_vm *vm, > struct xe_vma *vma, > > xe_svm_range_fault_count_stats_incr(gt, range); > > - if (ctx.devmem_only && !range->base.pages.flags.migrate_devmem) { > + if (ctx.devmem_only && !range->base.flags.migrate_devmem) { > err = -EACCES; > goto out; > } > @@ -1623,7 +1624,7 @@ int xe_svm_alloc_vram(struct xe_svm_range *range, const > struct drm_gpusvm_ctx *c > int err, retries = 1; > bool write_locked = false; > > - xe_assert(range_to_vm(&range->base)->xe, > range->base.pages.flags.migrate_devmem); > + xe_assert(range_to_vm(&range->base)->xe, > range->base.flags.migrate_devmem); > range_debug(range, "ALLOCATE VRAM"); > > migration_state = drm_gpusvm_scan_mm(&range->base, > diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h > index 8a4d7134a9a..251a7266a73 100644 > --- a/include/drm/drm_gpusvm.h > +++ b/include/drm/drm_gpusvm.h > @@ -109,9 +109,7 @@ struct drm_gpusvm_notifier { > /** > * struct drm_gpusvm_pages_flags - Structure representing a GPU SVM pages > flags > * > - * @migrate_devmem: Flag indicating whether the pages can be migrated to > device memory > * @unmapped: Flag indicating if the pages has been unmapped > - * @partial_unmap: Flag indicating if the pages has been partially unmapped > * @has_devmem_pages: Flag indicating if the pages has devmem pages > * @has_dma_mapping: Flag indicating if the pages has a DMA mapping > * @__flags: Flags for pages in u16 form (used for READ_ONCE) > @@ -119,11 +117,8 @@ struct drm_gpusvm_notifier { > struct drm_gpusvm_pages_flags { > union { > struct { > - /* All flags below must be set upon creation */ > - u16 migrate_devmem : 1; > /* All flags below must be set / cleared under notifier > lock */ > u16 unmapped : 1; > - u16 partial_unmap : 1; > u16 has_devmem_pages : 1; > u16 has_dma_mapping : 1; > }; > @@ -151,6 +146,27 @@ struct drm_gpusvm_pages { > struct drm_gpusvm_pages_flags flags; > }; > > +/** > + * struct drm_gpusvm_range_flags - Range-level GPU SVM flags > + * > + * @migrate_devmem: Flag indicating whether the range can be migrated to > device memory > + * @unmapped: Flag indicating if the range has been unmapped > + * @partial_unmap: Flag indicating if the range has been partially unmapped > + * @__flags: All flags in u16 form (used for READ_ONCE) > + */ > +struct drm_gpusvm_range_flags { > + union { > + struct { > + /* All flags below must be set upon creation */ > + u16 migrate_devmem : 1; > + /* All flags below must be set / cleared under notifier > lock */ > + u16 unmapped : 1; > + u16 partial_unmap : 1; > + }; > + u16 __flags; > + }; > +}; > + > /** > * struct drm_gpusvm_range - Structure representing a GPU SVM range > * > @@ -160,6 +176,7 @@ struct drm_gpusvm_pages { > * @itree: Interval tree node for the range (inserted in GPU SVM notifier) > * @entry: List entry to fast interval tree traversal > * @pages: The pages for this range. > + * @flags: Flags for range see &struct drm_gpusvm_range_flags > * > * This structure represents a GPU SVM range used for tracking memory ranges > * mapped in a DRM device. > @@ -171,6 +188,7 @@ struct drm_gpusvm_range { > struct interval_tree_node itree; > struct list_head entry; > struct drm_gpusvm_pages pages; > + struct drm_gpusvm_range_flags flags; > }; > > /** > @@ -310,6 +328,8 @@ drm_gpusvm_range_find(struct drm_gpusvm_notifier > *notifier, unsigned long start, > unsigned long end); > > void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range, > + struct drm_gpusvm_pages *pages, > + unsigned int pages_count, > const struct mmu_notifier_range *mmu_range); > > int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm, > -- > 2.34.1 >
