Skip to content

Commit 754c232

Browse files
author
Thomas Hellström
committed
drm/pagemap, drm/xe: Ensure that the devmem allocation is idle before use
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>
1 parent d2d7f56 commit 754c232

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
@@ -2062,6 +2062,7 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
20622062
unsigned long sram_offset,
20632063
struct drm_pagemap_addr *sram_addr,
20642064
u64 vram_addr,
2065+
struct dma_fence *deps,
20652066
const enum xe_migrate_copy_dir dir)
20662067
{
20672068
struct xe_gt *gt = m->tile->primary_gt;
@@ -2150,6 +2151,14 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
21502151

21512152
xe_sched_job_add_migrate_flush(job, MI_INVALIDATE_TLB);
21522153

2154+
if (deps && !dma_fence_is_signaled(deps)) {
2155+
dma_fence_get(deps);
2156+
err = drm_sched_job_add_dependency(&job->drm, deps);
2157+
if (err)
2158+
dma_fence_wait(deps, false);
2159+
err = 0;
2160+
}
2161+
21532162
mutex_lock(&m->job_mutex);
21542163
xe_sched_job_arm(job);
21552164
fence = dma_fence_get(&job->drm.s_fence->finished);
@@ -2175,6 +2184,8 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
21752184
* @npages: Number of pages to migrate.
21762185
* @src_addr: Array of DMA information (source of migrate)
21772186
* @dst_addr: Device physical address of VRAM (destination of migrate)
2187+
* @deps: struct dma_fence representing the dependencies that need
2188+
* to be signaled before migration.
21782189
*
21792190
* Copy from an array dma addresses to a VRAM device physical address
21802191
*
@@ -2184,10 +2195,11 @@ static struct dma_fence *xe_migrate_vram(struct xe_migrate *m,
21842195
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
21852196
unsigned long npages,
21862197
struct drm_pagemap_addr *src_addr,
2187-
u64 dst_addr)
2198+
u64 dst_addr,
2199+
struct dma_fence *deps)
21882200
{
21892201
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, src_addr, dst_addr,
2190-
XE_MIGRATE_COPY_TO_VRAM);
2202+
deps, XE_MIGRATE_COPY_TO_VRAM);
21912203
}
21922204

21932205
/**
@@ -2196,6 +2208,8 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
21962208
* @npages: Number of pages to migrate.
21972209
* @src_addr: Device physical address of VRAM (source of migrate)
21982210
* @dst_addr: Array of DMA information (destination of migrate)
2211+
* @deps: struct dma_fence representing the dependencies that need
2212+
* to be signaled before migration.
21992213
*
22002214
* Copy from a VRAM device physical address to an array dma addresses
22012215
*
@@ -2205,10 +2219,11 @@ struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
22052219
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
22062220
unsigned long npages,
22072221
u64 src_addr,
2208-
struct drm_pagemap_addr *dst_addr)
2222+
struct drm_pagemap_addr *dst_addr,
2223+
struct dma_fence *deps)
22092224
{
22102225
return xe_migrate_vram(m, npages * PAGE_SIZE, 0, dst_addr, src_addr,
2211-
XE_MIGRATE_COPY_TO_SRAM);
2226+
deps, XE_MIGRATE_COPY_TO_SRAM);
22122227
}
22132228

22142229
static void xe_migrate_dma_unmap(struct xe_device *xe,
@@ -2384,7 +2399,7 @@ int xe_migrate_access_memory(struct xe_migrate *m, struct xe_bo *bo,
23842399
__fence = xe_migrate_vram(m, current_bytes,
23852400
(unsigned long)buf & ~PAGE_MASK,
23862401
&pagemap_addr[current_page],
2387-
vram_addr, write ?
2402+
vram_addr, NULL, write ?
23882403
XE_MIGRATE_COPY_TO_VRAM :
23892404
XE_MIGRATE_COPY_TO_SRAM);
23902405
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
@@ -116,12 +116,14 @@ int xe_migrate_init(struct xe_migrate *m);
116116
struct dma_fence *xe_migrate_to_vram(struct xe_migrate *m,
117117
unsigned long npages,
118118
struct drm_pagemap_addr *src_addr,
119-
u64 dst_addr);
119+
u64 dst_addr,
120+
struct dma_fence *deps);
120121

121122
struct dma_fence *xe_migrate_from_vram(struct xe_migrate *m,
122123
unsigned long npages,
123124
u64 src_addr,
124-
struct drm_pagemap_addr *dst_addr);
125+
struct drm_pagemap_addr *dst_addr,
126+
struct dma_fence *deps);
125127

126128
struct dma_fence *xe_migrate_copy(struct xe_migrate *m,
127129
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
@@ -476,7 +476,8 @@ static void xe_svm_copy_us_stats_incr(struct xe_gt *gt,
476476

477477
static int xe_svm_copy(struct page **pages,
478478
struct drm_pagemap_addr *pagemap_addr,
479-
unsigned long npages, const enum xe_svm_copy_dir dir)
479+
unsigned long npages, const enum xe_svm_copy_dir dir,
480+
struct dma_fence *pre_migrate_fence)
480481
{
481482
struct xe_vram_region *vr = NULL;
482483
struct xe_gt *gt = NULL;
@@ -565,7 +566,8 @@ static int xe_svm_copy(struct page **pages,
565566
__fence = xe_migrate_from_vram(vr->migrate,
566567
i - pos + incr,
567568
vram_addr,
568-
&pagemap_addr[pos]);
569+
&pagemap_addr[pos],
570+
pre_migrate_fence);
569571
} else {
570572
vm_dbg(&xe->drm,
571573
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%ld",
@@ -574,13 +576,14 @@ static int xe_svm_copy(struct page **pages,
574576
__fence = xe_migrate_to_vram(vr->migrate,
575577
i - pos + incr,
576578
&pagemap_addr[pos],
577-
vram_addr);
579+
vram_addr,
580+
pre_migrate_fence);
578581
}
579582
if (IS_ERR(__fence)) {
580583
err = PTR_ERR(__fence);
581584
goto err_out;
582585
}
583-
586+
pre_migrate_fence = NULL;
584587
dma_fence_put(fence);
585588
fence = __fence;
586589
}
@@ -603,20 +606,22 @@ static int xe_svm_copy(struct page **pages,
603606
vram_addr, (u64)pagemap_addr[pos].addr, 1);
604607
__fence = xe_migrate_from_vram(vr->migrate, 1,
605608
vram_addr,
606-
&pagemap_addr[pos]);
609+
&pagemap_addr[pos],
610+
pre_migrate_fence);
607611
} else {
608612
vm_dbg(&xe->drm,
609613
"COPY TO VRAM - 0x%016llx -> 0x%016llx, NPAGES=%d",
610614
(u64)pagemap_addr[pos].addr, vram_addr, 1);
611615
__fence = xe_migrate_to_vram(vr->migrate, 1,
612616
&pagemap_addr[pos],
613-
vram_addr);
617+
vram_addr,
618+
pre_migrate_fence);
614619
}
615620
if (IS_ERR(__fence)) {
616621
err = PTR_ERR(__fence);
617622
goto err_out;
618623
}
619-
624+
pre_migrate_fence = NULL;
620625
dma_fence_put(fence);
621626
fence = __fence;
622627
}
@@ -629,6 +634,8 @@ static int xe_svm_copy(struct page **pages,
629634
dma_fence_wait(fence, false);
630635
dma_fence_put(fence);
631636
}
637+
if (pre_migrate_fence)
638+
dma_fence_wait(pre_migrate_fence, false);
632639

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

646653
static int xe_svm_copy_to_devmem(struct page **pages,
647654
struct drm_pagemap_addr *pagemap_addr,
648-
unsigned long npages)
655+
unsigned long npages,
656+
struct dma_fence *pre_migrate_fence)
649657
{
650-
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM);
658+
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_VRAM,
659+
pre_migrate_fence);
651660
}
652661

653662
static int xe_svm_copy_to_ram(struct page **pages,
654663
struct drm_pagemap_addr *pagemap_addr,
655-
unsigned long npages)
664+
unsigned long npages,
665+
struct dma_fence *pre_migrate_fence)
656666
{
657-
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM);
667+
return xe_svm_copy(pages, pagemap_addr, npages, XE_SVM_COPY_TO_SRAM,
668+
pre_migrate_fence);
658669
}
659670

660671
static struct xe_bo *to_xe_bo(struct drm_pagemap_devmem *devmem_allocation)
@@ -667,6 +678,7 @@ static void xe_svm_devmem_release(struct drm_pagemap_devmem *devmem_allocation)
667678
struct xe_bo *bo = to_xe_bo(devmem_allocation);
668679
struct xe_device *xe = xe_bo_device(bo);
669680

681+
dma_fence_put(devmem_allocation->pre_migrate_fence);
670682
xe_bo_put_async(bo);
671683
xe_pm_runtime_put(xe);
672684
}
@@ -861,6 +873,7 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
861873
unsigned long timeslice_ms)
862874
{
863875
struct xe_vram_region *vr = container_of(dpagemap, typeof(*vr), dpagemap);
876+
struct dma_fence *pre_migrate_fence = NULL;
864877
struct xe_device *xe = vr->xe;
865878
struct device *dev = xe->drm.dev;
866879
struct drm_buddy_block *block;
@@ -887,8 +900,20 @@ static int xe_drm_pagemap_populate_mm(struct drm_pagemap *dpagemap,
887900
break;
888901
}
889902

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

893918
blocks = &to_xe_ttm_vram_mgr_resource(bo->ttm.resource)->blocks;
894919
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)