diff options
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r-- | virt/kvm/kvm_main.c | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 228f00f87966..475a100f3a22 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -952,6 +952,12 @@ unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) | |||
952 | } | 952 | } |
953 | EXPORT_SYMBOL_GPL(gfn_to_hva); | 953 | EXPORT_SYMBOL_GPL(gfn_to_hva); |
954 | 954 | ||
955 | static pfn_t get_fault_pfn(void) | ||
956 | { | ||
957 | get_page(fault_page); | ||
958 | return fault_pfn; | ||
959 | } | ||
960 | |||
955 | static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic, | 961 | static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic, |
956 | bool *async) | 962 | bool *async) |
957 | { | 963 | { |
@@ -974,7 +980,7 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic, | |||
974 | struct vm_area_struct *vma; | 980 | struct vm_area_struct *vma; |
975 | 981 | ||
976 | if (atomic) | 982 | if (atomic) |
977 | goto return_fault_page; | 983 | return get_fault_pfn(); |
978 | 984 | ||
979 | down_read(¤t->mm->mmap_sem); | 985 | down_read(¤t->mm->mmap_sem); |
980 | if (is_hwpoison_address(addr)) { | 986 | if (is_hwpoison_address(addr)) { |
@@ -983,22 +989,20 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic, | |||
983 | return page_to_pfn(hwpoison_page); | 989 | return page_to_pfn(hwpoison_page); |
984 | } | 990 | } |
985 | 991 | ||
986 | vma = find_vma(current->mm, addr); | 992 | vma = find_vma_intersection(current->mm, addr, addr+1); |
987 | 993 | ||
988 | if (vma == NULL || addr < vma->vm_start || | 994 | if (vma == NULL) |
989 | !(vma->vm_flags & VM_PFNMAP)) { | 995 | pfn = get_fault_pfn(); |
990 | if (async && !(vma->vm_flags & VM_PFNMAP) && | 996 | else if ((vma->vm_flags & VM_PFNMAP)) { |
991 | (vma->vm_flags & VM_WRITE)) | 997 | pfn = ((addr - vma->vm_start) >> PAGE_SHIFT) + |
998 | vma->vm_pgoff; | ||
999 | BUG_ON(!kvm_is_mmio_pfn(pfn)); | ||
1000 | } else { | ||
1001 | if (async && (vma->vm_flags & VM_WRITE)) | ||
992 | *async = true; | 1002 | *async = true; |
993 | up_read(¤t->mm->mmap_sem); | 1003 | pfn = get_fault_pfn(); |
994 | return_fault_page: | ||
995 | get_page(fault_page); | ||
996 | return page_to_pfn(fault_page); | ||
997 | } | 1004 | } |
998 | |||
999 | pfn = ((addr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; | ||
1000 | up_read(¤t->mm->mmap_sem); | 1005 | up_read(¤t->mm->mmap_sem); |
1001 | BUG_ON(!kvm_is_mmio_pfn(pfn)); | ||
1002 | } else | 1006 | } else |
1003 | pfn = page_to_pfn(page[0]); | 1007 | pfn = page_to_pfn(page[0]); |
1004 | 1008 | ||