diff options
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r-- | virt/kvm/kvm_main.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index f42d5c2a396d..2907d05cfcc3 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -1394,17 +1394,22 @@ out: | |||
1394 | 1394 | ||
1395 | static int kvm_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | 1395 | static int kvm_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
1396 | { | 1396 | { |
1397 | struct page *page[1]; | ||
1398 | unsigned long addr; | ||
1399 | int npages; | ||
1400 | gfn_t gfn = vmf->pgoff; | ||
1397 | struct kvm *kvm = vma->vm_file->private_data; | 1401 | struct kvm *kvm = vma->vm_file->private_data; |
1398 | struct page *page; | ||
1399 | 1402 | ||
1400 | if (!kvm_is_visible_gfn(kvm, vmf->pgoff)) | 1403 | addr = gfn_to_hva(kvm, gfn); |
1404 | if (kvm_is_error_hva(addr)) | ||
1401 | return VM_FAULT_SIGBUS; | 1405 | return VM_FAULT_SIGBUS; |
1402 | page = gfn_to_page(kvm, vmf->pgoff); | 1406 | |
1403 | if (is_error_page(page)) { | 1407 | npages = get_user_pages(current, current->mm, addr, 1, 1, 0, page, |
1404 | kvm_release_page_clean(page); | 1408 | NULL); |
1409 | if (unlikely(npages != 1)) | ||
1405 | return VM_FAULT_SIGBUS; | 1410 | return VM_FAULT_SIGBUS; |
1406 | } | 1411 | |
1407 | vmf->page = page; | 1412 | vmf->page = page[0]; |
1408 | return 0; | 1413 | return 0; |
1409 | } | 1414 | } |
1410 | 1415 | ||