[PATCH] drm/amdkfd: fix signal page mmap PFN for GTT-backed event pages.

2026-05-26 Thread Yongqiang Sun
__pa(kernel_address) is invalid for vmap'd GTT kmap addresses. Record
page->user_pfn at setup (virt_to_page / vmalloc_to_pfn) and use it in
kfd_event_mmap() instead of __pa().

Signed-off-by: Yongqiang Sun 
---
 drivers/gpu/drm/amd/amdkfd/kfd_events.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
index e9be798c0a2b..6e0beacca81e 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
@@ -21,8 +21,10 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -54,6 +56,7 @@ struct kfd_event_waiter {
 struct kfd_signal_page {
uint64_t *kernel_address;
uint64_t __user *user_address;
+   unsigned long user_pfn;
bool need_to_free_pages;
 };
 
@@ -82,6 +85,7 @@ static struct kfd_signal_page *allocate_signal_page(struct 
kfd_process *p)
 
page->kernel_address = backing_store;
page->need_to_free_pages = true;
+   page->user_pfn = page_to_pfn(virt_to_page(backing_store));
pr_debug("Allocated new event signal page at %p, for process %p\n",
page, p);
 
@@ -349,6 +353,11 @@ static int kfd_event_page_set(struct kfd_process *p, void 
*kernel_address,
   KFD_SIGNAL_EVENT_LIMIT * 8);
 
page->kernel_address = kernel_address;
+   /* kmap for GTT is vmap-backed; do not use __pa() on kernel_address */
+   if (is_vmalloc_addr(kernel_address))
+   page->user_pfn = vmalloc_to_pfn(kernel_address);
+   else
+   page->user_pfn = page_to_pfn(virt_to_page(kernel_address));
 
p->signal_page = page;
p->signal_mapped_size = size;
@@ -1087,8 +1096,11 @@ int kfd_event_mmap(struct kfd_process *p, struct 
vm_area_struct *vma)
return -EINVAL;
}
 
-   pfn = __pa(page->kernel_address);
-   pfn >>= PAGE_SHIFT;
+   if (!page->user_pfn) {
+   pr_err("signal page has no recorded PFN\n");
+   return -EINVAL;
+   }
+   pfn = page->user_pfn;
 
vm_flags_set(vma, VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_NORESERVE
   | VM_DONTDUMP | VM_PFNMAP);
-- 
2.43.0



[PATCH] drm/amdkfd: fix signal page mmap PFN for GTT-backed event pages.

2026-05-12 Thread Sun, Yongqiang
__pa(kernel_address) is invalid for vmap'd GTT kmap addresses. Record
page->user_pfn at setup (virt_to_page / vmalloc_to_pfn) and use it in
kfd_event_mmap() instead of __pa().

Change-Id: I61061ab280850afa776191c30ba90a475afab46d
Signed-off-by: "Sun, Yongqiang" 
---
 drivers/gpu/drm/amd/amdkfd/kfd_events.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c 
b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
index e9be798c0a2b..6e0beacca81e 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
@@ -21,8 +21,10 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -54,6 +56,7 @@ struct kfd_event_waiter {
 struct kfd_signal_page {
uint64_t *kernel_address;
uint64_t __user *user_address;
+   unsigned long user_pfn;
bool need_to_free_pages;
 };
 
@@ -82,6 +85,7 @@ static struct kfd_signal_page *allocate_signal_page(struct 
kfd_process *p)
 
page->kernel_address = backing_store;
page->need_to_free_pages = true;
+   page->user_pfn = page_to_pfn(virt_to_page(backing_store));
pr_debug("Allocated new event signal page at %p, for process %p\n",
page, p);
 
@@ -349,6 +353,11 @@ static int kfd_event_page_set(struct kfd_process *p, void 
*kernel_address,
   KFD_SIGNAL_EVENT_LIMIT * 8);
 
page->kernel_address = kernel_address;
+   /* kmap for GTT is vmap-backed; do not use __pa() on kernel_address */
+   if (is_vmalloc_addr(kernel_address))
+   page->user_pfn = vmalloc_to_pfn(kernel_address);
+   else
+   page->user_pfn = page_to_pfn(virt_to_page(kernel_address));
 
p->signal_page = page;
p->signal_mapped_size = size;
@@ -1087,8 +1096,11 @@ int kfd_event_mmap(struct kfd_process *p, struct 
vm_area_struct *vma)
return -EINVAL;
}
 
-   pfn = __pa(page->kernel_address);
-   pfn >>= PAGE_SHIFT;
+   if (!page->user_pfn) {
+   pr_err("signal page has no recorded PFN\n");
+   return -EINVAL;
+   }
+   pfn = page->user_pfn;
 
vm_flags_set(vma, VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_NORESERVE
   | VM_DONTDUMP | VM_PFNMAP);
-- 
2.43.0