* [PATCH v2 1/7] drm/gpusvm: fix hmm_pfn_to_map_order() usage
2025-03-28 18:10 [PATCH v2 0/7] Replace xe_hmm with gpusvm Matthew Auld
@ 2025-03-28 18:10 ` Matthew Auld
2025-03-28 18:10 ` [PATCH v2 2/7] drm/gpusvm: use more selective dma dir in get_pages() Matthew Auld
` (8 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Matthew Auld @ 2025-03-28 18:10 UTC (permalink / raw)
To: intel-xe; +Cc: dri-devel, Thomas Hellström, Matthew Brost
Handle the case where the hmm range partially covers a huge page (like
2M), otherwise we can potentially end up doing something nasty like
mapping memory which is outside the range, and maybe not even mapped by
the mm. Fix is based on the xe userptr code, which in a future patch
will directly use gpusvm, so needs alignment here.
v2:
- Add kernel-doc (Matt B)
- s/fls/ilog2/ (Thomas)
Reported-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
drivers/gpu/drm/drm_gpusvm.c | 33 +++++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index 2451c816edd5..07dda042624c 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -817,6 +817,35 @@ drm_gpusvm_range_alloc(struct drm_gpusvm *gpusvm,
return range;
}
+/**
+ * drm_gpusvm_hmm_pfn_to_order() - Get the largest CPU mapping order.
+ * @hmm_pfn: The current hmm_pfn.
+ * @hmm_pfn_index: Index of the @hmm_pfn within the pfn array.
+ * @npages: Number of pages within the pfn array i.e the hmm range size.
+ *
+ * To allow skipping PFNs with the same flags (like when they belong to
+ * the same huge PTE) when looping over the pfn array, take a given a hmm_pfn,
+ * and return the largest order that will fit inside the CPU PTE, but also
+ * crucially accounting for the original hmm range boundaries.
+ *
+ * Return: The largest order that will safely fit within the size of the hmm_pfn
+ * CPU PTE.
+ */
+static unsigned int drm_gpusvm_hmm_pfn_to_order(unsigned long hmm_pfn,
+ unsigned long hmm_pfn_index,
+ unsigned long npages)
+{
+ unsigned long size;
+
+ size = 1UL << hmm_pfn_to_map_order(hmm_pfn);
+ size -= (hmm_pfn & ~HMM_PFN_FLAGS) & (size - 1);
+ hmm_pfn_index += size;
+ if (hmm_pfn_index > npages)
+ size -= (hmm_pfn_index - npages);
+
+ return ilog2(size);
+}
+
/**
* drm_gpusvm_check_pages() - Check pages
* @gpusvm: Pointer to the GPU SVM structure
@@ -875,7 +904,7 @@ static bool drm_gpusvm_check_pages(struct drm_gpusvm *gpusvm,
err = -EFAULT;
goto err_free;
}
- i += 0x1 << hmm_pfn_to_map_order(pfns[i]);
+ i += 0x1 << drm_gpusvm_hmm_pfn_to_order(pfns[i], i, npages);
}
err_free:
@@ -1408,7 +1437,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
for (i = 0, j = 0; i < npages; ++j) {
struct page *page = hmm_pfn_to_page(pfns[i]);
- order = hmm_pfn_to_map_order(pfns[i]);
+ order = drm_gpusvm_hmm_pfn_to_order(pfns[i], i, npages);
if (is_device_private_page(page) ||
is_device_coherent_page(page)) {
if (zdd != page->zone_device_data && i > 0) {
--
2.48.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v2 2/7] drm/gpusvm: use more selective dma dir in get_pages()
2025-03-28 18:10 [PATCH v2 0/7] Replace xe_hmm with gpusvm Matthew Auld
2025-03-28 18:10 ` [PATCH v2 1/7] drm/gpusvm: fix hmm_pfn_to_map_order() usage Matthew Auld
@ 2025-03-28 18:10 ` Matthew Auld
2025-03-28 18:10 ` [PATCH v2 3/7] drm/gpusvm: pull out drm_gpusvm_pages substructure Matthew Auld
` (7 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Matthew Auld @ 2025-03-28 18:10 UTC (permalink / raw)
To: intel-xe; +Cc: dri-devel, Thomas Hellström, Matthew Brost
If we are only reading the memory then from the device pov the direction
can be DMA_TO_DEVICE. This aligns with the xe-userptr code. Using the
most restrictive data direction to represent the access is normally a
good idea.
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>
Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
drivers/gpu/drm/drm_gpusvm.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index 07dda042624c..e0c8d450752a 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -1363,6 +1363,8 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
int err = 0;
struct dev_pagemap *pagemap;
struct drm_pagemap *dpagemap;
+ enum dma_data_direction dma_dir = ctx->read_only ? DMA_TO_DEVICE :
+ DMA_BIDIRECTIONAL;
retry:
hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
@@ -1467,7 +1469,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
dpagemap->ops->device_map(dpagemap,
gpusvm->drm->dev,
page, order,
- DMA_BIDIRECTIONAL);
+ dma_dir);
if (dma_mapping_error(gpusvm->drm->dev,
range->dma_addr[j].addr)) {
err = -EFAULT;
@@ -1486,7 +1488,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
addr = dma_map_page(gpusvm->drm->dev,
page, 0,
PAGE_SIZE << order,
- DMA_BIDIRECTIONAL);
+ dma_dir);
if (dma_mapping_error(gpusvm->drm->dev, addr)) {
err = -EFAULT;
goto err_unmap;
@@ -1494,7 +1496,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
range->dma_addr[j] = drm_pagemap_device_addr_encode
(addr, DRM_INTERCONNECT_SYSTEM, order,
- DMA_BIDIRECTIONAL);
+ dma_dir);
}
i += 1 << order;
num_dma_mapped = i;
--
2.48.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v2 3/7] drm/gpusvm: pull out drm_gpusvm_pages substructure
2025-03-28 18:10 [PATCH v2 0/7] Replace xe_hmm with gpusvm Matthew Auld
2025-03-28 18:10 ` [PATCH v2 1/7] drm/gpusvm: fix hmm_pfn_to_map_order() usage Matthew Auld
2025-03-28 18:10 ` [PATCH v2 2/7] drm/gpusvm: use more selective dma dir in get_pages() Matthew Auld
@ 2025-03-28 18:10 ` Matthew Auld
2025-04-03 21:15 ` Matthew Brost
2025-03-28 18:10 ` [PATCH v2 4/7] drm/gpusvm: refactor core API to use pages struct Matthew Auld
` (6 subsequent siblings)
9 siblings, 1 reply; 19+ messages in thread
From: Matthew Auld @ 2025-03-28 18:10 UTC (permalink / raw)
To: intel-xe; +Cc: dri-devel, Matthew Brost, Thomas Hellström
Pull the pages stuff from the svm range into its own substructure, with
the idea of having the main pages related routines, like get_pages(),
unmap_pages() and free_pages() all operating on some lower level
structures, which can then be re-used for stuff like userptr.
v2:
- Move seq into pages struct (Matt B)
Suggested-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
drivers/gpu/drm/drm_gpusvm.c | 66 ++++++++++++++++++++----------------
drivers/gpu/drm/xe/xe_pt.c | 2 +-
drivers/gpu/drm/xe/xe_svm.c | 8 ++---
drivers/gpu/drm/xe/xe_svm.h | 6 ++--
include/drm/drm_gpusvm.h | 53 +++++++++++++++++------------
5 files changed, 76 insertions(+), 59 deletions(-)
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index e0c8d450752a..c3d70403fbcc 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -811,8 +811,8 @@ drm_gpusvm_range_alloc(struct drm_gpusvm *gpusvm,
range->itree.start = ALIGN_DOWN(fault_addr, chunk_size);
range->itree.last = ALIGN(fault_addr + 1, chunk_size) - 1;
INIT_LIST_HEAD(&range->entry);
- range->notifier_seq = LONG_MAX;
- range->flags.migrate_devmem = migrate_devmem ? 1 : 0;
+ range->pages.notifier_seq = LONG_MAX;
+ range->pages.flags.migrate_devmem = migrate_devmem ? 1 : 0;
return range;
}
@@ -1140,15 +1140,16 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
struct drm_gpusvm_range *range,
unsigned long npages)
{
- unsigned long i, j;
- struct drm_pagemap *dpagemap = range->dpagemap;
+ struct drm_gpusvm_pages *svm_pages = &range->pages;
+ struct drm_pagemap *dpagemap = svm_pages->dpagemap;
struct device *dev = gpusvm->drm->dev;
+ unsigned long i, j;
lockdep_assert_held(&gpusvm->notifier_lock);
- if (range->flags.has_dma_mapping) {
+ if (svm_pages->flags.has_dma_mapping) {
for (i = 0, j = 0; i < npages; j++) {
- struct drm_pagemap_device_addr *addr = &range->dma_addr[j];
+ struct drm_pagemap_device_addr *addr = &svm_pages->dma_addr[j];
if (addr->proto == DRM_INTERCONNECT_SYSTEM)
dma_unmap_page(dev,
@@ -1160,9 +1161,9 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
dev, *addr);
i += 1 << addr->order;
}
- range->flags.has_devmem_pages = false;
- range->flags.has_dma_mapping = false;
- range->dpagemap = NULL;
+ svm_pages->flags.has_devmem_pages = false;
+ svm_pages->flags.has_dma_mapping = false;
+ svm_pages->dpagemap = NULL;
}
}
@@ -1176,11 +1177,13 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
static void drm_gpusvm_range_free_pages(struct drm_gpusvm *gpusvm,
struct drm_gpusvm_range *range)
{
+ struct drm_gpusvm_pages *svm_pages = &range->pages;
+
lockdep_assert_held(&gpusvm->notifier_lock);
- if (range->dma_addr) {
- kvfree(range->dma_addr);
- range->dma_addr = NULL;
+ if (svm_pages->dma_addr) {
+ kvfree(svm_pages->dma_addr);
+ svm_pages->dma_addr = NULL;
}
}
@@ -1291,9 +1294,11 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_range_put);
bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
struct drm_gpusvm_range *range)
{
+ struct drm_gpusvm_pages *svm_pages = &range->pages;
+
lockdep_assert_held(&gpusvm->notifier_lock);
- return range->flags.has_devmem_pages || range->flags.has_dma_mapping;
+ return svm_pages->flags.has_devmem_pages || svm_pages->flags.has_dma_mapping;
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);
@@ -1311,9 +1316,10 @@ static bool
drm_gpusvm_range_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
struct drm_gpusvm_range *range)
{
+ struct drm_gpusvm_pages *svm_pages = &range->pages;
bool pages_valid;
- if (!range->dma_addr)
+ if (!svm_pages->dma_addr)
return false;
drm_gpusvm_notifier_lock(gpusvm);
@@ -1340,6 +1346,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
struct drm_gpusvm_range *range,
const struct drm_gpusvm_ctx *ctx)
{
+ struct drm_gpusvm_pages *svm_pages = &range->pages;
struct mmu_interval_notifier *notifier = &range->notifier->notifier;
struct hmm_range hmm_range = {
.default_flags = HMM_PFN_REQ_FAULT | (ctx->read_only ? 0 :
@@ -1409,7 +1416,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
*/
drm_gpusvm_notifier_lock(gpusvm);
- if (range->flags.unmapped) {
+ if (svm_pages->flags.unmapped) {
drm_gpusvm_notifier_unlock(gpusvm);
err = -EFAULT;
goto err_free;
@@ -1421,13 +1428,12 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
goto retry;
}
- if (!range->dma_addr) {
+ if (!svm_pages->dma_addr) {
/* Unlock and restart mapping to allocate memory. */
drm_gpusvm_notifier_unlock(gpusvm);
- range->dma_addr = kvmalloc_array(npages,
- sizeof(*range->dma_addr),
- GFP_KERNEL);
- if (!range->dma_addr) {
+ svm_pages->dma_addr =
+ kvmalloc_array(npages, sizeof(*svm_pages->dma_addr), GFP_KERNEL);
+ if (!svm_pages->dma_addr) {
err = -ENOMEM;
goto err_free;
}
@@ -1465,13 +1471,13 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
goto err_unmap;
}
}
- range->dma_addr[j] =
+ svm_pages->dma_addr[j] =
dpagemap->ops->device_map(dpagemap,
gpusvm->drm->dev,
page, order,
dma_dir);
if (dma_mapping_error(gpusvm->drm->dev,
- range->dma_addr[j].addr)) {
+ svm_pages->dma_addr[j].addr)) {
err = -EFAULT;
goto err_unmap;
}
@@ -1494,7 +1500,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
goto err_unmap;
}
- range->dma_addr[j] = drm_pagemap_device_addr_encode
+ svm_pages->dma_addr[j] = drm_pagemap_device_addr_encode
(addr, DRM_INTERCONNECT_SYSTEM, order,
dma_dir);
}
@@ -1502,16 +1508,16 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
num_dma_mapped = i;
}
- range->flags.has_dma_mapping = true;
+ svm_pages->flags.has_dma_mapping = true;
if (zdd) {
- range->flags.has_devmem_pages = true;
- range->dpagemap = dpagemap;
+ svm_pages->flags.has_devmem_pages = true;
+ svm_pages->dpagemap = dpagemap;
}
drm_gpusvm_notifier_unlock(gpusvm);
kvfree(pfns);
set_seqno:
- range->notifier_seq = hmm_range.notifier_seq;
+ svm_pages->notifier_seq = hmm_range.notifier_seq;
return 0;
@@ -1718,7 +1724,7 @@ int drm_gpusvm_migrate_to_devmem(struct drm_gpusvm *gpusvm,
mmap_assert_locked(gpusvm->mm);
- if (!range->flags.migrate_devmem)
+ if (!range->pages.flags.migrate_devmem)
return -EINVAL;
if (!ops->populate_devmem_pfn || !ops->copy_to_devmem ||
@@ -2247,10 +2253,10 @@ void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range,
{
lockdep_assert_held_write(&range->gpusvm->notifier_lock);
- range->flags.unmapped = true;
+ range->pages.flags.unmapped = true;
if (drm_gpusvm_range_start(range) < mmu_range->start ||
drm_gpusvm_range_end(range) > mmu_range->end)
- range->flags.partial_unmap = true;
+ range->pages.flags.partial_unmap = true;
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_set_unmapped);
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 82ae159feed1..9ac9291baeac 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -701,7 +701,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
return -EAGAIN;
}
if (xe_svm_range_has_dma_mapping(range)) {
- xe_res_first_dma(range->base.dma_addr, 0,
+ xe_res_first_dma(range->base.pages.dma_addr, 0,
range->base.itree.last + 1 - range->base.itree.start,
&curs);
xe_svm_range_debug(range, "BIND PREPARE - MIXED");
diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
index c7424c824a14..be077766fd73 100644
--- a/drivers/gpu/drm/xe/xe_svm.c
+++ b/drivers/gpu/drm/xe/xe_svm.c
@@ -17,7 +17,7 @@
static bool xe_svm_range_in_vram(struct xe_svm_range *range)
{
/* Not reliable without notifier lock */
- return range->base.flags.has_devmem_pages;
+ return range->base.pages.flags.has_devmem_pages;
}
static bool xe_svm_range_has_vram_binding(struct xe_svm_range *range)
@@ -59,7 +59,7 @@ static unsigned long xe_svm_range_size(struct xe_svm_range *range)
(r__)->base.gpusvm, \
xe_svm_range_in_vram((r__)) ? 1 : 0, \
xe_svm_range_has_vram_binding((r__)) ? 1 : 0, \
- (r__)->base.notifier_seq, \
+ (r__)->base.pages.notifier_seq, \
xe_svm_range_start((r__)), xe_svm_range_end((r__)), \
xe_svm_range_size((r__)))
@@ -135,7 +135,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.flags.unmapped || !range->tile_present)
+ if (range->base.pages.flags.unmapped || !range->tile_present)
return 0;
range_debug(range, "NOTIFIER - EXECUTE");
@@ -783,7 +783,7 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma,
range_debug(range, "PAGE FAULT");
/* XXX: Add migration policy, for now migrate range once */
- if (!range->skip_migrate && range->base.flags.migrate_devmem &&
+ if (!range->skip_migrate && range->base.pages.flags.migrate_devmem &&
xe_svm_range_size(range) >= SZ_64K) {
range->skip_migrate = true;
diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
index 3d441eb1f7ea..8bc83de87250 100644
--- a/drivers/gpu/drm/xe/xe_svm.h
+++ b/drivers/gpu/drm/xe/xe_svm.h
@@ -84,7 +84,7 @@ void xe_svm_range_debug(struct xe_svm_range *range, const char *operation);
static inline bool xe_svm_range_has_dma_mapping(struct xe_svm_range *range)
{
lockdep_assert_held(&range->base.gpusvm->notifier_lock);
- return range->base.flags.has_dma_mapping;
+ return range->base.pages.flags.has_dma_mapping;
}
#define xe_svm_assert_in_notifier(vm__) \
@@ -112,7 +112,9 @@ struct xe_vram_region;
struct xe_svm_range {
struct {
struct interval_tree_node itree;
- const struct drm_pagemap_device_addr *dma_addr;
+ struct {
+ struct drm_pagemap_device_addr *dma_addr;
+ } pages;
} base;
u32 tile_present;
u32 tile_invalidated;
diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h
index df120b4d1f83..1b7ed4f4a8e2 100644
--- a/include/drm/drm_gpusvm.h
+++ b/include/drm/drm_gpusvm.h
@@ -185,6 +185,35 @@ struct drm_gpusvm_notifier {
} flags;
};
+/**
+ * struct drm_gpusvm_pages - Structure representing a GPU SVM mapped pages
+ *
+ * @dma_addr: Device address array
+ * @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping.
+ * Note this is assuming only one drm_pagemap per range is allowed.
+ * @notifier_seq: Notifier sequence number of the range's pages
+ * @flags: Flags for range
+ * @flags.migrate_devmem: Flag indicating whether the range can be migrated to device memory
+ * @flags.unmapped: Flag indicating if the range has been unmapped
+ * @flags.partial_unmap: Flag indicating if the range has been partially unmapped
+ * @flags.has_devmem_pages: Flag indicating if the range has devmem pages
+ * @flags.has_dma_mapping: Flag indicating if the range has a DMA mapping
+ */
+struct drm_gpusvm_pages {
+ struct drm_pagemap_device_addr *dma_addr;
+ struct drm_pagemap *dpagemap;
+ unsigned long notifier_seq;
+ 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;
+ } flags;
+};
+
/**
* struct drm_gpusvm_range - Structure representing a GPU SVM range
*
@@ -193,16 +222,7 @@ struct drm_gpusvm_notifier {
* @refcount: Reference count for the range
* @itree: Interval tree node for the range (inserted in GPU SVM notifier)
* @entry: List entry to fast interval tree traversal
- * @notifier_seq: Notifier sequence number of the range's pages
- * @dma_addr: Device address array
- * @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping.
- * Note this is assuming only one drm_pagemap per range is allowed.
- * @flags: Flags for range
- * @flags.migrate_devmem: Flag indicating whether the range can be migrated to device memory
- * @flags.unmapped: Flag indicating if the range has been unmapped
- * @flags.partial_unmap: Flag indicating if the range has been partially unmapped
- * @flags.has_devmem_pages: Flag indicating if the range has devmem pages
- * @flags.has_dma_mapping: Flag indicating if the range has a DMA mapping
+ * @pages: The pages for this range.
*
* This structure represents a GPU SVM range used for tracking memory ranges
* mapped in a DRM device.
@@ -213,18 +233,7 @@ struct drm_gpusvm_range {
struct kref refcount;
struct interval_tree_node itree;
struct list_head entry;
- unsigned long notifier_seq;
- struct drm_pagemap_device_addr *dma_addr;
- struct drm_pagemap *dpagemap;
- 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;
- } flags;
+ struct drm_gpusvm_pages pages;
};
/**
--
2.48.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v2 3/7] drm/gpusvm: pull out drm_gpusvm_pages substructure
2025-03-28 18:10 ` [PATCH v2 3/7] drm/gpusvm: pull out drm_gpusvm_pages substructure Matthew Auld
@ 2025-04-03 21:15 ` Matthew Brost
0 siblings, 0 replies; 19+ messages in thread
From: Matthew Brost @ 2025-04-03 21:15 UTC (permalink / raw)
To: Matthew Auld; +Cc: intel-xe, dri-devel, Thomas Hellström
On Fri, Mar 28, 2025 at 06:10:32PM +0000, Matthew Auld wrote:
> Pull the pages stuff from the svm range into its own substructure, with
> the idea of having the main pages related routines, like get_pages(),
> unmap_pages() and free_pages() all operating on some lower level
> structures, which can then be re-used for stuff like userptr.
>
> v2:
> - Move seq into pages struct (Matt B)
>
> Suggested-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> ---
> drivers/gpu/drm/drm_gpusvm.c | 66 ++++++++++++++++++++----------------
> drivers/gpu/drm/xe/xe_pt.c | 2 +-
> drivers/gpu/drm/xe/xe_svm.c | 8 ++---
> drivers/gpu/drm/xe/xe_svm.h | 6 ++--
> include/drm/drm_gpusvm.h | 53 +++++++++++++++++------------
> 5 files changed, 76 insertions(+), 59 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
> index e0c8d450752a..c3d70403fbcc 100644
> --- a/drivers/gpu/drm/drm_gpusvm.c
> +++ b/drivers/gpu/drm/drm_gpusvm.c
> @@ -811,8 +811,8 @@ drm_gpusvm_range_alloc(struct drm_gpusvm *gpusvm,
> range->itree.start = ALIGN_DOWN(fault_addr, chunk_size);
> range->itree.last = ALIGN(fault_addr + 1, chunk_size) - 1;
> INIT_LIST_HEAD(&range->entry);
> - range->notifier_seq = LONG_MAX;
> - range->flags.migrate_devmem = migrate_devmem ? 1 : 0;
> + range->pages.notifier_seq = LONG_MAX;
> + range->pages.flags.migrate_devmem = migrate_devmem ? 1 : 0;
>
> return range;
> }
> @@ -1140,15 +1140,16 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
> struct drm_gpusvm_range *range,
> unsigned long npages)
> {
> - unsigned long i, j;
> - struct drm_pagemap *dpagemap = range->dpagemap;
> + struct drm_gpusvm_pages *svm_pages = &range->pages;
> + struct drm_pagemap *dpagemap = svm_pages->dpagemap;
> struct device *dev = gpusvm->drm->dev;
> + unsigned long i, j;
>
> lockdep_assert_held(&gpusvm->notifier_lock);
>
> - if (range->flags.has_dma_mapping) {
> + if (svm_pages->flags.has_dma_mapping) {
> for (i = 0, j = 0; i < npages; j++) {
> - struct drm_pagemap_device_addr *addr = &range->dma_addr[j];
> + struct drm_pagemap_device_addr *addr = &svm_pages->dma_addr[j];
>
> if (addr->proto == DRM_INTERCONNECT_SYSTEM)
> dma_unmap_page(dev,
> @@ -1160,9 +1161,9 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
> dev, *addr);
> i += 1 << addr->order;
> }
> - range->flags.has_devmem_pages = false;
> - range->flags.has_dma_mapping = false;
> - range->dpagemap = NULL;
> + svm_pages->flags.has_devmem_pages = false;
> + svm_pages->flags.has_dma_mapping = false;
> + svm_pages->dpagemap = NULL;
> }
> }
>
> @@ -1176,11 +1177,13 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
> static void drm_gpusvm_range_free_pages(struct drm_gpusvm *gpusvm,
> struct drm_gpusvm_range *range)
> {
> + struct drm_gpusvm_pages *svm_pages = &range->pages;
> +
> lockdep_assert_held(&gpusvm->notifier_lock);
>
> - if (range->dma_addr) {
> - kvfree(range->dma_addr);
> - range->dma_addr = NULL;
> + if (svm_pages->dma_addr) {
> + kvfree(svm_pages->dma_addr);
> + svm_pages->dma_addr = NULL;
> }
> }
>
> @@ -1291,9 +1294,11 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_range_put);
> bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
> struct drm_gpusvm_range *range)
> {
> + struct drm_gpusvm_pages *svm_pages = &range->pages;
> +
> lockdep_assert_held(&gpusvm->notifier_lock);
>
> - return range->flags.has_devmem_pages || range->flags.has_dma_mapping;
> + return svm_pages->flags.has_devmem_pages || svm_pages->flags.has_dma_mapping;
> }
> EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);
>
> @@ -1311,9 +1316,10 @@ static bool
> drm_gpusvm_range_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
> struct drm_gpusvm_range *range)
> {
> + struct drm_gpusvm_pages *svm_pages = &range->pages;
> bool pages_valid;
>
> - if (!range->dma_addr)
> + if (!svm_pages->dma_addr)
> return false;
>
> drm_gpusvm_notifier_lock(gpusvm);
> @@ -1340,6 +1346,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
> struct drm_gpusvm_range *range,
> const struct drm_gpusvm_ctx *ctx)
> {
> + struct drm_gpusvm_pages *svm_pages = &range->pages;
> struct mmu_interval_notifier *notifier = &range->notifier->notifier;
> struct hmm_range hmm_range = {
> .default_flags = HMM_PFN_REQ_FAULT | (ctx->read_only ? 0 :
> @@ -1409,7 +1416,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
> */
> drm_gpusvm_notifier_lock(gpusvm);
>
> - if (range->flags.unmapped) {
> + if (svm_pages->flags.unmapped) {
> drm_gpusvm_notifier_unlock(gpusvm);
> err = -EFAULT;
> goto err_free;
> @@ -1421,13 +1428,12 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
> goto retry;
> }
>
> - if (!range->dma_addr) {
> + if (!svm_pages->dma_addr) {
> /* Unlock and restart mapping to allocate memory. */
> drm_gpusvm_notifier_unlock(gpusvm);
> - range->dma_addr = kvmalloc_array(npages,
> - sizeof(*range->dma_addr),
> - GFP_KERNEL);
> - if (!range->dma_addr) {
> + svm_pages->dma_addr =
> + kvmalloc_array(npages, sizeof(*svm_pages->dma_addr), GFP_KERNEL);
> + if (!svm_pages->dma_addr) {
> err = -ENOMEM;
> goto err_free;
> }
> @@ -1465,13 +1471,13 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
> goto err_unmap;
> }
> }
> - range->dma_addr[j] =
> + svm_pages->dma_addr[j] =
> dpagemap->ops->device_map(dpagemap,
> gpusvm->drm->dev,
> page, order,
> dma_dir);
> if (dma_mapping_error(gpusvm->drm->dev,
> - range->dma_addr[j].addr)) {
> + svm_pages->dma_addr[j].addr)) {
> err = -EFAULT;
> goto err_unmap;
> }
> @@ -1494,7 +1500,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
> goto err_unmap;
> }
>
> - range->dma_addr[j] = drm_pagemap_device_addr_encode
> + svm_pages->dma_addr[j] = drm_pagemap_device_addr_encode
> (addr, DRM_INTERCONNECT_SYSTEM, order,
> dma_dir);
> }
> @@ -1502,16 +1508,16 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
> num_dma_mapped = i;
> }
>
> - range->flags.has_dma_mapping = true;
> + svm_pages->flags.has_dma_mapping = true;
> if (zdd) {
> - range->flags.has_devmem_pages = true;
> - range->dpagemap = dpagemap;
> + svm_pages->flags.has_devmem_pages = true;
> + svm_pages->dpagemap = dpagemap;
> }
>
> drm_gpusvm_notifier_unlock(gpusvm);
> kvfree(pfns);
> set_seqno:
> - range->notifier_seq = hmm_range.notifier_seq;
> + svm_pages->notifier_seq = hmm_range.notifier_seq;
>
> return 0;
>
> @@ -1718,7 +1724,7 @@ int drm_gpusvm_migrate_to_devmem(struct drm_gpusvm *gpusvm,
>
> mmap_assert_locked(gpusvm->mm);
>
> - if (!range->flags.migrate_devmem)
> + if (!range->pages.flags.migrate_devmem)
> return -EINVAL;
>
> if (!ops->populate_devmem_pfn || !ops->copy_to_devmem ||
> @@ -2247,10 +2253,10 @@ void drm_gpusvm_range_set_unmapped(struct drm_gpusvm_range *range,
> {
> lockdep_assert_held_write(&range->gpusvm->notifier_lock);
>
> - range->flags.unmapped = true;
> + range->pages.flags.unmapped = true;
> if (drm_gpusvm_range_start(range) < mmu_range->start ||
> drm_gpusvm_range_end(range) > mmu_range->end)
> - range->flags.partial_unmap = true;
> + range->pages.flags.partial_unmap = true;
> }
> EXPORT_SYMBOL_GPL(drm_gpusvm_range_set_unmapped);
>
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index 82ae159feed1..9ac9291baeac 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -701,7 +701,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
> return -EAGAIN;
> }
> if (xe_svm_range_has_dma_mapping(range)) {
> - xe_res_first_dma(range->base.dma_addr, 0,
> + xe_res_first_dma(range->base.pages.dma_addr, 0,
> range->base.itree.last + 1 - range->base.itree.start,
> &curs);
> xe_svm_range_debug(range, "BIND PREPARE - MIXED");
> diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c
> index c7424c824a14..be077766fd73 100644
> --- a/drivers/gpu/drm/xe/xe_svm.c
> +++ b/drivers/gpu/drm/xe/xe_svm.c
> @@ -17,7 +17,7 @@
> static bool xe_svm_range_in_vram(struct xe_svm_range *range)
> {
> /* Not reliable without notifier lock */
> - return range->base.flags.has_devmem_pages;
> + return range->base.pages.flags.has_devmem_pages;
> }
>
> static bool xe_svm_range_has_vram_binding(struct xe_svm_range *range)
> @@ -59,7 +59,7 @@ static unsigned long xe_svm_range_size(struct xe_svm_range *range)
> (r__)->base.gpusvm, \
> xe_svm_range_in_vram((r__)) ? 1 : 0, \
> xe_svm_range_has_vram_binding((r__)) ? 1 : 0, \
> - (r__)->base.notifier_seq, \
> + (r__)->base.pages.notifier_seq, \
> xe_svm_range_start((r__)), xe_svm_range_end((r__)), \
> xe_svm_range_size((r__)))
>
> @@ -135,7 +135,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.flags.unmapped || !range->tile_present)
> + if (range->base.pages.flags.unmapped || !range->tile_present)
> return 0;
>
> range_debug(range, "NOTIFIER - EXECUTE");
> @@ -783,7 +783,7 @@ int xe_svm_handle_pagefault(struct xe_vm *vm, struct xe_vma *vma,
> range_debug(range, "PAGE FAULT");
>
> /* XXX: Add migration policy, for now migrate range once */
> - if (!range->skip_migrate && range->base.flags.migrate_devmem &&
> + if (!range->skip_migrate && range->base.pages.flags.migrate_devmem &&
> xe_svm_range_size(range) >= SZ_64K) {
> range->skip_migrate = true;
>
> diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h
> index 3d441eb1f7ea..8bc83de87250 100644
> --- a/drivers/gpu/drm/xe/xe_svm.h
> +++ b/drivers/gpu/drm/xe/xe_svm.h
> @@ -84,7 +84,7 @@ void xe_svm_range_debug(struct xe_svm_range *range, const char *operation);
> static inline bool xe_svm_range_has_dma_mapping(struct xe_svm_range *range)
> {
> lockdep_assert_held(&range->base.gpusvm->notifier_lock);
> - return range->base.flags.has_dma_mapping;
> + return range->base.pages.flags.has_dma_mapping;
> }
>
> #define xe_svm_assert_in_notifier(vm__) \
> @@ -112,7 +112,9 @@ struct xe_vram_region;
> struct xe_svm_range {
> struct {
> struct interval_tree_node itree;
> - const struct drm_pagemap_device_addr *dma_addr;
> + struct {
> + struct drm_pagemap_device_addr *dma_addr;
> + } pages;
> } base;
> u32 tile_present;
> u32 tile_invalidated;
> diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h
> index df120b4d1f83..1b7ed4f4a8e2 100644
> --- a/include/drm/drm_gpusvm.h
> +++ b/include/drm/drm_gpusvm.h
> @@ -185,6 +185,35 @@ struct drm_gpusvm_notifier {
> } flags;
> };
>
> +/**
> + * struct drm_gpusvm_pages - Structure representing a GPU SVM mapped pages
> + *
> + * @dma_addr: Device address array
> + * @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping.
> + * Note this is assuming only one drm_pagemap per range is allowed.
> + * @notifier_seq: Notifier sequence number of the range's pages
> + * @flags: Flags for range
> + * @flags.migrate_devmem: Flag indicating whether the range can be migrated to device memory
> + * @flags.unmapped: Flag indicating if the range has been unmapped
> + * @flags.partial_unmap: Flag indicating if the range has been partially unmapped
> + * @flags.has_devmem_pages: Flag indicating if the range has devmem pages
> + * @flags.has_dma_mapping: Flag indicating if the range has a DMA mapping
> + */
> +struct drm_gpusvm_pages {
> + struct drm_pagemap_device_addr *dma_addr;
> + struct drm_pagemap *dpagemap;
> + unsigned long notifier_seq;
> + 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;
> + } flags;
> +};
> +
> /**
> * struct drm_gpusvm_range - Structure representing a GPU SVM range
> *
> @@ -193,16 +222,7 @@ struct drm_gpusvm_notifier {
> * @refcount: Reference count for the range
> * @itree: Interval tree node for the range (inserted in GPU SVM notifier)
> * @entry: List entry to fast interval tree traversal
> - * @notifier_seq: Notifier sequence number of the range's pages
> - * @dma_addr: Device address array
> - * @dpagemap: The struct drm_pagemap of the device pages we're dma-mapping.
> - * Note this is assuming only one drm_pagemap per range is allowed.
> - * @flags: Flags for range
> - * @flags.migrate_devmem: Flag indicating whether the range can be migrated to device memory
> - * @flags.unmapped: Flag indicating if the range has been unmapped
> - * @flags.partial_unmap: Flag indicating if the range has been partially unmapped
> - * @flags.has_devmem_pages: Flag indicating if the range has devmem pages
> - * @flags.has_dma_mapping: Flag indicating if the range has a DMA mapping
> + * @pages: The pages for this range.
> *
> * This structure represents a GPU SVM range used for tracking memory ranges
> * mapped in a DRM device.
> @@ -213,18 +233,7 @@ struct drm_gpusvm_range {
> struct kref refcount;
> struct interval_tree_node itree;
> struct list_head entry;
> - unsigned long notifier_seq;
> - struct drm_pagemap_device_addr *dma_addr;
> - struct drm_pagemap *dpagemap;
> - 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;
> - } flags;
> + struct drm_gpusvm_pages pages;
> };
>
> /**
> --
> 2.48.1
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2 4/7] drm/gpusvm: refactor core API to use pages struct
2025-03-28 18:10 [PATCH v2 0/7] Replace xe_hmm with gpusvm Matthew Auld
` (2 preceding siblings ...)
2025-03-28 18:10 ` [PATCH v2 3/7] drm/gpusvm: pull out drm_gpusvm_pages substructure Matthew Auld
@ 2025-03-28 18:10 ` Matthew Auld
2025-03-28 18:10 ` [PATCH v2 5/7] drm/gpusvm: export drm_gpusvm_pages API Matthew Auld
` (5 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Matthew Auld @ 2025-03-28 18:10 UTC (permalink / raw)
To: intel-xe; +Cc: dri-devel, Matthew Brost, Thomas Hellström
Refactor the core API of get/unmap/free pages to all operate on
drm_gpusvm_pages. In the next patch we want to export a simplified core
API without needing fully blown svm range etc.
Suggested-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
drivers/gpu/drm/drm_gpusvm.c | 161 ++++++++++++++++++++++++-----------
1 file changed, 110 insertions(+), 51 deletions(-)
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index c3d70403fbcc..e1f9c013071f 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -1128,19 +1128,19 @@ drm_gpusvm_range_find_or_insert(struct drm_gpusvm *gpusvm,
EXPORT_SYMBOL_GPL(drm_gpusvm_range_find_or_insert);
/**
- * __drm_gpusvm_range_unmap_pages() - Unmap pages associated with a GPU SVM range (internal)
+ * __drm_gpusvm_unmap_pages() - Unmap pages associated with GPU SVM pages
+ * (internal)
* @gpusvm: Pointer to the GPU SVM structure
- * @range: Pointer to the GPU SVM range structure
+ * @pages: Pointer to the GPU SVM pages structure
* @npages: Number of pages to unmap
*
- * This function unmap pages associated with a GPU SVM range. Assumes and
+ * This function unmap pages associated with a GPU SVM pages struct. Assumes and
* asserts correct locking is in place when called.
*/
-static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range,
- unsigned long npages)
+static void __drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages,
+ unsigned long npages)
{
- struct drm_gpusvm_pages *svm_pages = &range->pages;
struct drm_pagemap *dpagemap = svm_pages->dpagemap;
struct device *dev = gpusvm->drm->dev;
unsigned long i, j;
@@ -1168,17 +1168,15 @@ static void __drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
}
/**
- * drm_gpusvm_range_free_pages() - Free pages associated with a GPU SVM range
+ * __drm_gpusvm_free_pages() - Free dma array associated with GPU SVM pages
* @gpusvm: Pointer to the GPU SVM structure
- * @range: Pointer to the GPU SVM range structure
+ * @svm_pages: Pointer to the GPU SVM pages structure
*
* This function frees the dma address array associated with a GPU SVM range.
*/
-static void drm_gpusvm_range_free_pages(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range)
+static void __drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages)
{
- struct drm_gpusvm_pages *svm_pages = &range->pages;
-
lockdep_assert_held(&gpusvm->notifier_lock);
if (svm_pages->dma_addr) {
@@ -1211,8 +1209,8 @@ void drm_gpusvm_range_remove(struct drm_gpusvm *gpusvm,
return;
drm_gpusvm_notifier_lock(gpusvm);
- __drm_gpusvm_range_unmap_pages(gpusvm, range, npages);
- drm_gpusvm_range_free_pages(gpusvm, range);
+ __drm_gpusvm_unmap_pages(gpusvm, &range->pages, npages);
+ __drm_gpusvm_free_pages(gpusvm, &range->pages);
__drm_gpusvm_range_remove(notifier, range);
drm_gpusvm_notifier_unlock(gpusvm);
@@ -1277,6 +1275,28 @@ void drm_gpusvm_range_put(struct drm_gpusvm_range *range)
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_put);
+/**
+ * drm_gpusvm_pages_valid() - GPU SVM range pages valid
+ * @gpusvm: Pointer to the GPU SVM structure
+ * @svm_pages: Pointer to the GPU SVM pages structure
+ *
+ * This function determines if a GPU SVM range pages are valid. Expected be
+ * called holding gpusvm->notifier_lock and as the last step before committing a
+ * GPU binding. This is akin to a notifier seqno check in the HMM documentation
+ * but due to wider notifiers (i.e., notifiers which span multiple ranges) this
+ * function is required for finer grained checking (i.e., per range) if pages
+ * are valid.
+ *
+ * Return: True if GPU SVM range has valid pages, False otherwise
+ */
+static bool drm_gpusvm_pages_valid(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages)
+{
+ lockdep_assert_held(&gpusvm->notifier_lock);
+
+ return svm_pages->flags.has_devmem_pages || svm_pages->flags.has_dma_mapping;
+}
+
/**
* drm_gpusvm_range_pages_valid() - GPU SVM range pages valid
* @gpusvm: Pointer to the GPU SVM structure
@@ -1294,11 +1314,7 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_range_put);
bool drm_gpusvm_range_pages_valid(struct drm_gpusvm *gpusvm,
struct drm_gpusvm_range *range)
{
- struct drm_gpusvm_pages *svm_pages = &range->pages;
-
- lockdep_assert_held(&gpusvm->notifier_lock);
-
- return svm_pages->flags.has_devmem_pages || svm_pages->flags.has_dma_mapping;
+ return drm_gpusvm_pages_valid(gpusvm, &range->pages);
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);
@@ -1312,57 +1328,59 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_range_pages_valid);
*
* Return: True if GPU SVM range has valid pages, False otherwise
*/
-static bool
-drm_gpusvm_range_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range)
+static bool drm_gpusvm_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages)
{
- struct drm_gpusvm_pages *svm_pages = &range->pages;
bool pages_valid;
if (!svm_pages->dma_addr)
return false;
drm_gpusvm_notifier_lock(gpusvm);
- pages_valid = drm_gpusvm_range_pages_valid(gpusvm, range);
+ pages_valid = drm_gpusvm_pages_valid(gpusvm, svm_pages);
if (!pages_valid)
- drm_gpusvm_range_free_pages(gpusvm, range);
+ __drm_gpusvm_free_pages(gpusvm, svm_pages);
drm_gpusvm_notifier_unlock(gpusvm);
return pages_valid;
}
/**
- * drm_gpusvm_range_get_pages() - Get pages for a GPU SVM range
+ * drm_gpusvm_get_pages() - Get pages and populate GPU SVM pages struct
* @gpusvm: Pointer to the GPU SVM structure
- * @range: Pointer to the GPU SVM range structure
+ * @svm_pages: The SVM pages to populate. This will contain the dma-addresses
+ * @mm: The mm corresponding to the CPU range
+ * @notifier: The corresponding notifier for the given CPU range
+ * @pages_start: Start CPU address for the pages
+ * @pages_end: End CPU address for the pages (exclusive)
* @ctx: GPU SVM context
*
- * This function gets pages for a GPU SVM range and ensures they are mapped for
- * DMA access.
+ * This function gets and maps pages for CPU range and ensures they are
+ * mapped for DMA access.
*
* Return: 0 on success, negative error code on failure.
*/
-int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_range *range,
- const struct drm_gpusvm_ctx *ctx)
+static int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages,
+ struct mm_struct *mm,
+ struct mmu_interval_notifier *notifier,
+ unsigned long pages_start,
+ unsigned long pages_end,
+ const struct drm_gpusvm_ctx *ctx)
{
- struct drm_gpusvm_pages *svm_pages = &range->pages;
- struct mmu_interval_notifier *notifier = &range->notifier->notifier;
struct hmm_range hmm_range = {
.default_flags = HMM_PFN_REQ_FAULT | (ctx->read_only ? 0 :
HMM_PFN_REQ_WRITE),
.notifier = notifier,
- .start = drm_gpusvm_range_start(range),
- .end = drm_gpusvm_range_end(range),
+ .start = pages_start,
+ .end = pages_end,
.dev_private_owner = gpusvm->device_private_page_owner,
};
- struct mm_struct *mm = gpusvm->mm;
struct drm_gpusvm_zdd *zdd;
unsigned long timeout =
jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
unsigned long i, j;
- unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
- drm_gpusvm_range_end(range));
+ unsigned long npages = npages_in_range(pages_start, pages_end);
unsigned long num_dma_mapped;
unsigned int order = 0;
unsigned long *pfns;
@@ -1375,7 +1393,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
retry:
hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
- if (drm_gpusvm_range_pages_valid_unlocked(gpusvm, range))
+ if (drm_gpusvm_pages_valid_unlocked(gpusvm, svm_pages))
goto set_seqno;
pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
@@ -1522,7 +1540,7 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
return 0;
err_unmap:
- __drm_gpusvm_range_unmap_pages(gpusvm, range, num_dma_mapped);
+ __drm_gpusvm_unmap_pages(gpusvm, svm_pages, num_dma_mapped);
drm_gpusvm_notifier_unlock(gpusvm);
err_free:
kvfree(pfns);
@@ -1530,8 +1548,57 @@ int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
goto retry;
return err;
}
+
+/**
+ * drm_gpusvm_range_get_pages() - Get pages for a GPU SVM range
+ * @gpusvm: Pointer to the GPU SVM structure
+ * @range: Pointer to the GPU SVM range structure
+ * @ctx: GPU SVM context
+ *
+ * This function gets pages for a GPU SVM range and ensures they are mapped for
+ * DMA access.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int drm_gpusvm_range_get_pages(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_range *range,
+ const struct drm_gpusvm_ctx *ctx)
+{
+ return drm_gpusvm_get_pages(gpusvm, &range->pages, gpusvm->mm,
+ &range->notifier->notifier,
+ drm_gpusvm_range_start(range),
+ drm_gpusvm_range_end(range), ctx);
+}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_get_pages);
+/**
+ * drm_gpusvm_unmap_pages() - Unmap GPU svm pages
+ * @gpusvm: Pointer to the GPU SVM structure
+ * @pages: Pointer to the GPU SVM pages structure
+ * @ctx: GPU SVM context
+ *
+ * This function unmaps pages associated with a GPU SVM pages struct. If
+ * @in_notifier is set, it is assumed that gpusvm->notifier_lock is held in
+ * write mode; if it is clear, it acquires gpusvm->notifier_lock in read mode.
+ * Must be called in the invalidate() callback of the corresponding notifier for
+ * IOMMU security model.
+ */
+static void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages,
+ unsigned long npages,
+ const struct drm_gpusvm_ctx *ctx)
+{
+ if (ctx->in_notifier)
+ lockdep_assert_held_write(&gpusvm->notifier_lock);
+ else
+ drm_gpusvm_notifier_lock(gpusvm);
+
+ __drm_gpusvm_unmap_pages(gpusvm, svm_pages, npages);
+
+ if (!ctx->in_notifier)
+ drm_gpusvm_notifier_unlock(gpusvm);
+}
+
/**
* drm_gpusvm_range_unmap_pages() - Unmap pages associated with a GPU SVM range
* @gpusvm: Pointer to the GPU SVM structure
@@ -1551,15 +1618,7 @@ void drm_gpusvm_range_unmap_pages(struct drm_gpusvm *gpusvm,
unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
drm_gpusvm_range_end(range));
- if (ctx->in_notifier)
- lockdep_assert_held_write(&gpusvm->notifier_lock);
- else
- drm_gpusvm_notifier_lock(gpusvm);
-
- __drm_gpusvm_range_unmap_pages(gpusvm, range, npages);
-
- if (!ctx->in_notifier)
- drm_gpusvm_notifier_unlock(gpusvm);
+ return drm_gpusvm_unmap_pages(gpusvm, &range->pages, npages, ctx);
}
EXPORT_SYMBOL_GPL(drm_gpusvm_range_unmap_pages);
--
2.48.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v2 5/7] drm/gpusvm: export drm_gpusvm_pages API
2025-03-28 18:10 [PATCH v2 0/7] Replace xe_hmm with gpusvm Matthew Auld
` (3 preceding siblings ...)
2025-03-28 18:10 ` [PATCH v2 4/7] drm/gpusvm: refactor core API to use pages struct Matthew Auld
@ 2025-03-28 18:10 ` Matthew Auld
2025-03-28 18:10 ` [PATCH v2 6/7] drm/xe/userptr: replace xe_hmm with gpusvm Matthew Auld
` (4 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Matthew Auld @ 2025-03-28 18:10 UTC (permalink / raw)
To: intel-xe; +Cc: dri-devel, Thomas Hellström, Matthew Brost
Export get/unmap/free pages API. We also need to tweak the SVM init to
allow skipping much of the unneeded parts.
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>
---
drivers/gpu/drm/drm_gpusvm.c | 66 ++++++++++++++++++++++++++++--------
include/drm/drm_gpusvm.h | 16 +++++++++
2 files changed, 67 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index e1f9c013071f..7c117d7a8d5b 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -539,6 +539,12 @@ static const struct mmu_interval_notifier_ops drm_gpusvm_notifier_ops = {
*
* This function initializes the GPU SVM.
*
+ * Note: If only using the simple drm_gpusvm_pages API (get/unmap/free),
+ * then only @gpusvm, @name, and @drm are expected. However, the same base
+ * @gpusvm can also be used with both modes together in which case the full
+ * setup is needed, where the core drm_gpusvm_pages API will simply never use
+ * the other fields.
+ *
* Return: 0 on success, a negative error code on failure.
*/
int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
@@ -549,8 +555,16 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
const struct drm_gpusvm_ops *ops,
const unsigned long *chunk_sizes, int num_chunks)
{
- if (!ops->invalidate || !num_chunks)
- return -EINVAL;
+ if (mm) {
+ if (!ops->invalidate || !num_chunks)
+ return -EINVAL;
+ mmgrab(mm);
+ } else {
+ /* No full SVM mode, only core drm_gpusvm_pages API. */
+ if (ops || num_chunks || mm_range || notifier_size ||
+ device_private_page_owner)
+ return -EINVAL;
+ }
gpusvm->name = name;
gpusvm->drm = drm;
@@ -563,7 +577,6 @@ int drm_gpusvm_init(struct drm_gpusvm *gpusvm,
gpusvm->chunk_sizes = chunk_sizes;
gpusvm->num_chunks = num_chunks;
- mmgrab(mm);
gpusvm->root = RB_ROOT_CACHED;
INIT_LIST_HEAD(&gpusvm->notifier_list);
@@ -671,7 +684,8 @@ void drm_gpusvm_fini(struct drm_gpusvm *gpusvm)
drm_gpusvm_range_remove(gpusvm, range);
}
- mmdrop(gpusvm->mm);
+ if (gpusvm->mm)
+ mmdrop(gpusvm->mm);
WARN_ON(!RB_EMPTY_ROOT(&gpusvm->root.rb_root));
}
EXPORT_SYMBOL_GPL(drm_gpusvm_fini);
@@ -1185,6 +1199,27 @@ static void __drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
}
}
+/**
+ * drm_gpusvm_free_pages() - Free dma-mapping associated with GPU SVM pages
+ * struct
+ * @gpusvm: Pointer to the GPU SVM structure
+ * @svm_pages: Pointer to the GPU SVM pages structure
+ * @npages: Number of mapped pages
+ *
+ * This function unmaps and frees the dma address array associated with a GPU
+ * SVM pages struct.
+ */
+void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages,
+ unsigned long npages)
+{
+ drm_gpusvm_notifier_lock(gpusvm);
+ __drm_gpusvm_unmap_pages(gpusvm, svm_pages, npages);
+ __drm_gpusvm_free_pages(gpusvm, svm_pages);
+ drm_gpusvm_notifier_unlock(gpusvm);
+}
+EXPORT_SYMBOL_GPL(drm_gpusvm_free_pages);
+
/**
* drm_gpusvm_range_remove() - Remove GPU SVM range
* @gpusvm: Pointer to the GPU SVM structure
@@ -1360,13 +1395,12 @@ static bool drm_gpusvm_pages_valid_unlocked(struct drm_gpusvm *gpusvm,
*
* Return: 0 on success, negative error code on failure.
*/
-static int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_pages *svm_pages,
- struct mm_struct *mm,
- struct mmu_interval_notifier *notifier,
- unsigned long pages_start,
- unsigned long pages_end,
- const struct drm_gpusvm_ctx *ctx)
+int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages,
+ struct mm_struct *mm,
+ struct mmu_interval_notifier *notifier,
+ unsigned long pages_start, unsigned long pages_end,
+ const struct drm_gpusvm_ctx *ctx)
{
struct hmm_range hmm_range = {
.default_flags = HMM_PFN_REQ_FAULT | (ctx->read_only ? 0 :
@@ -1548,6 +1582,7 @@ static int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
goto retry;
return err;
}
+EXPORT_SYMBOL_GPL(drm_gpusvm_get_pages);
/**
* drm_gpusvm_range_get_pages() - Get pages for a GPU SVM range
@@ -1583,10 +1618,10 @@ EXPORT_SYMBOL_GPL(drm_gpusvm_range_get_pages);
* Must be called in the invalidate() callback of the corresponding notifier for
* IOMMU security model.
*/
-static void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
- struct drm_gpusvm_pages *svm_pages,
- unsigned long npages,
- const struct drm_gpusvm_ctx *ctx)
+void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages,
+ unsigned long npages,
+ const struct drm_gpusvm_ctx *ctx)
{
if (ctx->in_notifier)
lockdep_assert_held_write(&gpusvm->notifier_lock);
@@ -1598,6 +1633,7 @@ static void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
if (!ctx->in_notifier)
drm_gpusvm_notifier_unlock(gpusvm);
}
+EXPORT_SYMBOL_GPL(drm_gpusvm_unmap_pages);
/**
* drm_gpusvm_range_unmap_pages() - Unmap pages associated with a GPU SVM range
diff --git a/include/drm/drm_gpusvm.h b/include/drm/drm_gpusvm.h
index 1b7ed4f4a8e2..611aaba1ac80 100644
--- a/include/drm/drm_gpusvm.h
+++ b/include/drm/drm_gpusvm.h
@@ -370,6 +370,22 @@ void drm_gpusvm_devmem_init(struct drm_gpusvm_devmem *devmem_allocation,
const struct drm_gpusvm_devmem_ops *ops,
struct drm_pagemap *dpagemap, size_t size);
+int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages,
+ struct mm_struct *mm,
+ struct mmu_interval_notifier *notifier,
+ unsigned long pages_start, unsigned long pages_end,
+ const struct drm_gpusvm_ctx *ctx);
+
+void drm_gpusvm_unmap_pages(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages,
+ unsigned long npages,
+ const struct drm_gpusvm_ctx *ctx);
+
+void drm_gpusvm_free_pages(struct drm_gpusvm *gpusvm,
+ struct drm_gpusvm_pages *svm_pages,
+ unsigned long npages);
+
#ifdef CONFIG_LOCKDEP
/**
* drm_gpusvm_driver_set_lock() - Set the lock protecting accesses to GPU SVM
--
2.48.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v2 6/7] drm/xe/userptr: replace xe_hmm with gpusvm
2025-03-28 18:10 [PATCH v2 0/7] Replace xe_hmm with gpusvm Matthew Auld
` (4 preceding siblings ...)
2025-03-28 18:10 ` [PATCH v2 5/7] drm/gpusvm: export drm_gpusvm_pages API Matthew Auld
@ 2025-03-28 18:10 ` Matthew Auld
2025-03-28 18:10 ` [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr Matthew Auld
` (3 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: Matthew Auld @ 2025-03-28 18:10 UTC (permalink / raw)
To: intel-xe
Cc: dri-devel, Himal Prasad Ghimiray, Thomas Hellström,
Matthew Brost
Goal here is cut over to gpusvm and remove xe_hmm, relying instead on
common code. The core facilities we need are get_pages(), unmap_pages()
and free_pages() for a given useptr range, plus a vm level notifier
lock, which is now provided by gpusvm.
v2:
- Reuse the same SVM vm struct we use for full SVM, that way we can
use the same lock (Matt B & Himal)
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
---
drivers/gpu/drm/xe/Kconfig | 3 +-
drivers/gpu/drm/xe/Makefile | 1 -
drivers/gpu/drm/xe/xe_exec.c | 4 +-
drivers/gpu/drm/xe/xe_hmm.c | 349 -------------------------------
drivers/gpu/drm/xe/xe_hmm.h | 18 --
drivers/gpu/drm/xe/xe_pt.c | 22 +-
drivers/gpu/drm/xe/xe_vm.c | 85 +++++---
drivers/gpu/drm/xe/xe_vm_types.h | 26 +--
8 files changed, 73 insertions(+), 435 deletions(-)
delete mode 100644 drivers/gpu/drm/xe/xe_hmm.c
delete mode 100644 drivers/gpu/drm/xe/xe_hmm.h
diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig
index 9bce047901b2..1e63dde76c55 100644
--- a/drivers/gpu/drm/xe/Kconfig
+++ b/drivers/gpu/drm/xe/Kconfig
@@ -43,7 +43,7 @@ config DRM_XE
select MMU_NOTIFIER
select WANT_DEV_COREDUMP
select AUXILIARY_BUS
- select HMM_MIRROR
+ select DRM_GPUSVM
help
Experimental driver for Intel Xe series GPUs
@@ -79,7 +79,6 @@ config DRM_XE_GPUSVM
depends on !UML
depends on DEVICE_PRIVATE
default y
- select DRM_GPUSVM
help
Enable this option if you want support for CPU to GPU address
mirroring.
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index 72eaadc4cbee..0d133a5ecf5f 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -124,7 +124,6 @@ xe-y += xe_bb.o \
xe_wait_user_fence.o \
xe_wopcm.o
-xe-$(CONFIG_HMM_MIRROR) += xe_hmm.o
xe-$(CONFIG_DRM_XE_GPUSVM) += xe_svm.o
# graphics hardware monitoring (HWMON) support
diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
index b75adfc99fb7..c0ce681076d5 100644
--- a/drivers/gpu/drm/xe/xe_exec.c
+++ b/drivers/gpu/drm/xe/xe_exec.c
@@ -294,7 +294,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
if (err)
goto err_put_job;
- err = down_read_interruptible(&vm->userptr.notifier_lock);
+ err = down_read_interruptible(&vm->svm.gpusvm.notifier_lock);
if (err)
goto err_put_job;
@@ -336,7 +336,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
err_repin:
if (!xe_vm_in_lr_mode(vm))
- up_read(&vm->userptr.notifier_lock);
+ up_read(&vm->svm.gpusvm.notifier_lock);
err_put_job:
if (err)
xe_sched_job_put(job);
diff --git a/drivers/gpu/drm/xe/xe_hmm.c b/drivers/gpu/drm/xe/xe_hmm.c
deleted file mode 100644
index c3cc0fa105e8..000000000000
--- a/drivers/gpu/drm/xe/xe_hmm.c
+++ /dev/null
@@ -1,349 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2024 Intel Corporation
- */
-
-#include <linux/scatterlist.h>
-#include <linux/mmu_notifier.h>
-#include <linux/dma-mapping.h>
-#include <linux/memremap.h>
-#include <linux/swap.h>
-#include <linux/hmm.h>
-#include <linux/mm.h>
-#include "xe_hmm.h"
-#include "xe_vm.h"
-#include "xe_bo.h"
-
-static u64 xe_npages_in_range(unsigned long start, unsigned long end)
-{
- return (end - start) >> PAGE_SHIFT;
-}
-
-/**
- * xe_mark_range_accessed() - mark a range is accessed, so core mm
- * have such information for memory eviction or write back to
- * hard disk
- * @range: the range to mark
- * @write: if write to this range, we mark pages in this range
- * as dirty
- */
-static void xe_mark_range_accessed(struct hmm_range *range, bool write)
-{
- struct page *page;
- u64 i, npages;
-
- npages = xe_npages_in_range(range->start, range->end);
- for (i = 0; i < npages; i++) {
- page = hmm_pfn_to_page(range->hmm_pfns[i]);
- if (write)
- set_page_dirty_lock(page);
-
- mark_page_accessed(page);
- }
-}
-
-static int xe_alloc_sg(struct xe_device *xe, struct sg_table *st,
- struct hmm_range *range, struct rw_semaphore *notifier_sem)
-{
- unsigned long i, npages, hmm_pfn;
- unsigned long num_chunks = 0;
- int ret;
-
- /* HMM docs says this is needed. */
- ret = down_read_interruptible(notifier_sem);
- if (ret)
- return ret;
-
- if (mmu_interval_read_retry(range->notifier, range->notifier_seq)) {
- up_read(notifier_sem);
- return -EAGAIN;
- }
-
- npages = xe_npages_in_range(range->start, range->end);
- for (i = 0; i < npages;) {
- unsigned long len;
-
- hmm_pfn = range->hmm_pfns[i];
- xe_assert(xe, hmm_pfn & HMM_PFN_VALID);
-
- len = 1UL << hmm_pfn_to_map_order(hmm_pfn);
-
- /* If order > 0 the page may extend beyond range->start */
- len -= (hmm_pfn & ~HMM_PFN_FLAGS) & (len - 1);
- i += len;
- num_chunks++;
- }
- up_read(notifier_sem);
-
- return sg_alloc_table(st, num_chunks, GFP_KERNEL);
-}
-
-/**
- * xe_build_sg() - build a scatter gather table for all the physical pages/pfn
- * in a hmm_range. dma-map pages if necessary. dma-address is save in sg table
- * and will be used to program GPU page table later.
- * @xe: the xe device who will access the dma-address in sg table
- * @range: the hmm range that we build the sg table from. range->hmm_pfns[]
- * has the pfn numbers of pages that back up this hmm address range.
- * @st: pointer to the sg table.
- * @notifier_sem: The xe notifier lock.
- * @write: whether we write to this range. This decides dma map direction
- * for system pages. If write we map it bi-diretional; otherwise
- * DMA_TO_DEVICE
- *
- * All the contiguous pfns will be collapsed into one entry in
- * the scatter gather table. This is for the purpose of efficiently
- * programming GPU page table.
- *
- * The dma_address in the sg table will later be used by GPU to
- * access memory. So if the memory is system memory, we need to
- * do a dma-mapping so it can be accessed by GPU/DMA.
- *
- * FIXME: This function currently only support pages in system
- * memory. If the memory is GPU local memory (of the GPU who
- * is going to access memory), we need gpu dpa (device physical
- * address), and there is no need of dma-mapping. This is TBD.
- *
- * FIXME: dma-mapping for peer gpu device to access remote gpu's
- * memory. Add this when you support p2p
- *
- * This function allocates the storage of the sg table. It is
- * caller's responsibility to free it calling sg_free_table.
- *
- * Returns 0 if successful; -ENOMEM if fails to allocate memory
- */
-static int xe_build_sg(struct xe_device *xe, struct hmm_range *range,
- struct sg_table *st,
- struct rw_semaphore *notifier_sem,
- bool write)
-{
- unsigned long npages = xe_npages_in_range(range->start, range->end);
- struct device *dev = xe->drm.dev;
- struct scatterlist *sgl;
- struct page *page;
- unsigned long i, j;
-
- lockdep_assert_held(notifier_sem);
-
- i = 0;
- for_each_sg(st->sgl, sgl, st->nents, j) {
- unsigned long hmm_pfn, size;
-
- hmm_pfn = range->hmm_pfns[i];
- page = hmm_pfn_to_page(hmm_pfn);
- xe_assert(xe, !is_device_private_page(page));
-
- size = 1UL << hmm_pfn_to_map_order(hmm_pfn);
- size -= page_to_pfn(page) & (size - 1);
- i += size;
-
- if (unlikely(j == st->nents - 1)) {
- xe_assert(xe, i >= npages);
- if (i > npages)
- size -= (i - npages);
-
- sg_mark_end(sgl);
- } else {
- xe_assert(xe, i < npages);
- }
-
- sg_set_page(sgl, page, size << PAGE_SHIFT, 0);
- }
-
- return dma_map_sgtable(dev, st, write ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE,
- DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_NO_KERNEL_MAPPING);
-}
-
-static void xe_hmm_userptr_set_mapped(struct xe_userptr_vma *uvma)
-{
- struct xe_userptr *userptr = &uvma->userptr;
- struct xe_vm *vm = xe_vma_vm(&uvma->vma);
-
- lockdep_assert_held_write(&vm->lock);
- lockdep_assert_held(&vm->userptr.notifier_lock);
-
- mutex_lock(&userptr->unmap_mutex);
- xe_assert(vm->xe, !userptr->mapped);
- userptr->mapped = true;
- mutex_unlock(&userptr->unmap_mutex);
-}
-
-void xe_hmm_userptr_unmap(struct xe_userptr_vma *uvma)
-{
- struct xe_userptr *userptr = &uvma->userptr;
- struct xe_vma *vma = &uvma->vma;
- bool write = !xe_vma_read_only(vma);
- struct xe_vm *vm = xe_vma_vm(vma);
- struct xe_device *xe = vm->xe;
-
- if (!lockdep_is_held_type(&vm->userptr.notifier_lock, 0) &&
- !lockdep_is_held_type(&vm->lock, 0) &&
- !(vma->gpuva.flags & XE_VMA_DESTROYED)) {
- /* Don't unmap in exec critical section. */
- xe_vm_assert_held(vm);
- /* Don't unmap while mapping the sg. */
- lockdep_assert_held(&vm->lock);
- }
-
- mutex_lock(&userptr->unmap_mutex);
- if (userptr->sg && userptr->mapped)
- dma_unmap_sgtable(xe->drm.dev, userptr->sg,
- write ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE, 0);
- userptr->mapped = false;
- mutex_unlock(&userptr->unmap_mutex);
-}
-
-/**
- * xe_hmm_userptr_free_sg() - Free the scatter gather table of userptr
- * @uvma: the userptr vma which hold the scatter gather table
- *
- * With function xe_userptr_populate_range, we allocate storage of
- * the userptr sg table. This is a helper function to free this
- * sg table, and dma unmap the address in the table.
- */
-void xe_hmm_userptr_free_sg(struct xe_userptr_vma *uvma)
-{
- struct xe_userptr *userptr = &uvma->userptr;
-
- xe_assert(xe_vma_vm(&uvma->vma)->xe, userptr->sg);
- xe_hmm_userptr_unmap(uvma);
- sg_free_table(userptr->sg);
- userptr->sg = NULL;
-}
-
-/**
- * xe_hmm_userptr_populate_range() - Populate physical pages of a virtual
- * address range
- *
- * @uvma: userptr vma which has information of the range to populate.
- * @is_mm_mmap_locked: True if mmap_read_lock is already acquired by caller.
- *
- * This function populate the physical pages of a virtual
- * address range. The populated physical pages is saved in
- * userptr's sg table. It is similar to get_user_pages but call
- * hmm_range_fault.
- *
- * This function also read mmu notifier sequence # (
- * mmu_interval_read_begin), for the purpose of later
- * comparison (through mmu_interval_read_retry).
- *
- * This must be called with mmap read or write lock held.
- *
- * This function allocates the storage of the userptr sg table.
- * It is caller's responsibility to free it calling sg_free_table.
- *
- * returns: 0 for success; negative error no on failure
- */
-int xe_hmm_userptr_populate_range(struct xe_userptr_vma *uvma,
- bool is_mm_mmap_locked)
-{
- unsigned long timeout =
- jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
- unsigned long *pfns;
- struct xe_userptr *userptr;
- struct xe_vma *vma = &uvma->vma;
- u64 userptr_start = xe_vma_userptr(vma);
- u64 userptr_end = userptr_start + xe_vma_size(vma);
- struct xe_vm *vm = xe_vma_vm(vma);
- struct hmm_range hmm_range = {
- .pfn_flags_mask = 0, /* ignore pfns */
- .default_flags = HMM_PFN_REQ_FAULT,
- .start = userptr_start,
- .end = userptr_end,
- .notifier = &uvma->userptr.notifier,
- .dev_private_owner = vm->xe,
- };
- bool write = !xe_vma_read_only(vma);
- unsigned long notifier_seq;
- u64 npages;
- int ret;
-
- userptr = &uvma->userptr;
-
- if (is_mm_mmap_locked)
- mmap_assert_locked(userptr->notifier.mm);
-
- if (vma->gpuva.flags & XE_VMA_DESTROYED)
- return 0;
-
- notifier_seq = mmu_interval_read_begin(&userptr->notifier);
- if (notifier_seq == userptr->notifier_seq)
- return 0;
-
- if (userptr->sg)
- xe_hmm_userptr_free_sg(uvma);
-
- npages = xe_npages_in_range(userptr_start, userptr_end);
- pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL);
- if (unlikely(!pfns))
- return -ENOMEM;
-
- if (write)
- hmm_range.default_flags |= HMM_PFN_REQ_WRITE;
-
- if (!mmget_not_zero(userptr->notifier.mm)) {
- ret = -EFAULT;
- goto free_pfns;
- }
-
- hmm_range.hmm_pfns = pfns;
-
- while (true) {
- hmm_range.notifier_seq = mmu_interval_read_begin(&userptr->notifier);
-
- if (!is_mm_mmap_locked)
- mmap_read_lock(userptr->notifier.mm);
-
- ret = hmm_range_fault(&hmm_range);
-
- if (!is_mm_mmap_locked)
- mmap_read_unlock(userptr->notifier.mm);
-
- if (ret == -EBUSY) {
- if (time_after(jiffies, timeout))
- break;
-
- continue;
- }
- break;
- }
-
- mmput(userptr->notifier.mm);
-
- if (ret)
- goto free_pfns;
-
- ret = xe_alloc_sg(vm->xe, &userptr->sgt, &hmm_range, &vm->userptr.notifier_lock);
- if (ret)
- goto free_pfns;
-
- ret = down_read_interruptible(&vm->userptr.notifier_lock);
- if (ret)
- goto free_st;
-
- if (mmu_interval_read_retry(hmm_range.notifier, hmm_range.notifier_seq)) {
- ret = -EAGAIN;
- goto out_unlock;
- }
-
- ret = xe_build_sg(vm->xe, &hmm_range, &userptr->sgt,
- &vm->userptr.notifier_lock, write);
- if (ret)
- goto out_unlock;
-
- xe_mark_range_accessed(&hmm_range, write);
- userptr->sg = &userptr->sgt;
- xe_hmm_userptr_set_mapped(uvma);
- userptr->notifier_seq = hmm_range.notifier_seq;
- up_read(&vm->userptr.notifier_lock);
- kvfree(pfns);
- return 0;
-
-out_unlock:
- up_read(&vm->userptr.notifier_lock);
-free_st:
- sg_free_table(&userptr->sgt);
-free_pfns:
- kvfree(pfns);
- return ret;
-}
diff --git a/drivers/gpu/drm/xe/xe_hmm.h b/drivers/gpu/drm/xe/xe_hmm.h
deleted file mode 100644
index 0ea98d8e7bbc..000000000000
--- a/drivers/gpu/drm/xe/xe_hmm.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright © 2024 Intel Corporation
- */
-
-#ifndef _XE_HMM_H_
-#define _XE_HMM_H_
-
-#include <linux/types.h>
-
-struct xe_userptr_vma;
-
-int xe_hmm_userptr_populate_range(struct xe_userptr_vma *uvma, bool is_mm_mmap_locked);
-
-void xe_hmm_userptr_free_sg(struct xe_userptr_vma *uvma);
-
-void xe_hmm_userptr_unmap(struct xe_userptr_vma *uvma);
-#endif
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 9ac9291baeac..b097c91e2e02 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -729,8 +729,8 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
if (!xe_vma_is_null(vma) && !range) {
if (xe_vma_is_userptr(vma))
- xe_res_first_sg(to_userptr_vma(vma)->userptr.sg, 0,
- xe_vma_size(vma), &curs);
+ xe_res_first_dma(to_userptr_vma(vma)->userptr.pages.dma_addr, 0,
+ xe_vma_size(vma), &curs);
else if (xe_bo_is_vram(bo) || xe_bo_is_stolen(bo))
xe_res_first(bo->ttm.resource, xe_vma_bo_offset(vma),
xe_vma_size(vma), &curs);
@@ -1000,7 +1000,7 @@ static void xe_pt_commit_locks_assert(struct xe_vma *vma)
xe_pt_commit_prepare_locks_assert(vma);
if (xe_vma_is_userptr(vma))
- lockdep_assert_held_read(&vm->userptr.notifier_lock);
+ lockdep_assert_held_read(&vm->svm.gpusvm.notifier_lock);
}
static void xe_pt_commit(struct xe_vma *vma,
@@ -1338,7 +1338,7 @@ static int vma_check_userptr(struct xe_vm *vm, struct xe_vma *vma,
struct xe_userptr_vma *uvma;
unsigned long notifier_seq;
- lockdep_assert_held_read(&vm->userptr.notifier_lock);
+ lockdep_assert_held_read(&vm->svm.gpusvm.notifier_lock);
if (!xe_vma_is_userptr(vma))
return 0;
@@ -1347,7 +1347,7 @@ static int vma_check_userptr(struct xe_vm *vm, struct xe_vma *vma,
if (xe_pt_userptr_inject_eagain(uvma))
xe_vma_userptr_force_invalidate(uvma);
- notifier_seq = uvma->userptr.notifier_seq;
+ notifier_seq = uvma->userptr.pages.notifier_seq;
if (!mmu_interval_read_retry(&uvma->userptr.notifier,
notifier_seq))
@@ -1368,7 +1368,7 @@ static int op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op,
{
int err = 0;
- lockdep_assert_held_read(&vm->userptr.notifier_lock);
+ lockdep_assert_held_read(&vm->svm.gpusvm.notifier_lock);
switch (op->base.op) {
case DRM_GPUVA_OP_MAP:
@@ -1409,12 +1409,12 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
if (err)
return err;
- down_read(&vm->userptr.notifier_lock);
+ down_read(&vm->svm.gpusvm.notifier_lock);
list_for_each_entry(op, &vops->list, link) {
err = op_check_userptr(vm, op, pt_update_ops);
if (err) {
- up_read(&vm->userptr.notifier_lock);
+ up_read(&vm->svm.gpusvm.notifier_lock);
break;
}
}
@@ -2137,7 +2137,7 @@ static void bind_op_commit(struct xe_vm *vm, struct xe_tile *tile,
vma->tile_present |= BIT(tile->id);
vma->tile_staged &= ~BIT(tile->id);
if (xe_vma_is_userptr(vma)) {
- lockdep_assert_held_read(&vm->userptr.notifier_lock);
+ lockdep_assert_held_read(&vm->svm.gpusvm.notifier_lock);
to_userptr_vma(vma)->userptr.initial_bind = true;
}
@@ -2173,7 +2173,7 @@ static void unbind_op_commit(struct xe_vm *vm, struct xe_tile *tile,
if (!vma->tile_present) {
list_del_init(&vma->combined_links.rebind);
if (xe_vma_is_userptr(vma)) {
- lockdep_assert_held_read(&vm->userptr.notifier_lock);
+ lockdep_assert_held_read(&vm->svm.gpusvm.notifier_lock);
spin_lock(&vm->userptr.invalidated_lock);
list_del_init(&to_userptr_vma(vma)->userptr.invalidate_link);
@@ -2422,7 +2422,7 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
if (pt_update_ops->needs_svm_lock)
xe_svm_notifier_unlock(vm);
if (pt_update_ops->needs_userptr_lock)
- up_read(&vm->userptr.notifier_lock);
+ up_read(&vm->svm.gpusvm.notifier_lock);
return fence;
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 864266e38aa7..bcc707b68afc 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -40,7 +40,6 @@
#include "xe_sync.h"
#include "xe_trace_bo.h"
#include "xe_wa.h"
-#include "xe_hmm.h"
static struct drm_gem_object *xe_vm_obj(struct xe_vm *vm)
{
@@ -53,7 +52,7 @@ static struct drm_gem_object *xe_vm_obj(struct xe_vm *vm)
*
* Check if the userptr vma has been invalidated since last successful
* repin. The check is advisory only and can the function can be called
- * without the vm->userptr.notifier_lock held. There is no guarantee that the
+ * without the vm->svm.gpusvm.notifier_lock held. There is no guarantee that the
* vma userptr will remain valid after a lockless check, so typically
* the call needs to be followed by a proper check under the notifier_lock.
*
@@ -62,7 +61,7 @@ static struct drm_gem_object *xe_vm_obj(struct xe_vm *vm)
int xe_vma_userptr_check_repin(struct xe_userptr_vma *uvma)
{
return mmu_interval_check_retry(&uvma->userptr.notifier,
- uvma->userptr.notifier_seq) ?
+ uvma->userptr.pages.notifier_seq) ?
-EAGAIN : 0;
}
@@ -71,11 +70,22 @@ int xe_vma_userptr_pin_pages(struct xe_userptr_vma *uvma)
struct xe_vma *vma = &uvma->vma;
struct xe_vm *vm = xe_vma_vm(vma);
struct xe_device *xe = vm->xe;
+ struct drm_gpusvm_ctx ctx = {
+ .read_only = xe_vma_read_only(vma),
+ };
lockdep_assert_held(&vm->lock);
xe_assert(xe, xe_vma_is_userptr(vma));
- return xe_hmm_userptr_populate_range(uvma, false);
+ if (vma->gpuva.flags & XE_VMA_DESTROYED)
+ return 0;
+
+ return drm_gpusvm_get_pages(&vm->svm.gpusvm, &uvma->userptr.pages,
+ uvma->userptr.notifier.mm,
+ &uvma->userptr.notifier,
+ xe_vma_userptr(vma),
+ xe_vma_userptr(vma) + xe_vma_size(vma),
+ &ctx);
}
static bool preempt_fences_waiting(struct xe_vm *vm)
@@ -249,7 +259,7 @@ int xe_vm_add_compute_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
++vm->preempt.num_exec_queues;
q->lr.pfence = pfence;
- down_read(&vm->userptr.notifier_lock);
+ down_read(&vm->svm.gpusvm.notifier_lock);
drm_gpuvm_resv_add_fence(&vm->gpuvm, exec, pfence,
DMA_RESV_USAGE_BOOKKEEP, DMA_RESV_USAGE_BOOKKEEP);
@@ -263,7 +273,7 @@ int xe_vm_add_compute_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
if (wait)
dma_fence_enable_sw_signaling(pfence);
- up_read(&vm->userptr.notifier_lock);
+ up_read(&vm->svm.gpusvm.notifier_lock);
out_fini:
drm_exec_fini(exec);
@@ -305,14 +315,14 @@ void xe_vm_remove_compute_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
* @vm: The VM.
*
* This function checks for whether the VM has userptrs that need repinning,
- * and provides a release-type barrier on the userptr.notifier_lock after
+ * and provides a release-type barrier on the svm.gpusvm.notifier_lock after
* checking.
*
* Return: 0 if there are no userptrs needing repinning, -EAGAIN if there are.
*/
int __xe_vm_userptr_needs_repin(struct xe_vm *vm)
{
- lockdep_assert_held_read(&vm->userptr.notifier_lock);
+ lockdep_assert_held_read(&vm->svm.gpusvm.notifier_lock);
return (list_empty(&vm->userptr.repin_list) &&
list_empty(&vm->userptr.invalidated)) ? 0 : -EAGAIN;
@@ -546,9 +556,9 @@ static void preempt_rebind_work_func(struct work_struct *w)
(!(__tries)++ || __xe_vm_userptr_needs_repin(__vm)) : \
__xe_vm_userptr_needs_repin(__vm))
- down_read(&vm->userptr.notifier_lock);
+ down_read(&vm->svm.gpusvm.notifier_lock);
if (retry_required(tries, vm)) {
- up_read(&vm->userptr.notifier_lock);
+ up_read(&vm->svm.gpusvm.notifier_lock);
err = -EAGAIN;
goto out_unlock;
}
@@ -562,7 +572,7 @@ static void preempt_rebind_work_func(struct work_struct *w)
/* Point of no return. */
arm_preempt_fences(vm, &preempt_fences);
resume_and_reinstall_preempt_fences(vm, &exec);
- up_read(&vm->userptr.notifier_lock);
+ up_read(&vm->svm.gpusvm.notifier_lock);
out_unlock:
drm_exec_fini(&exec);
@@ -589,6 +599,9 @@ static void __vma_userptr_invalidate(struct xe_vm *vm, struct xe_userptr_vma *uv
struct xe_vma *vma = &uvma->vma;
struct dma_resv_iter cursor;
struct dma_fence *fence;
+ struct drm_gpusvm_ctx ctx = {
+ .in_notifier = true,
+ };
long err;
/*
@@ -625,7 +638,8 @@ static void __vma_userptr_invalidate(struct xe_vm *vm, struct xe_userptr_vma *uv
XE_WARN_ON(err);
}
- xe_hmm_userptr_unmap(uvma);
+ drm_gpusvm_unmap_pages(&vm->svm.gpusvm, &uvma->userptr.pages,
+ xe_vma_size(vma) >> PAGE_SHIFT, &ctx);
}
static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni,
@@ -646,11 +660,11 @@ static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni,
"NOTIFIER: addr=0x%016llx, range=0x%016llx",
xe_vma_start(vma), xe_vma_size(vma));
- down_write(&vm->userptr.notifier_lock);
+ down_write(&vm->svm.gpusvm.notifier_lock);
mmu_interval_set_seq(mni, cur_seq);
__vma_userptr_invalidate(vm, uvma);
- up_write(&vm->userptr.notifier_lock);
+ up_write(&vm->svm.gpusvm.notifier_lock);
trace_xe_vma_userptr_invalidate_complete(vma);
return true;
@@ -674,7 +688,7 @@ void xe_vma_userptr_force_invalidate(struct xe_userptr_vma *uvma)
/* Protect against concurrent userptr pinning */
lockdep_assert_held(&vm->lock);
/* Protect against concurrent notifiers */
- lockdep_assert_held(&vm->userptr.notifier_lock);
+ lockdep_assert_held(&vm->svm.gpusvm.notifier_lock);
/*
* Protect against concurrent instances of this function and
* the critical exec sections
@@ -747,7 +761,7 @@ int xe_vm_userptr_pin(struct xe_vm *vm)
}
if (err) {
- down_write(&vm->userptr.notifier_lock);
+ down_write(&vm->svm.gpusvm.notifier_lock);
spin_lock(&vm->userptr.invalidated_lock);
list_for_each_entry_safe(uvma, next, &vm->userptr.repin_list,
userptr.repin_link) {
@@ -756,7 +770,7 @@ int xe_vm_userptr_pin(struct xe_vm *vm)
&vm->userptr.invalidated);
}
spin_unlock(&vm->userptr.invalidated_lock);
- up_write(&vm->userptr.notifier_lock);
+ up_write(&vm->svm.gpusvm.notifier_lock);
}
return err;
}
@@ -1222,7 +1236,6 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
INIT_LIST_HEAD(&userptr->invalidate_link);
INIT_LIST_HEAD(&userptr->repin_link);
vma->gpuva.gem.offset = bo_offset_or_userptr;
- mutex_init(&userptr->unmap_mutex);
err = mmu_interval_notifier_insert(&userptr->notifier,
current->mm,
@@ -1233,7 +1246,7 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm,
return ERR_PTR(err);
}
- userptr->notifier_seq = LONG_MAX;
+ userptr->pages.notifier_seq = LONG_MAX;
}
xe_vm_get(vm);
@@ -1255,8 +1268,8 @@ static void xe_vma_destroy_late(struct xe_vma *vma)
struct xe_userptr_vma *uvma = to_userptr_vma(vma);
struct xe_userptr *userptr = &uvma->userptr;
- if (userptr->sg)
- xe_hmm_userptr_free_sg(uvma);
+ drm_gpusvm_free_pages(&vm->svm.gpusvm, &uvma->userptr.pages,
+ xe_vma_size(vma) >> PAGE_SHIFT);
/*
* Since userptr pages are not pinned, we can't remove
@@ -1264,7 +1277,6 @@ static void xe_vma_destroy_late(struct xe_vma *vma)
* them anymore
*/
mmu_interval_notifier_remove(&userptr->notifier);
- mutex_destroy(&userptr->unmap_mutex);
xe_vm_put(vm);
} else if (xe_vma_is_null(vma) || xe_vma_is_cpu_addr_mirror(vma)) {
xe_vm_put(vm);
@@ -1657,7 +1669,6 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
INIT_LIST_HEAD(&vm->userptr.repin_list);
INIT_LIST_HEAD(&vm->userptr.invalidated);
- init_rwsem(&vm->userptr.notifier_lock);
spin_lock_init(&vm->userptr.invalidated_lock);
ttm_lru_bulk_move_init(&vm->lru_bulk_move);
@@ -1759,9 +1770,13 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags)
if (flags & XE_VM_FLAG_FAULT_MODE) {
err = xe_svm_init(vm);
- if (err)
- goto err_close;
+ } else {
+ err = drm_gpusvm_init(&vm->svm.gpusvm, "Xe SVM (simple)",
+ &vm->xe->drm, NULL, NULL, 0, 0, 0, NULL,
+ NULL, 0);
}
+ if (err)
+ goto err_close;
if (number_tiles > 1)
vm->composite_fence_ctx = dma_fence_context_alloc(1);
@@ -1867,9 +1882,9 @@ void xe_vm_close_and_put(struct xe_vm *vm)
vma = gpuva_to_vma(gpuva);
if (xe_vma_has_no_bo(vma)) {
- down_read(&vm->userptr.notifier_lock);
+ down_read(&vm->svm.gpusvm.notifier_lock);
vma->gpuva.flags |= XE_VMA_DESTROYED;
- up_read(&vm->userptr.notifier_lock);
+ up_read(&vm->svm.gpusvm.notifier_lock);
}
xe_vm_remove_vma(vm, vma);
@@ -1915,6 +1930,8 @@ void xe_vm_close_and_put(struct xe_vm *vm)
if (xe_vm_in_fault_mode(vm))
xe_svm_fini(vm);
+ else
+ drm_gpusvm_fini(&vm->svm.gpusvm);
up_write(&vm->lock);
@@ -2144,9 +2161,9 @@ static const u32 region_to_mem_type[] = {
static void prep_vma_destroy(struct xe_vm *vm, struct xe_vma *vma,
bool post_commit)
{
- down_read(&vm->userptr.notifier_lock);
+ down_read(&vm->svm.gpusvm.notifier_lock);
vma->gpuva.flags |= XE_VMA_DESTROYED;
- up_read(&vm->userptr.notifier_lock);
+ up_read(&vm->svm.gpusvm.notifier_lock);
if (post_commit)
xe_vm_remove_vma(vm, vma);
}
@@ -2625,9 +2642,9 @@ static void xe_vma_op_unwind(struct xe_vm *vm, struct xe_vma_op *op,
struct xe_vma *vma = gpuva_to_vma(op->base.unmap.va);
if (vma) {
- down_read(&vm->userptr.notifier_lock);
+ down_read(&vm->svm.gpusvm.notifier_lock);
vma->gpuva.flags &= ~XE_VMA_DESTROYED;
- up_read(&vm->userptr.notifier_lock);
+ up_read(&vm->svm.gpusvm.notifier_lock);
if (post_commit)
xe_vm_insert_vma(vm, vma);
}
@@ -2646,9 +2663,9 @@ static void xe_vma_op_unwind(struct xe_vm *vm, struct xe_vma_op *op,
xe_vma_destroy_unlocked(op->remap.next);
}
if (vma) {
- down_read(&vm->userptr.notifier_lock);
+ down_read(&vm->svm.gpusvm.notifier_lock);
vma->gpuva.flags &= ~XE_VMA_DESTROYED;
- up_read(&vm->userptr.notifier_lock);
+ up_read(&vm->svm.gpusvm.notifier_lock);
if (post_commit)
xe_vm_insert_vma(vm, vma);
}
@@ -3629,7 +3646,7 @@ int xe_vm_invalidate_vma(struct xe_vma *vma)
if (xe_vma_is_userptr(vma)) {
WARN_ON_ONCE(!mmu_interval_check_retry
(&to_userptr_vma(vma)->userptr.notifier,
- to_userptr_vma(vma)->userptr.notifier_seq));
+ to_userptr_vma(vma)->userptr.pages.notifier_seq));
WARN_ON_ONCE(!dma_resv_test_signaled(xe_vm_resv(xe_vma_vm(vma)),
DMA_RESV_USAGE_BOOKKEEP));
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index 84fa41b9fa20..6f019a612686 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -52,26 +52,21 @@ struct xe_userptr {
struct list_head invalidate_link;
/** @userptr: link into VM repin list if userptr. */
struct list_head repin_link;
+ /**
+ * @pages: gpusvm pages for this user pointer.
+ */
+ struct drm_gpusvm_pages pages;
/**
* @notifier: MMU notifier for user pointer (invalidation call back)
*/
struct mmu_interval_notifier notifier;
- /** @sgt: storage for a scatter gather table */
- struct sg_table sgt;
- /** @sg: allocated scatter gather table */
- struct sg_table *sg;
- /** @notifier_seq: notifier sequence number */
- unsigned long notifier_seq;
- /** @unmap_mutex: Mutex protecting dma-unmapping */
- struct mutex unmap_mutex;
+
/**
* @initial_bind: user pointer has been bound at least once.
- * write: vm->userptr.notifier_lock in read mode and vm->resv held.
- * read: vm->userptr.notifier_lock in write mode or vm->resv held.
+ * write: vm->svm.gpusvm.notifier_lock in read mode and vm->resv held.
+ * read: vm->svm.gpusvm.notifier_lock in write mode or vm->resv held.
*/
bool initial_bind;
- /** @mapped: Whether the @sgt sg-table is dma-mapped. Protected by @unmap_mutex. */
- bool mapped;
#if IS_ENABLED(CONFIG_DRM_XE_USERPTR_INVAL_INJECT)
u32 divisor;
#endif
@@ -109,7 +104,7 @@ struct xe_vma {
/**
* @tile_present: GT 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,
+ * vm->svm.gpusvm.notifier_lock for writing. Needs either for reading,
* but if reading is done under the vm->lock only, it needs to be held
* in write mode.
*/
@@ -243,11 +238,6 @@ struct xe_vm {
* and needs repinning. Protected by @lock.
*/
struct list_head repin_list;
- /**
- * @notifier_lock: protects notifier in write mode and
- * submission in read mode.
- */
- struct rw_semaphore notifier_lock;
/**
* @userptr.invalidated_lock: Protects the
* @userptr.invalidated list.
--
2.48.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr
2025-03-28 18:10 [PATCH v2 0/7] Replace xe_hmm with gpusvm Matthew Auld
` (5 preceding siblings ...)
2025-03-28 18:10 ` [PATCH v2 6/7] drm/xe/userptr: replace xe_hmm with gpusvm Matthew Auld
@ 2025-03-28 18:10 ` Matthew Auld
2025-04-03 21:23 ` Matthew Brost
2025-04-03 21:25 ` Matthew Brost
2025-03-28 20:46 ` ✓ CI.Patch_applied: success for Replace xe_hmm with gpusvm (rev2) Patchwork
` (2 subsequent siblings)
9 siblings, 2 replies; 19+ messages in thread
From: Matthew Auld @ 2025-03-28 18:10 UTC (permalink / raw)
To: intel-xe
Cc: dri-devel, Matthew Brost, Himal Prasad Ghimiray,
Thomas Hellström
We now use the same notifier lock for SVM and userptr, with that we can
combine xe_pt_userptr_pre_commit and xe_pt_svm_pre_commit.
Suggested-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
drivers/gpu/drm/xe/xe_pt.c | 95 +++++++++++++-------------------------
1 file changed, 33 insertions(+), 62 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index b097c91e2e02..947b82aa19a6 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -1396,7 +1396,7 @@ static int op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op,
return err;
}
-static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
+static int xe_pt_svm_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
{
struct xe_vm *vm = pt_update->vops->vm;
struct xe_vma_ops *vops = pt_update->vops;
@@ -1409,55 +1409,40 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
if (err)
return err;
- down_read(&vm->svm.gpusvm.notifier_lock);
+ drm_gpusvm_notifier_lock(&vm->svm.gpusvm);
list_for_each_entry(op, &vops->list, link) {
- err = op_check_userptr(vm, op, pt_update_ops);
- if (err) {
- up_read(&vm->svm.gpusvm.notifier_lock);
- break;
+ if (pt_update_ops->needs_svm_lock) {
+#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
+ struct xe_svm_range *range = op->map_range.range;
+
+ if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
+ continue;
+
+ xe_svm_range_debug(range, "PRE-COMMIT");
+
+ xe_assert(vm->xe,
+ xe_vma_is_cpu_addr_mirror(op->map_range.vma));
+ xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
+
+ if (!xe_svm_range_pages_valid(range)) {
+ xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
+ drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
+ return -EAGAIN;
+ }
+#endif
+ } else {
+ err = op_check_userptr(vm, op, pt_update_ops);
+ if (err) {
+ drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
+ break;
+ }
}
}
return err;
}
-#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
-static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update)
-{
- struct xe_vm *vm = pt_update->vops->vm;
- struct xe_vma_ops *vops = pt_update->vops;
- struct xe_vma_op *op;
- int err;
-
- err = xe_pt_pre_commit(pt_update);
- if (err)
- return err;
-
- xe_svm_notifier_lock(vm);
-
- list_for_each_entry(op, &vops->list, link) {
- struct xe_svm_range *range = op->map_range.range;
-
- if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
- continue;
-
- xe_svm_range_debug(range, "PRE-COMMIT");
-
- xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma));
- xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
-
- if (!xe_svm_range_pages_valid(range)) {
- xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
- xe_svm_notifier_unlock(vm);
- return -EAGAIN;
- }
- }
-
- return 0;
-}
-#endif
-
struct invalidation_fence {
struct xe_gt_tlb_invalidation_fence base;
struct xe_gt *gt;
@@ -2255,22 +2240,12 @@ static const struct xe_migrate_pt_update_ops migrate_ops = {
.pre_commit = xe_pt_pre_commit,
};
-static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
+static const struct xe_migrate_pt_update_ops svm_userptr_migrate_ops = {
.populate = xe_vm_populate_pgtable,
.clear = xe_migrate_clear_pgtable_callback,
- .pre_commit = xe_pt_userptr_pre_commit,
+ .pre_commit = xe_pt_svm_userptr_pre_commit,
};
-#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
-static const struct xe_migrate_pt_update_ops svm_migrate_ops = {
- .populate = xe_vm_populate_pgtable,
- .clear = xe_migrate_clear_pgtable_callback,
- .pre_commit = xe_pt_svm_pre_commit,
-};
-#else
-static const struct xe_migrate_pt_update_ops svm_migrate_ops;
-#endif
-
/**
* xe_pt_update_ops_run() - Run PT update operations
* @tile: Tile of PT update operations
@@ -2296,10 +2271,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
struct xe_vma_op *op;
int err = 0, i;
struct xe_migrate_pt_update update = {
- .ops = pt_update_ops->needs_svm_lock ?
- &svm_migrate_ops :
- pt_update_ops->needs_userptr_lock ?
- &userptr_migrate_ops :
+ .ops = pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock ?
+ &svm_userptr_migrate_ops :
&migrate_ops,
.vops = vops,
.tile_id = tile->id,
@@ -2419,10 +2392,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
&ifence->base.base, &mfence->base.base);
}
- if (pt_update_ops->needs_svm_lock)
- xe_svm_notifier_unlock(vm);
- if (pt_update_ops->needs_userptr_lock)
- up_read(&vm->svm.gpusvm.notifier_lock);
+ if (pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock)
+ drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
return fence;
--
2.48.1
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr
2025-03-28 18:10 ` [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr Matthew Auld
@ 2025-04-03 21:23 ` Matthew Brost
2025-04-04 8:20 ` Matthew Auld
2025-04-03 21:25 ` Matthew Brost
1 sibling, 1 reply; 19+ messages in thread
From: Matthew Brost @ 2025-04-03 21:23 UTC (permalink / raw)
To: Matthew Auld
Cc: intel-xe, dri-devel, Himal Prasad Ghimiray, Thomas Hellström
On Fri, Mar 28, 2025 at 06:10:36PM +0000, Matthew Auld wrote:
> We now use the same notifier lock for SVM and userptr, with that we can
> combine xe_pt_userptr_pre_commit and xe_pt_svm_pre_commit.
>
> Suggested-by: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> ---
> drivers/gpu/drm/xe/xe_pt.c | 95 +++++++++++++-------------------------
> 1 file changed, 33 insertions(+), 62 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index b097c91e2e02..947b82aa19a6 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -1396,7 +1396,7 @@ static int op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op,
> return err;
> }
>
> -static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> +static int xe_pt_svm_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> {
> struct xe_vm *vm = pt_update->vops->vm;
> struct xe_vma_ops *vops = pt_update->vops;
> @@ -1409,55 +1409,40 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> if (err)
> return err;
>
> - down_read(&vm->svm.gpusvm.notifier_lock);
> + drm_gpusvm_notifier_lock(&vm->svm.gpusvm);
>
> list_for_each_entry(op, &vops->list, link) {
> - err = op_check_userptr(vm, op, pt_update_ops);
> - if (err) {
> - up_read(&vm->svm.gpusvm.notifier_lock);
> - break;
> + if (pt_update_ops->needs_svm_lock) {
> +#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> + struct xe_svm_range *range = op->map_range.range;
> +
> + if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
> + continue;
> +
> + xe_svm_range_debug(range, "PRE-COMMIT");
> +
> + xe_assert(vm->xe,
> + xe_vma_is_cpu_addr_mirror(op->map_range.vma));
> + xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
> +
> + if (!xe_svm_range_pages_valid(range)) {
> + xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
> + return -EAGAIN;
> + }
> +#endif
> + } else {
> + err = op_check_userptr(vm, op, pt_update_ops);
I think it would be better to combine needs_svm_lock into a single
variable, rename op_check_userptr to op_check_svm_userptr, and then add
the code in the above if statement to op_check_svm_userptr. Yes, the way
have it coded now works but when Himal's code for SVM prefetch lands a
VM operation list could have both userptr binds and binds SVM within
single list. Changing it per my suggestion should make that work too.
Matt
> + if (err) {
> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
> + break;
> + }
> }
> }
>
> return err;
> }
>
> -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> -static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update)
> -{
> - struct xe_vm *vm = pt_update->vops->vm;
> - struct xe_vma_ops *vops = pt_update->vops;
> - struct xe_vma_op *op;
> - int err;
> -
> - err = xe_pt_pre_commit(pt_update);
> - if (err)
> - return err;
> -
> - xe_svm_notifier_lock(vm);
> -
> - list_for_each_entry(op, &vops->list, link) {
> - struct xe_svm_range *range = op->map_range.range;
> -
> - if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
> - continue;
> -
> - xe_svm_range_debug(range, "PRE-COMMIT");
> -
> - xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma));
> - xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
> -
> - if (!xe_svm_range_pages_valid(range)) {
> - xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
> - xe_svm_notifier_unlock(vm);
> - return -EAGAIN;
> - }
> - }
> -
> - return 0;
> -}
> -#endif
> -
> struct invalidation_fence {
> struct xe_gt_tlb_invalidation_fence base;
> struct xe_gt *gt;
> @@ -2255,22 +2240,12 @@ static const struct xe_migrate_pt_update_ops migrate_ops = {
> .pre_commit = xe_pt_pre_commit,
> };
>
> -static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
> +static const struct xe_migrate_pt_update_ops svm_userptr_migrate_ops = {
> .populate = xe_vm_populate_pgtable,
> .clear = xe_migrate_clear_pgtable_callback,
> - .pre_commit = xe_pt_userptr_pre_commit,
> + .pre_commit = xe_pt_svm_userptr_pre_commit,
> };
>
> -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> -static const struct xe_migrate_pt_update_ops svm_migrate_ops = {
> - .populate = xe_vm_populate_pgtable,
> - .clear = xe_migrate_clear_pgtable_callback,
> - .pre_commit = xe_pt_svm_pre_commit,
> -};
> -#else
> -static const struct xe_migrate_pt_update_ops svm_migrate_ops;
> -#endif
> -
> /**
> * xe_pt_update_ops_run() - Run PT update operations
> * @tile: Tile of PT update operations
> @@ -2296,10 +2271,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> struct xe_vma_op *op;
> int err = 0, i;
> struct xe_migrate_pt_update update = {
> - .ops = pt_update_ops->needs_svm_lock ?
> - &svm_migrate_ops :
> - pt_update_ops->needs_userptr_lock ?
> - &userptr_migrate_ops :
> + .ops = pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock ?
> + &svm_userptr_migrate_ops :
> &migrate_ops,
> .vops = vops,
> .tile_id = tile->id,
> @@ -2419,10 +2392,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> &ifence->base.base, &mfence->base.base);
> }
>
> - if (pt_update_ops->needs_svm_lock)
> - xe_svm_notifier_unlock(vm);
> - if (pt_update_ops->needs_userptr_lock)
> - up_read(&vm->svm.gpusvm.notifier_lock);
> + if (pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock)
> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
>
> return fence;
>
> --
> 2.48.1
>
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr
2025-04-03 21:23 ` Matthew Brost
@ 2025-04-04 8:20 ` Matthew Auld
0 siblings, 0 replies; 19+ messages in thread
From: Matthew Auld @ 2025-04-04 8:20 UTC (permalink / raw)
To: Matthew Brost
Cc: intel-xe, dri-devel, Himal Prasad Ghimiray, Thomas Hellström
On 03/04/2025 22:23, Matthew Brost wrote:
> On Fri, Mar 28, 2025 at 06:10:36PM +0000, Matthew Auld wrote:
>> We now use the same notifier lock for SVM and userptr, with that we can
>> combine xe_pt_userptr_pre_commit and xe_pt_svm_pre_commit.
>>
>> Suggested-by: Matthew Brost <matthew.brost@intel.com>
>> Signed-off-by: Matthew Auld <matthew.auld@intel.com>
>> Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> ---
>> drivers/gpu/drm/xe/xe_pt.c | 95 +++++++++++++-------------------------
>> 1 file changed, 33 insertions(+), 62 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
>> index b097c91e2e02..947b82aa19a6 100644
>> --- a/drivers/gpu/drm/xe/xe_pt.c
>> +++ b/drivers/gpu/drm/xe/xe_pt.c
>> @@ -1396,7 +1396,7 @@ static int op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op,
>> return err;
>> }
>>
>> -static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
>> +static int xe_pt_svm_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
>> {
>> struct xe_vm *vm = pt_update->vops->vm;
>> struct xe_vma_ops *vops = pt_update->vops;
>> @@ -1409,55 +1409,40 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
>> if (err)
>> return err;
>>
>> - down_read(&vm->svm.gpusvm.notifier_lock);
>> + drm_gpusvm_notifier_lock(&vm->svm.gpusvm);
>>
>> list_for_each_entry(op, &vops->list, link) {
>> - err = op_check_userptr(vm, op, pt_update_ops);
>> - if (err) {
>> - up_read(&vm->svm.gpusvm.notifier_lock);
>> - break;
>> + if (pt_update_ops->needs_svm_lock) {
>> +#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
>> + struct xe_svm_range *range = op->map_range.range;
>> +
>> + if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
>> + continue;
>> +
>> + xe_svm_range_debug(range, "PRE-COMMIT");
>> +
>> + xe_assert(vm->xe,
>> + xe_vma_is_cpu_addr_mirror(op->map_range.vma));
>> + xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
>> +
>> + if (!xe_svm_range_pages_valid(range)) {
>> + xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
>> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
>> + return -EAGAIN;
>> + }
>> +#endif
>> + } else {
>> + err = op_check_userptr(vm, op, pt_update_ops);
>
> I think it would be better to combine needs_svm_lock into a single
> variable, rename op_check_userptr to op_check_svm_userptr, and then add
> the code in the above if statement to op_check_svm_userptr. Yes, the way
> have it coded now works but when Himal's code for SVM prefetch lands a
> VM operation list could have both userptr binds and binds SVM within
> single list. Changing it per my suggestion should make that work too.
Will try this. Thanks for the comments.
>
> Matt
>
>> + if (err) {
>> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
>> + break;
>> + }
>> }
>> }
>>
>> return err;
>> }
>>
>> -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
>> -static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update)
>> -{
>> - struct xe_vm *vm = pt_update->vops->vm;
>> - struct xe_vma_ops *vops = pt_update->vops;
>> - struct xe_vma_op *op;
>> - int err;
>> -
>> - err = xe_pt_pre_commit(pt_update);
>> - if (err)
>> - return err;
>> -
>> - xe_svm_notifier_lock(vm);
>> -
>> - list_for_each_entry(op, &vops->list, link) {
>> - struct xe_svm_range *range = op->map_range.range;
>> -
>> - if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
>> - continue;
>> -
>> - xe_svm_range_debug(range, "PRE-COMMIT");
>> -
>> - xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma));
>> - xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
>> -
>> - if (!xe_svm_range_pages_valid(range)) {
>> - xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
>> - xe_svm_notifier_unlock(vm);
>> - return -EAGAIN;
>> - }
>> - }
>> -
>> - return 0;
>> -}
>> -#endif
>> -
>> struct invalidation_fence {
>> struct xe_gt_tlb_invalidation_fence base;
>> struct xe_gt *gt;
>> @@ -2255,22 +2240,12 @@ static const struct xe_migrate_pt_update_ops migrate_ops = {
>> .pre_commit = xe_pt_pre_commit,
>> };
>>
>> -static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
>> +static const struct xe_migrate_pt_update_ops svm_userptr_migrate_ops = {
>> .populate = xe_vm_populate_pgtable,
>> .clear = xe_migrate_clear_pgtable_callback,
>> - .pre_commit = xe_pt_userptr_pre_commit,
>> + .pre_commit = xe_pt_svm_userptr_pre_commit,
>> };
>>
>> -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
>> -static const struct xe_migrate_pt_update_ops svm_migrate_ops = {
>> - .populate = xe_vm_populate_pgtable,
>> - .clear = xe_migrate_clear_pgtable_callback,
>> - .pre_commit = xe_pt_svm_pre_commit,
>> -};
>> -#else
>> -static const struct xe_migrate_pt_update_ops svm_migrate_ops;
>> -#endif
>> -
>> /**
>> * xe_pt_update_ops_run() - Run PT update operations
>> * @tile: Tile of PT update operations
>> @@ -2296,10 +2271,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
>> struct xe_vma_op *op;
>> int err = 0, i;
>> struct xe_migrate_pt_update update = {
>> - .ops = pt_update_ops->needs_svm_lock ?
>> - &svm_migrate_ops :
>> - pt_update_ops->needs_userptr_lock ?
>> - &userptr_migrate_ops :
>> + .ops = pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock ?
>> + &svm_userptr_migrate_ops :
>> &migrate_ops,
>> .vops = vops,
>> .tile_id = tile->id,
>> @@ -2419,10 +2392,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
>> &ifence->base.base, &mfence->base.base);
>> }
>>
>> - if (pt_update_ops->needs_svm_lock)
>> - xe_svm_notifier_unlock(vm);
>> - if (pt_update_ops->needs_userptr_lock)
>> - up_read(&vm->svm.gpusvm.notifier_lock);
>> + if (pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock)
>> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
>>
>> return fence;
>>
>> --
>> 2.48.1
>>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr
2025-03-28 18:10 ` [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr Matthew Auld
2025-04-03 21:23 ` Matthew Brost
@ 2025-04-03 21:25 ` Matthew Brost
2025-04-04 8:19 ` Matthew Auld
1 sibling, 1 reply; 19+ messages in thread
From: Matthew Brost @ 2025-04-03 21:25 UTC (permalink / raw)
To: Matthew Auld
Cc: intel-xe, dri-devel, Himal Prasad Ghimiray, Thomas Hellström
On Fri, Mar 28, 2025 at 06:10:36PM +0000, Matthew Auld wrote:
> We now use the same notifier lock for SVM and userptr, with that we can
> combine xe_pt_userptr_pre_commit and xe_pt_svm_pre_commit.
>
> Suggested-by: Matthew Brost <matthew.brost@intel.com>
> Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> ---
> drivers/gpu/drm/xe/xe_pt.c | 95 +++++++++++++-------------------------
> 1 file changed, 33 insertions(+), 62 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index b097c91e2e02..947b82aa19a6 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -1396,7 +1396,7 @@ static int op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op,
> return err;
> }
>
> -static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> +static int xe_pt_svm_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> {
> struct xe_vm *vm = pt_update->vops->vm;
> struct xe_vma_ops *vops = pt_update->vops;
> @@ -1409,55 +1409,40 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> if (err)
> return err;
>
> - down_read(&vm->svm.gpusvm.notifier_lock);
> + drm_gpusvm_notifier_lock(&vm->svm.gpusvm);
Also any reason not use xe_svm_notifier_lock / xe_svm_notifier_unlock wrappers?
Matt
>
> list_for_each_entry(op, &vops->list, link) {
> - err = op_check_userptr(vm, op, pt_update_ops);
> - if (err) {
> - up_read(&vm->svm.gpusvm.notifier_lock);
> - break;
> + if (pt_update_ops->needs_svm_lock) {
> +#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> + struct xe_svm_range *range = op->map_range.range;
> +
> + if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
> + continue;
> +
> + xe_svm_range_debug(range, "PRE-COMMIT");
> +
> + xe_assert(vm->xe,
> + xe_vma_is_cpu_addr_mirror(op->map_range.vma));
> + xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
> +
> + if (!xe_svm_range_pages_valid(range)) {
> + xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
> + return -EAGAIN;
> + }
> +#endif
> + } else {
> + err = op_check_userptr(vm, op, pt_update_ops);
> + if (err) {
> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
> + break;
> + }
> }
> }
>
> return err;
> }
>
> -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> -static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update)
> -{
> - struct xe_vm *vm = pt_update->vops->vm;
> - struct xe_vma_ops *vops = pt_update->vops;
> - struct xe_vma_op *op;
> - int err;
> -
> - err = xe_pt_pre_commit(pt_update);
> - if (err)
> - return err;
> -
> - xe_svm_notifier_lock(vm);
> -
> - list_for_each_entry(op, &vops->list, link) {
> - struct xe_svm_range *range = op->map_range.range;
> -
> - if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
> - continue;
> -
> - xe_svm_range_debug(range, "PRE-COMMIT");
> -
> - xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma));
> - xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
> -
> - if (!xe_svm_range_pages_valid(range)) {
> - xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
> - xe_svm_notifier_unlock(vm);
> - return -EAGAIN;
> - }
> - }
> -
> - return 0;
> -}
> -#endif
> -
> struct invalidation_fence {
> struct xe_gt_tlb_invalidation_fence base;
> struct xe_gt *gt;
> @@ -2255,22 +2240,12 @@ static const struct xe_migrate_pt_update_ops migrate_ops = {
> .pre_commit = xe_pt_pre_commit,
> };
>
> -static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
> +static const struct xe_migrate_pt_update_ops svm_userptr_migrate_ops = {
> .populate = xe_vm_populate_pgtable,
> .clear = xe_migrate_clear_pgtable_callback,
> - .pre_commit = xe_pt_userptr_pre_commit,
> + .pre_commit = xe_pt_svm_userptr_pre_commit,
> };
>
> -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> -static const struct xe_migrate_pt_update_ops svm_migrate_ops = {
> - .populate = xe_vm_populate_pgtable,
> - .clear = xe_migrate_clear_pgtable_callback,
> - .pre_commit = xe_pt_svm_pre_commit,
> -};
> -#else
> -static const struct xe_migrate_pt_update_ops svm_migrate_ops;
> -#endif
> -
> /**
> * xe_pt_update_ops_run() - Run PT update operations
> * @tile: Tile of PT update operations
> @@ -2296,10 +2271,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> struct xe_vma_op *op;
> int err = 0, i;
> struct xe_migrate_pt_update update = {
> - .ops = pt_update_ops->needs_svm_lock ?
> - &svm_migrate_ops :
> - pt_update_ops->needs_userptr_lock ?
> - &userptr_migrate_ops :
> + .ops = pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock ?
> + &svm_userptr_migrate_ops :
> &migrate_ops,
> .vops = vops,
> .tile_id = tile->id,
> @@ -2419,10 +2392,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> &ifence->base.base, &mfence->base.base);
> }
>
> - if (pt_update_ops->needs_svm_lock)
> - xe_svm_notifier_unlock(vm);
> - if (pt_update_ops->needs_userptr_lock)
> - up_read(&vm->svm.gpusvm.notifier_lock);
> + if (pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock)
> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
>
> return fence;
>
> --
> 2.48.1
>
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr
2025-04-03 21:25 ` Matthew Brost
@ 2025-04-04 8:19 ` Matthew Auld
2025-04-04 17:02 ` Matthew Brost
0 siblings, 1 reply; 19+ messages in thread
From: Matthew Auld @ 2025-04-04 8:19 UTC (permalink / raw)
To: Matthew Brost
Cc: intel-xe, dri-devel, Himal Prasad Ghimiray, Thomas Hellström
On 03/04/2025 22:25, Matthew Brost wrote:
> On Fri, Mar 28, 2025 at 06:10:36PM +0000, Matthew Auld wrote:
>> We now use the same notifier lock for SVM and userptr, with that we can
>> combine xe_pt_userptr_pre_commit and xe_pt_svm_pre_commit.
>>
>> Suggested-by: Matthew Brost <matthew.brost@intel.com>
>> Signed-off-by: Matthew Auld <matthew.auld@intel.com>
>> Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>> ---
>> drivers/gpu/drm/xe/xe_pt.c | 95 +++++++++++++-------------------------
>> 1 file changed, 33 insertions(+), 62 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
>> index b097c91e2e02..947b82aa19a6 100644
>> --- a/drivers/gpu/drm/xe/xe_pt.c
>> +++ b/drivers/gpu/drm/xe/xe_pt.c
>> @@ -1396,7 +1396,7 @@ static int op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op,
>> return err;
>> }
>>
>> -static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
>> +static int xe_pt_svm_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
>> {
>> struct xe_vm *vm = pt_update->vops->vm;
>> struct xe_vma_ops *vops = pt_update->vops;
>> @@ -1409,55 +1409,40 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
>> if (err)
>> return err;
>>
>> - down_read(&vm->svm.gpusvm.notifier_lock);
>> + drm_gpusvm_notifier_lock(&vm->svm.gpusvm);
>
> Also any reason not use xe_svm_notifier_lock / xe_svm_notifier_unlock wrappers?
Just that those are hidden behind CONFIG_DRM_XE_GPUSVM, so looks
possible to disable svm, but then I think we should still have working
userptr. Should I pull xe_svm_notifier_lock out of CONFIG_DRM_XE_GPUSVM?
>
> Matt
>
>>
>> list_for_each_entry(op, &vops->list, link) {
>> - err = op_check_userptr(vm, op, pt_update_ops);
>> - if (err) {
>> - up_read(&vm->svm.gpusvm.notifier_lock);
>> - break;
>> + if (pt_update_ops->needs_svm_lock) {
>> +#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
>> + struct xe_svm_range *range = op->map_range.range;
>> +
>> + if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
>> + continue;
>> +
>> + xe_svm_range_debug(range, "PRE-COMMIT");
>> +
>> + xe_assert(vm->xe,
>> + xe_vma_is_cpu_addr_mirror(op->map_range.vma));
>> + xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
>> +
>> + if (!xe_svm_range_pages_valid(range)) {
>> + xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
>> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
>> + return -EAGAIN;
>> + }
>> +#endif
>> + } else {
>> + err = op_check_userptr(vm, op, pt_update_ops);
>> + if (err) {
>> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
>> + break;
>> + }
>> }
>> }
>>
>> return err;
>> }
>>
>> -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
>> -static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update)
>> -{
>> - struct xe_vm *vm = pt_update->vops->vm;
>> - struct xe_vma_ops *vops = pt_update->vops;
>> - struct xe_vma_op *op;
>> - int err;
>> -
>> - err = xe_pt_pre_commit(pt_update);
>> - if (err)
>> - return err;
>> -
>> - xe_svm_notifier_lock(vm);
>> -
>> - list_for_each_entry(op, &vops->list, link) {
>> - struct xe_svm_range *range = op->map_range.range;
>> -
>> - if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
>> - continue;
>> -
>> - xe_svm_range_debug(range, "PRE-COMMIT");
>> -
>> - xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma));
>> - xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
>> -
>> - if (!xe_svm_range_pages_valid(range)) {
>> - xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
>> - xe_svm_notifier_unlock(vm);
>> - return -EAGAIN;
>> - }
>> - }
>> -
>> - return 0;
>> -}
>> -#endif
>> -
>> struct invalidation_fence {
>> struct xe_gt_tlb_invalidation_fence base;
>> struct xe_gt *gt;
>> @@ -2255,22 +2240,12 @@ static const struct xe_migrate_pt_update_ops migrate_ops = {
>> .pre_commit = xe_pt_pre_commit,
>> };
>>
>> -static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
>> +static const struct xe_migrate_pt_update_ops svm_userptr_migrate_ops = {
>> .populate = xe_vm_populate_pgtable,
>> .clear = xe_migrate_clear_pgtable_callback,
>> - .pre_commit = xe_pt_userptr_pre_commit,
>> + .pre_commit = xe_pt_svm_userptr_pre_commit,
>> };
>>
>> -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
>> -static const struct xe_migrate_pt_update_ops svm_migrate_ops = {
>> - .populate = xe_vm_populate_pgtable,
>> - .clear = xe_migrate_clear_pgtable_callback,
>> - .pre_commit = xe_pt_svm_pre_commit,
>> -};
>> -#else
>> -static const struct xe_migrate_pt_update_ops svm_migrate_ops;
>> -#endif
>> -
>> /**
>> * xe_pt_update_ops_run() - Run PT update operations
>> * @tile: Tile of PT update operations
>> @@ -2296,10 +2271,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
>> struct xe_vma_op *op;
>> int err = 0, i;
>> struct xe_migrate_pt_update update = {
>> - .ops = pt_update_ops->needs_svm_lock ?
>> - &svm_migrate_ops :
>> - pt_update_ops->needs_userptr_lock ?
>> - &userptr_migrate_ops :
>> + .ops = pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock ?
>> + &svm_userptr_migrate_ops :
>> &migrate_ops,
>> .vops = vops,
>> .tile_id = tile->id,
>> @@ -2419,10 +2392,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
>> &ifence->base.base, &mfence->base.base);
>> }
>>
>> - if (pt_update_ops->needs_svm_lock)
>> - xe_svm_notifier_unlock(vm);
>> - if (pt_update_ops->needs_userptr_lock)
>> - up_read(&vm->svm.gpusvm.notifier_lock);
>> + if (pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock)
>> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
>>
>> return fence;
>>
>> --
>> 2.48.1
>>
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr
2025-04-04 8:19 ` Matthew Auld
@ 2025-04-04 17:02 ` Matthew Brost
2025-04-07 7:29 ` Matthew Auld
0 siblings, 1 reply; 19+ messages in thread
From: Matthew Brost @ 2025-04-04 17:02 UTC (permalink / raw)
To: Matthew Auld
Cc: intel-xe, dri-devel, Himal Prasad Ghimiray, Thomas Hellström
On Fri, Apr 04, 2025 at 09:19:34AM +0100, Matthew Auld wrote:
> On 03/04/2025 22:25, Matthew Brost wrote:
> > On Fri, Mar 28, 2025 at 06:10:36PM +0000, Matthew Auld wrote:
> > > We now use the same notifier lock for SVM and userptr, with that we can
> > > combine xe_pt_userptr_pre_commit and xe_pt_svm_pre_commit.
> > >
> > > Suggested-by: Matthew Brost <matthew.brost@intel.com>
> > > Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> > > Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> > > Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> > > ---
> > > drivers/gpu/drm/xe/xe_pt.c | 95 +++++++++++++-------------------------
> > > 1 file changed, 33 insertions(+), 62 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> > > index b097c91e2e02..947b82aa19a6 100644
> > > --- a/drivers/gpu/drm/xe/xe_pt.c
> > > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > > @@ -1396,7 +1396,7 @@ static int op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op,
> > > return err;
> > > }
> > > -static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> > > +static int xe_pt_svm_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> > > {
> > > struct xe_vm *vm = pt_update->vops->vm;
> > > struct xe_vma_ops *vops = pt_update->vops;
> > > @@ -1409,55 +1409,40 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> > > if (err)
> > > return err;
> > > - down_read(&vm->svm.gpusvm.notifier_lock);
> > > + drm_gpusvm_notifier_lock(&vm->svm.gpusvm);
> >
> > Also any reason not use xe_svm_notifier_lock / xe_svm_notifier_unlock wrappers?
>
> Just that those are hidden behind CONFIG_DRM_XE_GPUSVM, so looks possible to
> disable svm, but then I think we should still have working userptr. Should I
> pull xe_svm_notifier_lock out of CONFIG_DRM_XE_GPUSVM?
>
How would userptr work without GPU SVM if we building it on top of it?
Matt
> >
> > Matt
> >
> > > list_for_each_entry(op, &vops->list, link) {
> > > - err = op_check_userptr(vm, op, pt_update_ops);
> > > - if (err) {
> > > - up_read(&vm->svm.gpusvm.notifier_lock);
> > > - break;
> > > + if (pt_update_ops->needs_svm_lock) {
> > > +#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> > > + struct xe_svm_range *range = op->map_range.range;
> > > +
> > > + if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
> > > + continue;
> > > +
> > > + xe_svm_range_debug(range, "PRE-COMMIT");
> > > +
> > > + xe_assert(vm->xe,
> > > + xe_vma_is_cpu_addr_mirror(op->map_range.vma));
> > > + xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
> > > +
> > > + if (!xe_svm_range_pages_valid(range)) {
> > > + xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
> > > + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
> > > + return -EAGAIN;
> > > + }
> > > +#endif
> > > + } else {
> > > + err = op_check_userptr(vm, op, pt_update_ops);
> > > + if (err) {
> > > + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
> > > + break;
> > > + }
> > > }
> > > }
> > > return err;
> > > }
> > > -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> > > -static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update)
> > > -{
> > > - struct xe_vm *vm = pt_update->vops->vm;
> > > - struct xe_vma_ops *vops = pt_update->vops;
> > > - struct xe_vma_op *op;
> > > - int err;
> > > -
> > > - err = xe_pt_pre_commit(pt_update);
> > > - if (err)
> > > - return err;
> > > -
> > > - xe_svm_notifier_lock(vm);
> > > -
> > > - list_for_each_entry(op, &vops->list, link) {
> > > - struct xe_svm_range *range = op->map_range.range;
> > > -
> > > - if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
> > > - continue;
> > > -
> > > - xe_svm_range_debug(range, "PRE-COMMIT");
> > > -
> > > - xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma));
> > > - xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
> > > -
> > > - if (!xe_svm_range_pages_valid(range)) {
> > > - xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
> > > - xe_svm_notifier_unlock(vm);
> > > - return -EAGAIN;
> > > - }
> > > - }
> > > -
> > > - return 0;
> > > -}
> > > -#endif
> > > -
> > > struct invalidation_fence {
> > > struct xe_gt_tlb_invalidation_fence base;
> > > struct xe_gt *gt;
> > > @@ -2255,22 +2240,12 @@ static const struct xe_migrate_pt_update_ops migrate_ops = {
> > > .pre_commit = xe_pt_pre_commit,
> > > };
> > > -static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
> > > +static const struct xe_migrate_pt_update_ops svm_userptr_migrate_ops = {
> > > .populate = xe_vm_populate_pgtable,
> > > .clear = xe_migrate_clear_pgtable_callback,
> > > - .pre_commit = xe_pt_userptr_pre_commit,
> > > + .pre_commit = xe_pt_svm_userptr_pre_commit,
> > > };
> > > -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> > > -static const struct xe_migrate_pt_update_ops svm_migrate_ops = {
> > > - .populate = xe_vm_populate_pgtable,
> > > - .clear = xe_migrate_clear_pgtable_callback,
> > > - .pre_commit = xe_pt_svm_pre_commit,
> > > -};
> > > -#else
> > > -static const struct xe_migrate_pt_update_ops svm_migrate_ops;
> > > -#endif
> > > -
> > > /**
> > > * xe_pt_update_ops_run() - Run PT update operations
> > > * @tile: Tile of PT update operations
> > > @@ -2296,10 +2271,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> > > struct xe_vma_op *op;
> > > int err = 0, i;
> > > struct xe_migrate_pt_update update = {
> > > - .ops = pt_update_ops->needs_svm_lock ?
> > > - &svm_migrate_ops :
> > > - pt_update_ops->needs_userptr_lock ?
> > > - &userptr_migrate_ops :
> > > + .ops = pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock ?
> > > + &svm_userptr_migrate_ops :
> > > &migrate_ops,
> > > .vops = vops,
> > > .tile_id = tile->id,
> > > @@ -2419,10 +2392,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> > > &ifence->base.base, &mfence->base.base);
> > > }
> > > - if (pt_update_ops->needs_svm_lock)
> > > - xe_svm_notifier_unlock(vm);
> > > - if (pt_update_ops->needs_userptr_lock)
> > > - up_read(&vm->svm.gpusvm.notifier_lock);
> > > + if (pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock)
> > > + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
> > > return fence;
> > > --
> > > 2.48.1
> > >
>
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr
2025-04-04 17:02 ` Matthew Brost
@ 2025-04-07 7:29 ` Matthew Auld
2025-04-23 16:20 ` Matthew Brost
0 siblings, 1 reply; 19+ messages in thread
From: Matthew Auld @ 2025-04-07 7:29 UTC (permalink / raw)
To: Matthew Brost
Cc: intel-xe, dri-devel, Himal Prasad Ghimiray, Thomas Hellström
On 04/04/2025 18:02, Matthew Brost wrote:
> On Fri, Apr 04, 2025 at 09:19:34AM +0100, Matthew Auld wrote:
>> On 03/04/2025 22:25, Matthew Brost wrote:
>>> On Fri, Mar 28, 2025 at 06:10:36PM +0000, Matthew Auld wrote:
>>>> We now use the same notifier lock for SVM and userptr, with that we can
>>>> combine xe_pt_userptr_pre_commit and xe_pt_svm_pre_commit.
>>>>
>>>> Suggested-by: Matthew Brost <matthew.brost@intel.com>
>>>> Signed-off-by: Matthew Auld <matthew.auld@intel.com>
>>>> Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
>>>> Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
>>>> ---
>>>> drivers/gpu/drm/xe/xe_pt.c | 95 +++++++++++++-------------------------
>>>> 1 file changed, 33 insertions(+), 62 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
>>>> index b097c91e2e02..947b82aa19a6 100644
>>>> --- a/drivers/gpu/drm/xe/xe_pt.c
>>>> +++ b/drivers/gpu/drm/xe/xe_pt.c
>>>> @@ -1396,7 +1396,7 @@ static int op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op,
>>>> return err;
>>>> }
>>>> -static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
>>>> +static int xe_pt_svm_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
>>>> {
>>>> struct xe_vm *vm = pt_update->vops->vm;
>>>> struct xe_vma_ops *vops = pt_update->vops;
>>>> @@ -1409,55 +1409,40 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
>>>> if (err)
>>>> return err;
>>>> - down_read(&vm->svm.gpusvm.notifier_lock);
>>>> + drm_gpusvm_notifier_lock(&vm->svm.gpusvm);
>>>
>>> Also any reason not use xe_svm_notifier_lock / xe_svm_notifier_unlock wrappers?
>>
>> Just that those are hidden behind CONFIG_DRM_XE_GPUSVM, so looks possible to
>> disable svm, but then I think we should still have working userptr. Should I
>> pull xe_svm_notifier_lock out of CONFIG_DRM_XE_GPUSVM?
>>
>
> How would userptr work without GPU SVM if we building it on top of it?
Here I mean CONFIG_DRM_*XE*_GPUSVM, which looks to be specific to
everything around xe_svm.c AFAICT, which useptr doesn't touch. We do now
ofc require DRM_GPUSVM by default, but that's a different config.
>
> Matt
>
>>>
>>> Matt
>>>
>>>> list_for_each_entry(op, &vops->list, link) {
>>>> - err = op_check_userptr(vm, op, pt_update_ops);
>>>> - if (err) {
>>>> - up_read(&vm->svm.gpusvm.notifier_lock);
>>>> - break;
>>>> + if (pt_update_ops->needs_svm_lock) {
>>>> +#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
>>>> + struct xe_svm_range *range = op->map_range.range;
>>>> +
>>>> + if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
>>>> + continue;
>>>> +
>>>> + xe_svm_range_debug(range, "PRE-COMMIT");
>>>> +
>>>> + xe_assert(vm->xe,
>>>> + xe_vma_is_cpu_addr_mirror(op->map_range.vma));
>>>> + xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
>>>> +
>>>> + if (!xe_svm_range_pages_valid(range)) {
>>>> + xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
>>>> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
>>>> + return -EAGAIN;
>>>> + }
>>>> +#endif
>>>> + } else {
>>>> + err = op_check_userptr(vm, op, pt_update_ops);
>>>> + if (err) {
>>>> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
>>>> + break;
>>>> + }
>>>> }
>>>> }
>>>> return err;
>>>> }
>>>> -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
>>>> -static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update)
>>>> -{
>>>> - struct xe_vm *vm = pt_update->vops->vm;
>>>> - struct xe_vma_ops *vops = pt_update->vops;
>>>> - struct xe_vma_op *op;
>>>> - int err;
>>>> -
>>>> - err = xe_pt_pre_commit(pt_update);
>>>> - if (err)
>>>> - return err;
>>>> -
>>>> - xe_svm_notifier_lock(vm);
>>>> -
>>>> - list_for_each_entry(op, &vops->list, link) {
>>>> - struct xe_svm_range *range = op->map_range.range;
>>>> -
>>>> - if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
>>>> - continue;
>>>> -
>>>> - xe_svm_range_debug(range, "PRE-COMMIT");
>>>> -
>>>> - xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma));
>>>> - xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
>>>> -
>>>> - if (!xe_svm_range_pages_valid(range)) {
>>>> - xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
>>>> - xe_svm_notifier_unlock(vm);
>>>> - return -EAGAIN;
>>>> - }
>>>> - }
>>>> -
>>>> - return 0;
>>>> -}
>>>> -#endif
>>>> -
>>>> struct invalidation_fence {
>>>> struct xe_gt_tlb_invalidation_fence base;
>>>> struct xe_gt *gt;
>>>> @@ -2255,22 +2240,12 @@ static const struct xe_migrate_pt_update_ops migrate_ops = {
>>>> .pre_commit = xe_pt_pre_commit,
>>>> };
>>>> -static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
>>>> +static const struct xe_migrate_pt_update_ops svm_userptr_migrate_ops = {
>>>> .populate = xe_vm_populate_pgtable,
>>>> .clear = xe_migrate_clear_pgtable_callback,
>>>> - .pre_commit = xe_pt_userptr_pre_commit,
>>>> + .pre_commit = xe_pt_svm_userptr_pre_commit,
>>>> };
>>>> -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
>>>> -static const struct xe_migrate_pt_update_ops svm_migrate_ops = {
>>>> - .populate = xe_vm_populate_pgtable,
>>>> - .clear = xe_migrate_clear_pgtable_callback,
>>>> - .pre_commit = xe_pt_svm_pre_commit,
>>>> -};
>>>> -#else
>>>> -static const struct xe_migrate_pt_update_ops svm_migrate_ops;
>>>> -#endif
>>>> -
>>>> /**
>>>> * xe_pt_update_ops_run() - Run PT update operations
>>>> * @tile: Tile of PT update operations
>>>> @@ -2296,10 +2271,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
>>>> struct xe_vma_op *op;
>>>> int err = 0, i;
>>>> struct xe_migrate_pt_update update = {
>>>> - .ops = pt_update_ops->needs_svm_lock ?
>>>> - &svm_migrate_ops :
>>>> - pt_update_ops->needs_userptr_lock ?
>>>> - &userptr_migrate_ops :
>>>> + .ops = pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock ?
>>>> + &svm_userptr_migrate_ops :
>>>> &migrate_ops,
>>>> .vops = vops,
>>>> .tile_id = tile->id,
>>>> @@ -2419,10 +2392,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
>>>> &ifence->base.base, &mfence->base.base);
>>>> }
>>>> - if (pt_update_ops->needs_svm_lock)
>>>> - xe_svm_notifier_unlock(vm);
>>>> - if (pt_update_ops->needs_userptr_lock)
>>>> - up_read(&vm->svm.gpusvm.notifier_lock);
>>>> + if (pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock)
>>>> + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
>>>> return fence;
>>>> --
>>>> 2.48.1
>>>>
>>
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr
2025-04-07 7:29 ` Matthew Auld
@ 2025-04-23 16:20 ` Matthew Brost
0 siblings, 0 replies; 19+ messages in thread
From: Matthew Brost @ 2025-04-23 16:20 UTC (permalink / raw)
To: Matthew Auld
Cc: intel-xe, dri-devel, Himal Prasad Ghimiray, Thomas Hellström
On Mon, Apr 07, 2025 at 08:29:11AM +0100, Matthew Auld wrote:
> On 04/04/2025 18:02, Matthew Brost wrote:
> > On Fri, Apr 04, 2025 at 09:19:34AM +0100, Matthew Auld wrote:
> > > On 03/04/2025 22:25, Matthew Brost wrote:
> > > > On Fri, Mar 28, 2025 at 06:10:36PM +0000, Matthew Auld wrote:
> > > > > We now use the same notifier lock for SVM and userptr, with that we can
> > > > > combine xe_pt_userptr_pre_commit and xe_pt_svm_pre_commit.
> > > > >
> > > > > Suggested-by: Matthew Brost <matthew.brost@intel.com>
> > > > > Signed-off-by: Matthew Auld <matthew.auld@intel.com>
> > > > > Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
> > > > > Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
> > > > > ---
> > > > > drivers/gpu/drm/xe/xe_pt.c | 95 +++++++++++++-------------------------
> > > > > 1 file changed, 33 insertions(+), 62 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> > > > > index b097c91e2e02..947b82aa19a6 100644
> > > > > --- a/drivers/gpu/drm/xe/xe_pt.c
> > > > > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > > > > @@ -1396,7 +1396,7 @@ static int op_check_userptr(struct xe_vm *vm, struct xe_vma_op *op,
> > > > > return err;
> > > > > }
> > > > > -static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> > > > > +static int xe_pt_svm_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> > > > > {
> > > > > struct xe_vm *vm = pt_update->vops->vm;
> > > > > struct xe_vma_ops *vops = pt_update->vops;
> > > > > @@ -1409,55 +1409,40 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
> > > > > if (err)
> > > > > return err;
> > > > > - down_read(&vm->svm.gpusvm.notifier_lock);
> > > > > + drm_gpusvm_notifier_lock(&vm->svm.gpusvm);
> > > >
> > > > Also any reason not use xe_svm_notifier_lock / xe_svm_notifier_unlock wrappers?
> > >
> > > Just that those are hidden behind CONFIG_DRM_XE_GPUSVM, so looks possible to
> > > disable svm, but then I think we should still have working userptr. Should I
> > > pull xe_svm_notifier_lock out of CONFIG_DRM_XE_GPUSVM?
> > >
> >
> > How would userptr work without GPU SVM if we building it on top of it?
>
> Here I mean CONFIG_DRM_*XE*_GPUSVM, which looks to be specific to everything
> around xe_svm.c AFAICT, which useptr doesn't touch. We do now ofc require
> DRM_GPUSVM by default, but that's a different config.
>
Ah ok, that makes sense I guess. We could pull xe_svm_notifier_lock /
xe_svm_notifier_unlock out these functions to not be hidden behind
CONFIG_DRM_*XE*_GPUSVM though.
Matt
> >
> > Matt
> >
> > > >
> > > > Matt
> > > >
> > > > > list_for_each_entry(op, &vops->list, link) {
> > > > > - err = op_check_userptr(vm, op, pt_update_ops);
> > > > > - if (err) {
> > > > > - up_read(&vm->svm.gpusvm.notifier_lock);
> > > > > - break;
> > > > > + if (pt_update_ops->needs_svm_lock) {
> > > > > +#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> > > > > + struct xe_svm_range *range = op->map_range.range;
> > > > > +
> > > > > + if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
> > > > > + continue;
> > > > > +
> > > > > + xe_svm_range_debug(range, "PRE-COMMIT");
> > > > > +
> > > > > + xe_assert(vm->xe,
> > > > > + xe_vma_is_cpu_addr_mirror(op->map_range.vma));
> > > > > + xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
> > > > > +
> > > > > + if (!xe_svm_range_pages_valid(range)) {
> > > > > + xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
> > > > > + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
> > > > > + return -EAGAIN;
> > > > > + }
> > > > > +#endif
> > > > > + } else {
> > > > > + err = op_check_userptr(vm, op, pt_update_ops);
> > > > > + if (err) {
> > > > > + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
> > > > > + break;
> > > > > + }
> > > > > }
> > > > > }
> > > > > return err;
> > > > > }
> > > > > -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> > > > > -static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update)
> > > > > -{
> > > > > - struct xe_vm *vm = pt_update->vops->vm;
> > > > > - struct xe_vma_ops *vops = pt_update->vops;
> > > > > - struct xe_vma_op *op;
> > > > > - int err;
> > > > > -
> > > > > - err = xe_pt_pre_commit(pt_update);
> > > > > - if (err)
> > > > > - return err;
> > > > > -
> > > > > - xe_svm_notifier_lock(vm);
> > > > > -
> > > > > - list_for_each_entry(op, &vops->list, link) {
> > > > > - struct xe_svm_range *range = op->map_range.range;
> > > > > -
> > > > > - if (op->subop == XE_VMA_SUBOP_UNMAP_RANGE)
> > > > > - continue;
> > > > > -
> > > > > - xe_svm_range_debug(range, "PRE-COMMIT");
> > > > > -
> > > > > - xe_assert(vm->xe, xe_vma_is_cpu_addr_mirror(op->map_range.vma));
> > > > > - xe_assert(vm->xe, op->subop == XE_VMA_SUBOP_MAP_RANGE);
> > > > > -
> > > > > - if (!xe_svm_range_pages_valid(range)) {
> > > > > - xe_svm_range_debug(range, "PRE-COMMIT - RETRY");
> > > > > - xe_svm_notifier_unlock(vm);
> > > > > - return -EAGAIN;
> > > > > - }
> > > > > - }
> > > > > -
> > > > > - return 0;
> > > > > -}
> > > > > -#endif
> > > > > -
> > > > > struct invalidation_fence {
> > > > > struct xe_gt_tlb_invalidation_fence base;
> > > > > struct xe_gt *gt;
> > > > > @@ -2255,22 +2240,12 @@ static const struct xe_migrate_pt_update_ops migrate_ops = {
> > > > > .pre_commit = xe_pt_pre_commit,
> > > > > };
> > > > > -static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
> > > > > +static const struct xe_migrate_pt_update_ops svm_userptr_migrate_ops = {
> > > > > .populate = xe_vm_populate_pgtable,
> > > > > .clear = xe_migrate_clear_pgtable_callback,
> > > > > - .pre_commit = xe_pt_userptr_pre_commit,
> > > > > + .pre_commit = xe_pt_svm_userptr_pre_commit,
> > > > > };
> > > > > -#if IS_ENABLED(CONFIG_DRM_XE_GPUSVM)
> > > > > -static const struct xe_migrate_pt_update_ops svm_migrate_ops = {
> > > > > - .populate = xe_vm_populate_pgtable,
> > > > > - .clear = xe_migrate_clear_pgtable_callback,
> > > > > - .pre_commit = xe_pt_svm_pre_commit,
> > > > > -};
> > > > > -#else
> > > > > -static const struct xe_migrate_pt_update_ops svm_migrate_ops;
> > > > > -#endif
> > > > > -
> > > > > /**
> > > > > * xe_pt_update_ops_run() - Run PT update operations
> > > > > * @tile: Tile of PT update operations
> > > > > @@ -2296,10 +2271,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> > > > > struct xe_vma_op *op;
> > > > > int err = 0, i;
> > > > > struct xe_migrate_pt_update update = {
> > > > > - .ops = pt_update_ops->needs_svm_lock ?
> > > > > - &svm_migrate_ops :
> > > > > - pt_update_ops->needs_userptr_lock ?
> > > > > - &userptr_migrate_ops :
> > > > > + .ops = pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock ?
> > > > > + &svm_userptr_migrate_ops :
> > > > > &migrate_ops,
> > > > > .vops = vops,
> > > > > .tile_id = tile->id,
> > > > > @@ -2419,10 +2392,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> > > > > &ifence->base.base, &mfence->base.base);
> > > > > }
> > > > > - if (pt_update_ops->needs_svm_lock)
> > > > > - xe_svm_notifier_unlock(vm);
> > > > > - if (pt_update_ops->needs_userptr_lock)
> > > > > - up_read(&vm->svm.gpusvm.notifier_lock);
> > > > > + if (pt_update_ops->needs_svm_lock || pt_update_ops->needs_userptr_lock)
> > > > > + drm_gpusvm_notifier_unlock(&vm->svm.gpusvm);
> > > > > return fence;
> > > > > --
> > > > > 2.48.1
> > > > >
> > >
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* ✓ CI.Patch_applied: success for Replace xe_hmm with gpusvm (rev2)
2025-03-28 18:10 [PATCH v2 0/7] Replace xe_hmm with gpusvm Matthew Auld
` (6 preceding siblings ...)
2025-03-28 18:10 ` [PATCH v2 7/7] drm/xe/pt: unify xe_pt_svm_pre_commit with userptr Matthew Auld
@ 2025-03-28 20:46 ` Patchwork
2025-03-28 20:47 ` ✗ CI.checkpatch: warning " Patchwork
2025-03-28 20:47 ` ✗ CI.KUnit: failure " Patchwork
9 siblings, 0 replies; 19+ messages in thread
From: Patchwork @ 2025-03-28 20:46 UTC (permalink / raw)
To: Matthew Auld; +Cc: intel-xe
== Series Details ==
Series: Replace xe_hmm with gpusvm (rev2)
URL : https://patchwork.freedesktop.org/series/146553/
State : success
== Summary ==
=== Applying kernel patches on branch 'drm-tip' with base: ===
Base commit: b8a000ee8dbf drm-tip: 2025y-03m-28d-19h-59m-23s UTC integration manifest
=== git am output follows ===
Applying: drm/gpusvm: fix hmm_pfn_to_map_order() usage
Applying: drm/gpusvm: use more selective dma dir in get_pages()
Applying: drm/gpusvm: pull out drm_gpusvm_pages substructure
Applying: drm/gpusvm: refactor core API to use pages struct
Applying: drm/gpusvm: export drm_gpusvm_pages API
Applying: drm/xe/userptr: replace xe_hmm with gpusvm
Applying: drm/xe/pt: unify xe_pt_svm_pre_commit with userptr
^ permalink raw reply [flat|nested] 19+ messages in thread* ✗ CI.checkpatch: warning for Replace xe_hmm with gpusvm (rev2)
2025-03-28 18:10 [PATCH v2 0/7] Replace xe_hmm with gpusvm Matthew Auld
` (7 preceding siblings ...)
2025-03-28 20:46 ` ✓ CI.Patch_applied: success for Replace xe_hmm with gpusvm (rev2) Patchwork
@ 2025-03-28 20:47 ` Patchwork
2025-03-28 20:47 ` ✗ CI.KUnit: failure " Patchwork
9 siblings, 0 replies; 19+ messages in thread
From: Patchwork @ 2025-03-28 20:47 UTC (permalink / raw)
To: Matthew Auld; +Cc: intel-xe
== Series Details ==
Series: Replace xe_hmm with gpusvm (rev2)
URL : https://patchwork.freedesktop.org/series/146553/
State : warning
== Summary ==
+ KERNEL=/kernel
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools mt
Cloning into 'mt'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ git -C mt rev-list -n1 origin/master
99e5a866b5e13f134e606a3e29d9508d97826fb3
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ git log -n1
commit 3f609c821a5c6f5a929e9c2956db2af12ca961c8
Author: Matthew Auld <matthew.auld@intel.com>
Date: Fri Mar 28 18:10:36 2025 +0000
drm/xe/pt: unify xe_pt_svm_pre_commit with userptr
We now use the same notifier lock for SVM and userptr, with that we can
combine xe_pt_userptr_pre_commit and xe_pt_svm_pre_commit.
Suggested-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+ /mt/dim checkpatch b8a000ee8dbf41db533796cefbfb275cd306eb5b drm-intel
929bce4fd08d drm/gpusvm: fix hmm_pfn_to_map_order() usage
-:19: WARNING:BAD_REPORTED_BY_LINK: Reported-by: should be immediately followed by Closes: with a URL to the report
#19:
Reported-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
total: 0 errors, 1 warnings, 0 checks, 51 lines checked
616e715847a0 drm/gpusvm: use more selective dma dir in get_pages()
cfa7c02bfb7d drm/gpusvm: pull out drm_gpusvm_pages substructure
6d8e98d48cd9 drm/gpusvm: refactor core API to use pages struct
9f6fcb323d0a drm/gpusvm: export drm_gpusvm_pages API
2a3bd6491d32 drm/xe/userptr: replace xe_hmm with gpusvm
-:79: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#79:
deleted file mode 100644
total: 0 errors, 1 warnings, 0 checks, 436 lines checked
3f609c821a5c drm/xe/pt: unify xe_pt_svm_pre_commit with userptr
^ permalink raw reply [flat|nested] 19+ messages in thread* ✗ CI.KUnit: failure for Replace xe_hmm with gpusvm (rev2)
2025-03-28 18:10 [PATCH v2 0/7] Replace xe_hmm with gpusvm Matthew Auld
` (8 preceding siblings ...)
2025-03-28 20:47 ` ✗ CI.checkpatch: warning " Patchwork
@ 2025-03-28 20:47 ` Patchwork
9 siblings, 0 replies; 19+ messages in thread
From: Patchwork @ 2025-03-28 20:47 UTC (permalink / raw)
To: Matthew Auld; +Cc: intel-xe
== Series Details ==
Series: Replace xe_hmm with gpusvm (rev2)
URL : https://patchwork.freedesktop.org/series/146553/
State : failure
== Summary ==
+ trap cleanup EXIT
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
ERROR:root:../lib/iomap.c:156:5: warning: no previous prototype for ‘ioread64_lo_hi’ [-Wmissing-prototypes]
156 | u64 ioread64_lo_hi(const void __iomem *addr)
| ^~~~~~~~~~~~~~
../lib/iomap.c:163:5: warning: no previous prototype for ‘ioread64_hi_lo’ [-Wmissing-prototypes]
163 | u64 ioread64_hi_lo(const void __iomem *addr)
| ^~~~~~~~~~~~~~
../lib/iomap.c:170:5: warning: no previous prototype for ‘ioread64be_lo_hi’ [-Wmissing-prototypes]
170 | u64 ioread64be_lo_hi(const void __iomem *addr)
| ^~~~~~~~~~~~~~~~
../lib/iomap.c:178:5: warning: no previous prototype for ‘ioread64be_hi_lo’ [-Wmissing-prototypes]
178 | u64 ioread64be_hi_lo(const void __iomem *addr)
| ^~~~~~~~~~~~~~~~
../lib/iomap.c:264:6: warning: no previous prototype for ‘iowrite64_lo_hi’ [-Wmissing-prototypes]
264 | void iowrite64_lo_hi(u64 val, void __iomem *addr)
| ^~~~~~~~~~~~~~~
../lib/iomap.c:272:6: warning: no previous prototype for ‘iowrite64_hi_lo’ [-Wmissing-prototypes]
272 | void iowrite64_hi_lo(u64 val, void __iomem *addr)
| ^~~~~~~~~~~~~~~
../lib/iomap.c:280:6: warning: no previous prototype for ‘iowrite64be_lo_hi’ [-Wmissing-prototypes]
280 | void iowrite64be_lo_hi(u64 val, void __iomem *addr)
| ^~~~~~~~~~~~~~~~~
../lib/iomap.c:288:6: warning: no previous prototype for ‘iowrite64be_hi_lo’ [-Wmissing-prototypes]
288 | void iowrite64be_hi_lo(u64 val, void __iomem *addr)
| ^~~~~~~~~~~~~~~~~
../drivers/gpu/drm/drm_gpusvm.c: In function ‘drm_gpusvm_get_devmem_page’:
../drivers/gpu/drm/drm_gpusvm.c:1709:9: error: implicit declaration of function ‘zone_device_page_init’ [-Werror=implicit-function-declaration]
1709 | zone_device_page_init(page);
| ^~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
make[6]: *** [../scripts/Makefile.build:207: drivers/gpu/drm/drm_gpusvm.o] Error 1
make[6]: *** Waiting for unfinished jobs....
make[5]: *** [../scripts/Makefile.build:465: drivers/gpu/drm] Error 2
make[4]: *** [../scripts/Makefile.build:465: drivers/gpu] Error 2
make[3]: *** [../scripts/Makefile.build:465: drivers] Error 2
make[2]: *** [/kernel/Makefile:1994: .] Error 2
make[1]: *** [/kernel/Makefile:251: __sub-make] Error 2
make: *** [Makefile:251: __sub-make] Error 2
[20:47:08] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[20:47:12] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json ARCH=um O=.kunit --jobs=48
+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel
^ permalink raw reply [flat|nested] 19+ messages in thread