[PATCH] drm/xe: Unmap userptr in MMU invalidation notifier

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



To be secure, when a userptr is invalidated the pages should be dma
unmapped ensuring the device can no longer touch the invalidated pages.

v2:
 - Don't free sg table in MMU notifer, just dma unmap pages

Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
Fixes: 12f4b58a37f4 ("drm/xe: Use hmm_range_fault to populate user pages")
Cc: Thomas Hellström <thomas.hellstrom@xxxxxxxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx # 6.8
Signed-off-by: Matthew Brost <matthew.brost@xxxxxxxxx>
---
 drivers/gpu/drm/xe/xe_hmm.c      | 42 ++++++++++++++++++++++++++------
 drivers/gpu/drm/xe/xe_hmm.h      |  1 +
 drivers/gpu/drm/xe/xe_pt.c       |  2 +-
 drivers/gpu/drm/xe/xe_vm.c       |  5 +++-
 drivers/gpu/drm/xe/xe_vm_types.h |  5 +++-
 5 files changed, 45 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_hmm.c b/drivers/gpu/drm/xe/xe_hmm.c
index 2c32dc46f7d4..baf42514e1f9 100644
--- a/drivers/gpu/drm/xe/xe_hmm.c
+++ b/drivers/gpu/drm/xe/xe_hmm.c
@@ -112,16 +112,20 @@ static int xe_build_sg(struct xe_device *xe, struct hmm_range *range,
 	return ret;
 }
 
-/*
- * xe_hmm_userptr_free_sg() - Free the scatter gather table of userptr
+#define need_unmap(__sg)	((u64)(__sg) & 0x1ull)
+#define clear_need_unmap(__sg)	(__sg) = (struct sg_table *)((u64)(__sg) & ~0x1ull)
+#define set_need_unmap(__sg)	(__sg) = (struct sg_table *)((u64)(__sg) | 0x1ull)
+
+/**
+ * xe_hmm_userptr_unmap_sg() - Unmap 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.
+ * the userptr sg table. This is a helper function to dma unmap the address in
+ * the table.
  */
-void xe_hmm_userptr_free_sg(struct xe_userptr_vma *uvma)
+void xe_hmm_userptr_unmap_sg(struct xe_userptr_vma *uvma)
 {
 	struct xe_userptr *userptr = &uvma->userptr;
 	struct xe_vma *vma = &uvma->vma;
@@ -129,11 +133,34 @@ void xe_hmm_userptr_free_sg(struct xe_userptr_vma *uvma)
 	struct xe_vm *vm = xe_vma_vm(vma);
 	struct xe_device *xe = vm->xe;
 	struct device *dev = xe->drm.dev;
+	bool do_unmap;
 
 	xe_assert(xe, userptr->sg);
-	dma_unmap_sgtable(dev, userptr->sg,
-			  write ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE, 0);
 
+	spin_lock(&vm->userptr.invalidated_lock);
+	do_unmap = need_unmap(userptr->sg);
+	clear_need_unmap(userptr->sg);
+	spin_unlock(&vm->userptr.invalidated_lock);
+
+	if (do_unmap)
+		dma_unmap_sgtable(dev, userptr->sg,
+				  write ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE, 0);
+}
+
+/*
+ * 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_hmm_userptr_unmap_sg(uvma);
 	sg_free_table(userptr->sg);
 	userptr->sg = NULL;
 }
@@ -244,6 +271,7 @@ int xe_hmm_userptr_populate_range(struct xe_userptr_vma *uvma,
 
 	xe_mark_range_accessed(&hmm_range, write);
 	userptr->sg = &userptr->sgt;
+	set_need_unmap(userptr->sg);
 	userptr->notifier_seq = hmm_range.notifier_seq;
 
 free_pfns:
diff --git a/drivers/gpu/drm/xe/xe_hmm.h b/drivers/gpu/drm/xe/xe_hmm.h
index 909dc2bdcd97..56e653dc9fa2 100644
--- a/drivers/gpu/drm/xe/xe_hmm.h
+++ b/drivers/gpu/drm/xe/xe_hmm.h
@@ -9,3 +9,4 @@ 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_sg(struct xe_userptr_vma *uvma);
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 8d3765d3351e..b095257dc684 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -635,7 +635,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
 
 	if (!xe_vma_is_null(vma)) {
 		if (xe_vma_is_userptr(vma))
-			xe_res_first_sg(to_userptr_vma(vma)->userptr.sg, 0,
+			xe_res_first_sg(vma_to_userptr_sg(vma), 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),
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index dfd31b346021..c3d54dcf2a3e 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -637,6 +637,9 @@ static bool vma_userptr_invalidate(struct mmu_interval_notifier *mni,
 		XE_WARN_ON(err);
 	}
 
+	if (userptr->sg)
+		xe_hmm_userptr_unmap_sg(uvma);
+
 	trace_xe_vma_userptr_invalidate_complete(vma);
 
 	return true;
@@ -3405,7 +3408,7 @@ int xe_analyze_vm(struct drm_printer *p, struct xe_vm *vm, int gt_id)
 		if (is_null) {
 			addr = 0;
 		} else if (is_userptr) {
-			struct sg_table *sg = to_userptr_vma(vma)->userptr.sg;
+			struct sg_table *sg = vma_to_userptr_sg(vma);
 			struct xe_res_cursor cur;
 
 			if (sg) {
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index ce1a63a5e3e7..0478a2235076 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -34,6 +34,9 @@ struct xe_vm;
 #define XE_VMA_PTE_COMPACT	(DRM_GPUVA_USERBITS << 9)
 #define XE_VMA_DUMPABLE		(DRM_GPUVA_USERBITS << 10)
 
+#define vma_to_userptr_sg(__vma) \
+	(struct sg_table *)((u64)to_userptr_vma((__vma))->userptr.sg & ~0x1ull)
+
 /** struct xe_userptr - User pointer */
 struct xe_userptr {
 	/** @invalidate_link: Link for the vm::userptr.invalidated list */
@@ -206,7 +209,7 @@ struct xe_vm {
 		struct rw_semaphore notifier_lock;
 		/**
 		 * @userptr.invalidated_lock: Protects the
-		 * @userptr.invalidated list.
+		 * @userptr.invalidated list and dma mapped pages of userptrs
 		 */
 		spinlock_t invalidated_lock;
 		/**
-- 
2.34.1





[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux