Skip to content

Commit c79ee71

Browse files
Thomas Hellströmgregkh
authored andcommitted
drm/pagemap, drm/xe: Ensure that the devmem allocation is idle before use
commit 754c232 upstream. In situations where no system memory is migrated to devmem, and in upcoming patches where another GPU is performing the migration to the newly allocated devmem buffer, there is nothing to ensure any ongoing clear to the devmem allocation or async eviction from the devmem allocation is complete. Address that by passing a struct dma_fence down to the copy functions, and ensure it is waited for before migration is marked complete. v3: - New patch. v4: - Update the logic used for determining when to wait for the pre_migrate_fence. - Update the logic used for determining when to warn for the pre_migrate_fence since the scheduler fences apparently can signal out-of-order. v5: - Fix a UAF (CI) - Remove references to source P2P migration (Himal) - Put the pre_migrate_fence after migration. v6: - Pipeline the pre_migrate_fence dependency (Matt Brost) Fixes: c5b3eb5 ("drm/xe: Add GPUSVM device memory copy vfunc functions") Cc: Matthew Brost <matthew.brost@intel.com> Cc: <stable@vger.kernel.org> # v6.15+ Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com> Reviewed-by: Matthew Brost <matthew.brost@intel.com> Acked-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> # For merging through drm-xe. Link: https://patch.msgid.link/20251219113320.183860-4-thomas.hellstrom@linux.intel.com (cherry picked from commit 16b5ad3) Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 548f139 commit c79ee71

5 files changed

Lines changed: 88 additions & 26 deletions

File tree

drivers/gpu/drm/drm_pagemap.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © 2024-2025 Intel Corporation
44
*/
55

6+
#include <linux/dma-fence.h>
67
#include <linux/dma-mapping.h>
78
#include <linux/migrate.h>
89
#include <linux/pagemap.h>
@@ -408,10 +409,14 @@ int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
408409
drm_pagemap_get_devmem_page(page, zdd);
409410
}
410411

411-
err = ops->copy_to_devmem(pages, pagemap_addr, npages);
412+
err = ops->copy_to_devmem(pages, pagemap_addr, npages,
413+
devmem_allocation->pre_migrate_fence);
412414
if (err)
413415
goto err_finalize;
414416

417+
dma_fence_put(devmem_allocation->pre_migrate_fence);
418+
devmem_allocation->pre_migrate_fence = NULL;
419+
415420
/* Upon success bind devmem allocation to range and zdd */
416421
devmem_allocation->timeslice_expiration = get_jiffies_64() +
417422
msecs_to_jiffies(timeslice_ms);
@@ -596,7 +601,7 @@ int drm_pagemap_evict_to_ram(struct drm_pagemap_devmem *devmem_allocation)
596601
for (i = 0; i < npages; ++i)
597602
pages[i] = migrate_pfn_to_page(src[i]);
598603

599-
err = ops->copy_to_ram(pages, pagemap_addr, npages);
604+
err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
600605
if (err)
601606
goto err_finalize;
602607

@@ -732,7 +737,7 @@ static int __drm_pagemap_migrate_to_ram(struct vm_area_struct *vas,
732737
for (i = 0; i < npages; ++i)
733738
pages[i] = migrate_pfn_to_page(migrate.src[i]);
734739

735-
err = ops->copy_to_ram(pages, pagemap_addr, npages);
740+
err = ops->copy_to_ram(pages, pagemap_addr, npages, NULL);
736741
if (err)
737742
goto err_finalize;
738743

@@ -813,18 +818,22 @@ EXPORT_SYMBOL_GPL(drm_pagemap_pagemap_ops_get);
813818
* @ops: Pointer to the operations structure for GPU SVM device memory
814819
* @dpagemap: The struct drm_pagemap we're allocating from.
815820
* @size: Size of device memory allocation
821+
* @pre_migrate_fence: Fence to wait for or pipeline behind before migration starts.
822+
* (May be NULL).
816823
*/
817824
void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
818825
struct device *dev, struct mm_struct *mm,
819826
const struct drm_pagemap_devmem_ops *ops,
820-
struct drm_pagemap *dpagemap, size_t size)
827+
struct drm_pagemap *dpagemap, size_t size,
828+
struct dma_fence *pre_migrate_fence)
821829
{
822830
init_completion(&devmem_allocation->detached);
823831
devmem_allocation->dev = dev;
824832
devmem_allocation->mm = mm;
825833
devmem_allocation->ops = ops;
826834
devmem_allocation->dpagemap = dpagemap;
827835
devmem_allocation->size = size;
836+
devmem_allocation->pre_migrate_fence = pre_migrate_fence;
828837
}
829838
EXPORT_SYMBOL_GPL(drm_pagemap_devmem_init);
830839

drivers/gpu/drm/xe/xe_migrate.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,6 +1813,7 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
18131813
unsigned long sram_offset,
18141814
struct drm_pagemap_addr *sram_addr,
18151815
u64 vram_addr,
1816+
struct dma_fence *deps,
18161817
const enum xe_migrate_copy_dir dir)
18171818
{
18181819
struct xe_gt *gt = m->tile->primary_gt;
@@ -1890,6 +1891,14 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
18901891

18911892
xe_sched_job_add_migrate_flush(job, MI_INVALIDATE_TLB);
18921893

1894+
if (deps && !dma_fence_is_signaled(deps)) {
1895+
dma_fence_get(deps);
1896+
err = drm_sched_job_add_dependency(&job->drm, deps);
1897+
if (err)
1898+
dma_fence_wait(deps, false);
1899+
err = 0;
1900+
}
1901+
18931902
mutex_lock(&m->job_mutex);
18941903
xe_sched_job_arm(job);
18951904
fence = dma_fence_get(&job->drm.s_fence->finished);
@@ -1915,6 +1924,8 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
19151924
* @npages: Number of pages to migrate.
19161925
* @src_addr: Array of DMA information (source of migrate)
19171926
* @dst_addr: Device physical address of VRAM (destination of migrate)
1927+
* @deps: struct dma_fence representing the dependencies that need
1928+
* to be signaled before migration.
19181929
*
19191930
* Copy from an array dma addresses to a VRAM device physical address
19201931
*
@@ -1924,10 +1935,11 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
19241935
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
19251936
unsigned long npages,
19261937
struct drm_pagemap_addr *src_addr,
1927-
u64 dst_addr)
1938+
u64 dst_addr,
1939+
struct dma_fence *deps)
19281940
{
19291941
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, src_addr, dst_addr,
1930-
XE_MIGRATE_COPY_TO_VRAM);
1942+
deps, XE_MIGRATE_COPY_TO_VRAM);
19311943
}
19321944

19331945
/**
@@ -1936,6 +1948,8 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
19361948
* @npages: Number of pages to migrate.
19371949
* @src_addr: Device physical address of VRAM (source of migrate)
19381950
* @dst_addr: Array of DMA information (destination of migrate)
1951+
* @deps: struct dma_fence representing the dependencies that need
1952+
* to be signaled before migration.
19391953
*
19401954
* Copy from a VRAM device physical address to an array dma addresses
19411955
*
@@ -1945,10 +1959,11 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
19451959
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
19461960
unsigned long npages,
19471961
u64 src_addr,
1948-
struct drm_pagemap_addr *dst_addr)
1962+
struct drm_pagemap_addr *dst_addr,
1963+
struct dma_fence *deps)
19491964
{
19501965
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, dst_addr, src_addr,
1951-
XE_MIGRATE_COPY_TO_SRAM);
1966+
deps, XE_MIGRATE_COPY_TO_SRAM);
19521967
}
19531968

19541969
static void xe_migrate_dma_unmap(struct xe_device *xe,
@@ -2121,7 +2136,7 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
21212136
__fence = xe_migrate_vram(m, current_bytes,
21222137
(unsigned long)buf & ~PAGE_MASK,
21232138
&pagemap_addr[current_page],
2124-
vram_addr, write ?
2139+
vram_addr, NULL, write ?
21252140
XE_MIGRATE_COPY_TO_VRAM :
21262141
XE_MIGRATE_COPY_TO_SRAM);
21272142
if (IS_ERR(__fence)) {

drivers/gpu/drm/xe/xe_migrate.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,14 @@ int xe_migrate_init(struct xe_migrate *m);
111111
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
112112
unsigned long npages,
113113
struct drm_pagemap_addr *src_addr,
114-
u64 dst_addr);
114+
u64 dst_addr,
115+
struct dma_fence *deps);
115116

116117
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
117118
unsigned long npages,
118119
u64 src_addr,
119-
struct drm_pagemap_addr *dst_addr);
120+
struct drm_pagemap_addr *dst_addr,
121+
struct dma_fence *deps);
120122

121123
struct dma_fence *xe_migrate_copy(struct xe_migrate *m,
122124
struct xe_bo *src_bo,

drivers/gpu/drm/xe/xe_svm.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,8 @@ static void xe_svm_copy_us_stats_incr(struct xe_gt *gt,
477477

478478
static int xe_svm_copy(struct page **pages,
479479
struct drm_pagemap_addr *pagemap_addr,
480-
unsigned long npages, const enum xe_svm_copy_dir dir)
480+
unsigned long npages, const enum xe_svm_copy_dir dir,
481+
struct dma_fence *pre_migrate_fence)
481482
{
482483
struct xe_vram_region *vr = NULL;
483484
struct xe_gt *gt = NULL;
@@ -566,7 +567,8 @@ static int xe_svm_copy(struct page **pages,
566567
__fence = xe_migrate_from_vram(vr->migrate,
567568
i - pos + incr,
568569
vram_addr,
569-
&pagemap_addr[pos]);
570+
&pagemap_addr[pos],
571+
pre_migrate_fence);
570572
} else {
571573
vm_dbg(&xe->drm,
572574
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%ld",
@@ -575,13 +577,14 @@ static int xe_svm_copy(struct page **pages,
575577
__fence = xe_migrate_to_vram(vr->migrate,
576578
i - pos + incr,
577579
&pagemap_addr[pos],
578-
vram_addr);
580+
vram_addr,
581+
pre_migrate_fence);
579582
}
580583
if (IS_ERR(__fence)) {
581584
err = PTR_ERR(__fence);
582585
goto err_out;
583586
}
584-
587+
pre_migrate_fence = NULL;
585588
dma_fence_put(fence);
586589
fence = __fence;
587590
}
@@ -604,20 +607,22 @@ static int xe_svm_copy(struct page **pages,
604607
vram_addr, (u64)pagemap_addr[pos].addr, 1);
605608
__fence = xe_migrate_from_vram(vr->migrate, 1,
606609
vram_addr,
607-
&pagemap_addr[pos]);
610+
&pagemap_addr[pos],
611+
pre_migrate_fence);
608612
} else {
609613
vm_dbg(&xe->drm,
610614
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%d",
611615
(u64)pagemap_addr[pos].addr, vram_addr, 1);
612616
__fence = xe_migrate_to_vram(vr->migrate, 1,
613617
&pagemap_addr[pos],
614-
vram_addr);
618+
vram_addr,
619+
pre_migrate_fence);
615620
}
616621
if (IS_ERR(__fence)) {
617622
err = PTR_ERR(__fence);
618623
goto err_out;
619624
}
620-
625+
pre_migrate_fence = NULL;
621626
dma_fence_put(fence);
622627
fence = __fence;
623628
}
@@ -630,6 +635,8 @@ static int xe_svm_copy(struct page **pages,
630635
dma_fence_wait(fence, false);
631636
dma_fence_put(fence);
632637
}
638+
if (pre_migrate_fence)
639+
dma_fence_wait(pre_migrate_fence, false);
633640

634641
/*
635642
* XXX: We can't derive the GT here (or anywhere in this functions, but
@@ -646,16 +653,20 @@ static int xe_svm_copy(struct page **pages,
646653

647654
static int xe_svm_copy_to_devmem(struct page **pages,
648655
struct drm_pagemap_addr *pagemap_addr,
649-
unsigned long npages)
656+
unsigned long npages,
657+
struct dma_fence *pre_migrate_fence)
650658
{
651-
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM);
659+
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM,
660+
pre_migrate_fence);
652661
}
653662

654663
static int xe_svm_copy_to_ram(struct page **pages,
655664
struct drm_pagemap_addr *pagemap_addr,
656-
unsigned long npages)
665+
unsigned long npages,
666+
struct dma_fence *pre_migrate_fence)
657667
{
658-
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM);
668+
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM,
669+
pre_migrate_fence);
659670
}
660671

661672
static struct xe_bo *to_xe_bo(struct drm_pagemap_devmem *devmem_allocation)
@@ -668,6 +679,7 @@ static void xe_svm_devmem_release(struct drm_pagemap_devmem *devmem_allocation)
668679
struct xe_bo *bo = to_xe_bo(devmem_allocation);
669680
struct xe_device *xe = xe_bo_device(bo);
670681

682+
dma_fence_put(devmem_allocation->pre_migrate_fence);
671683
xe_bo_put_async(bo);
672684
xe_pm_runtime_put(xe);
673685
}
@@ -862,6 +874,7 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
862874
unsigned long timeslice_ms)
863875
{
864876
struct xe_vram_region *vr = container_of(dpagemap, typeof(*vr), dpagemap);
877+
struct dma_fence *pre_migrate_fence = NULL;
865878
struct xe_device *xe = vr->xe;
866879
struct device *dev = xe->drm.dev;
867880
struct drm_buddy_block *block;
@@ -888,8 +901,20 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
888901
break;
889902
}
890903

904+
/* Ensure that any clearing or async eviction will complete before migration. */
905+
if (!dma_resv_test_signaled(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL)) {
906+
err = dma_resv_get_singleton(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL,
907+
&pre_migrate_fence);
908+
if (err)
909+
dma_resv_wait_timeout(bo->ttm.base.resv, DMA_RESV_USAGE_KERNEL,
910+
false, MAX_SCHEDULE_TIMEOUT);
911+
else if (pre_migrate_fence)
912+
dma_fence_enable_sw_signaling(pre_migrate_fence);
913+
}
914+
891915
drm_pagemap_devmem_init(&bo->devmem_allocation, dev, mm,
892-
&dpagemap_devmem_ops, dpagemap, end - start);
916+
&dpagemap_devmem_ops, dpagemap, end - start,
917+
pre_migrate_fence);
893918

894919
blocks = &to_xe_ttm_vram_mgr_resource(bo->ttm.resource)->blocks;
895920
list_for_each_entry(block, blocks, link)

include/drm/drm_pagemap.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#define NR_PAGES(order) (1U << (order))
1010

11+
struct dma_fence;
1112
struct drm_pagemap;
1213
struct drm_pagemap_zdd;
1314
struct device;
@@ -174,6 +175,8 @@ struct drm_pagemap_devmem_ops {
174175
* @pages: Pointer to array of device memory pages (destination)
175176
* @pagemap_addr: Pointer to array of DMA information (source)
176177
* @npages: Number of pages to copy
178+
* @pre_migrate_fence: dma-fence to wait for before migration start.
179+
* May be NULL.
177180
*
178181
* Copy pages to device memory. If the order of a @pagemap_addr entry
179182
* is greater than 0, the entry is populated but subsequent entries
@@ -183,13 +186,16 @@ struct drm_pagemap_devmem_ops {
183186
*/
184187
int (*copy_to_devmem)(struct page **pages,
185188
struct drm_pagemap_addr *pagemap_addr,
186-
unsigned long npages);
189+
unsigned long npages,
190+
struct dma_fence *pre_migrate_fence);
187191

188192
/**
189193
* @copy_to_ram: Copy to system RAM (required for migration)
190194
* @pages: Pointer to array of device memory pages (source)
191195
* @pagemap_addr: Pointer to array of DMA information (destination)
192196
* @npages: Number of pages to copy
197+
* @pre_migrate_fence: dma-fence to wait for before migration start.
198+
* May be NULL.
193199
*
194200
* Copy pages to system RAM. If the order of a @pagemap_addr entry
195201
* is greater than 0, the entry is populated but subsequent entries
@@ -199,7 +205,8 @@ struct drm_pagemap_devmem_ops {
199205
*/
200206
int (*copy_to_ram)(struct page **pages,
201207
struct drm_pagemap_addr *pagemap_addr,
202-
unsigned long npages);
208+
unsigned long npages,
209+
struct dma_fence *pre_migrate_fence);
203210
};
204211

205212
/**
@@ -212,6 +219,8 @@ struct drm_pagemap_devmem_ops {
212219
* @dpagemap: The struct drm_pagemap of the pages this allocation belongs to.
213220
* @size: Size of device memory allocation
214221
* @timeslice_expiration: Timeslice expiration in jiffies
222+
* @pre_migrate_fence: Fence to wait for or pipeline behind before migration starts.
223+
* (May be NULL).
215224
*/
216225
struct drm_pagemap_devmem {
217226
struct device *dev;
@@ -221,6 +230,7 @@ struct drm_pagemap_devmem {
221230
struct drm_pagemap *dpagemap;
222231
size_t size;
223232
u64 timeslice_expiration;
233+
struct dma_fence *pre_migrate_fence;
224234
};
225235

226236
int drm_pagemap_migrate_to_devmem(struct drm_pagemap_devmem *devmem_allocation,
@@ -238,7 +248,8 @@ struct drm_pagemap *drm_pagemap_page_to_dpagemap(struct page *page);
238248
void drm_pagemap_devmem_init(struct drm_pagemap_devmem *devmem_allocation,
239249
struct device *dev, struct mm_struct *mm,
240250
const struct drm_pagemap_devmem_ops *ops,
241-
struct drm_pagemap *dpagemap, size_t size);
251+
struct drm_pagemap *dpagemap, size_t size,
252+
struct dma_fence *pre_migrate_fence);
242253

243254
int drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
244255
unsigned long start, unsigned long end,

0 commit comments

Comments
 (0)