__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" <[email protected]> --- 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 <linux/mm.h> #include <linux/mm_types.h> #include <linux/slab.h> +#include <linux/vmalloc.h> #include <linux/types.h> #include <linux/sched/signal.h> #include <linux/sched/mm.h> @@ -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
