]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
powerpc/powernv/npu: Fault user page into the hypervisor's pagetable
authorAlexey Kardashevskiy <aik@ozlabs.ru>
Wed, 19 Dec 2018 08:52:29 +0000 (19:52 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 21 Dec 2018 05:20:46 +0000 (16:20 +1100)
When a page fault happens in a GPU, the GPU signals the OS and the GPU
driver calls the fault handler which populated a page table; this allows
the GPU to complete an ATS request.

On the bare metal get_user_pages() is enough as it adds a pte to
the kernel page table but under KVM the partition scope tree does not get
updated so ATS will still fail.

This reads a byte from an effective address which causes HV storage
interrupt and KVM updates the partition scope tree.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/platforms/powernv/npu-dma.c

index b713727663e26e7469484b6027d198500a11e3f6..d7f742ed48ba4bb3b002f23daf2ffa576f055dfb 100644 (file)
@@ -1132,6 +1132,8 @@ int pnv_npu2_handle_fault(struct npu_context *context, uintptr_t *ea,
        u64 rc = 0, result = 0;
        int i, is_write;
        struct page *page[1];
+       const char __user *u;
+       char c;
 
        /* mmap_sem should be held so the struct_mm must be present */
        struct mm_struct *mm = context->mm;
@@ -1144,18 +1146,17 @@ int pnv_npu2_handle_fault(struct npu_context *context, uintptr_t *ea,
                                        is_write ? FOLL_WRITE : 0,
                                        page, NULL, NULL);
 
-               /*
-                * To support virtualised environments we will have to do an
-                * access to the page to ensure it gets faulted into the
-                * hypervisor. For the moment virtualisation is not supported in
-                * other areas so leave the access out.
-                */
                if (rc != 1) {
                        status[i] = rc;
                        result = -EFAULT;
                        continue;
                }
 
+               /* Make sure partition scoped tree gets a pte */
+               u = page_address(page[0]);
+               if (__get_user(c, u))
+                       result = -EFAULT;
+
                status[i] = 0;
                put_page(page[0]);
        }