diff options
| author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2018-12-19 03:52:29 -0500 |
|---|---|---|
| committer | Michael Ellerman <mpe@ellerman.id.au> | 2018-12-21 00:20:46 -0500 |
| commit | 58629c0dc34904d135af944d120eb23165ec3b61 (patch) | |
| tree | c6e96ae78213fc95c6f7181047ee68210d6440d1 | |
| parent | 135ef954051b102870a8d47a8eb822af1f1b1ec1 (diff) | |
powerpc/powernv/npu: Fault user page into the hypervisor's pagetable
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>
| -rw-r--r-- | arch/powerpc/platforms/powernv/npu-dma.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c index b713727663e2..d7f742ed48ba 100644 --- a/arch/powerpc/platforms/powernv/npu-dma.c +++ b/arch/powerpc/platforms/powernv/npu-dma.c | |||
| @@ -1132,6 +1132,8 @@ int pnv_npu2_handle_fault(struct npu_context *context, uintptr_t *ea, | |||
| 1132 | u64 rc = 0, result = 0; | 1132 | u64 rc = 0, result = 0; |
| 1133 | int i, is_write; | 1133 | int i, is_write; |
| 1134 | struct page *page[1]; | 1134 | struct page *page[1]; |
| 1135 | const char __user *u; | ||
| 1136 | char c; | ||
| 1135 | 1137 | ||
| 1136 | /* mmap_sem should be held so the struct_mm must be present */ | 1138 | /* mmap_sem should be held so the struct_mm must be present */ |
| 1137 | struct mm_struct *mm = context->mm; | 1139 | struct mm_struct *mm = context->mm; |
| @@ -1144,18 +1146,17 @@ int pnv_npu2_handle_fault(struct npu_context *context, uintptr_t *ea, | |||
| 1144 | is_write ? FOLL_WRITE : 0, | 1146 | is_write ? FOLL_WRITE : 0, |
| 1145 | page, NULL, NULL); | 1147 | page, NULL, NULL); |
| 1146 | 1148 | ||
| 1147 | /* | ||
| 1148 | * To support virtualised environments we will have to do an | ||
| 1149 | * access to the page to ensure it gets faulted into the | ||
| 1150 | * hypervisor. For the moment virtualisation is not supported in | ||
| 1151 | * other areas so leave the access out. | ||
| 1152 | */ | ||
| 1153 | if (rc != 1) { | 1149 | if (rc != 1) { |
| 1154 | status[i] = rc; | 1150 | status[i] = rc; |
| 1155 | result = -EFAULT; | 1151 | result = -EFAULT; |
| 1156 | continue; | 1152 | continue; |
| 1157 | } | 1153 | } |
| 1158 | 1154 | ||
| 1155 | /* Make sure partition scoped tree gets a pte */ | ||
| 1156 | u = page_address(page[0]); | ||
| 1157 | if (__get_user(c, u)) | ||
| 1158 | result = -EFAULT; | ||
| 1159 | |||
| 1159 | status[i] = 0; | 1160 | status[i] = 0; |
| 1160 | put_page(page[0]); | 1161 | put_page(page[0]); |
| 1161 | } | 1162 | } |
