diff options
author | Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> | 2010-08-22 07:10:28 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:51:26 -0400 |
commit | 887c08ac191efb103e33e589aacbc2ce1a3f131e (patch) | |
tree | 635b2da93109722e5a254041d5b193a8db99b8d9 /virt | |
parent | 45888a0c6edc305495b6bd72a30e66bc40b324c6 (diff) |
KVM: MMU: introduce hva_to_pfn_atomic function
Introduce hva_to_pfn_atomic(), it's the fast path and can used in atomic
context, the later patch will use it
Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/kvm_main.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index da117a6b1e2e..08bd304f8bc7 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -927,11 +927,6 @@ int memslot_id(struct kvm *kvm, gfn_t gfn) | |||
927 | return memslot - slots->memslots; | 927 | return memslot - slots->memslots; |
928 | } | 928 | } |
929 | 929 | ||
930 | static unsigned long gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn) | ||
931 | { | ||
932 | return slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE; | ||
933 | } | ||
934 | |||
935 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) | 930 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) |
936 | { | 931 | { |
937 | struct kvm_memory_slot *slot; | 932 | struct kvm_memory_slot *slot; |
@@ -943,19 +938,25 @@ unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) | |||
943 | } | 938 | } |
944 | EXPORT_SYMBOL_GPL(gfn_to_hva); | 939 | EXPORT_SYMBOL_GPL(gfn_to_hva); |
945 | 940 | ||
946 | static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr) | 941 | static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic) |
947 | { | 942 | { |
948 | struct page *page[1]; | 943 | struct page *page[1]; |
949 | int npages; | 944 | int npages; |
950 | pfn_t pfn; | 945 | pfn_t pfn; |
951 | 946 | ||
952 | might_sleep(); | 947 | if (atomic) |
953 | 948 | npages = __get_user_pages_fast(addr, 1, 1, page); | |
954 | npages = get_user_pages_fast(addr, 1, 1, page); | 949 | else { |
950 | might_sleep(); | ||
951 | npages = get_user_pages_fast(addr, 1, 1, page); | ||
952 | } | ||
955 | 953 | ||
956 | if (unlikely(npages != 1)) { | 954 | if (unlikely(npages != 1)) { |
957 | struct vm_area_struct *vma; | 955 | struct vm_area_struct *vma; |
958 | 956 | ||
957 | if (atomic) | ||
958 | goto return_fault_page; | ||
959 | |||
959 | down_read(¤t->mm->mmap_sem); | 960 | down_read(¤t->mm->mmap_sem); |
960 | if (is_hwpoison_address(addr)) { | 961 | if (is_hwpoison_address(addr)) { |
961 | up_read(¤t->mm->mmap_sem); | 962 | up_read(¤t->mm->mmap_sem); |
@@ -968,6 +969,7 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr) | |||
968 | if (vma == NULL || addr < vma->vm_start || | 969 | if (vma == NULL || addr < vma->vm_start || |
969 | !(vma->vm_flags & VM_PFNMAP)) { | 970 | !(vma->vm_flags & VM_PFNMAP)) { |
970 | up_read(¤t->mm->mmap_sem); | 971 | up_read(¤t->mm->mmap_sem); |
972 | return_fault_page: | ||
971 | get_page(fault_page); | 973 | get_page(fault_page); |
972 | return page_to_pfn(fault_page); | 974 | return page_to_pfn(fault_page); |
973 | } | 975 | } |
@@ -981,6 +983,12 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr) | |||
981 | return pfn; | 983 | return pfn; |
982 | } | 984 | } |
983 | 985 | ||
986 | pfn_t hva_to_pfn_atomic(struct kvm *kvm, unsigned long addr) | ||
987 | { | ||
988 | return hva_to_pfn(kvm, addr, true); | ||
989 | } | ||
990 | EXPORT_SYMBOL_GPL(hva_to_pfn_atomic); | ||
991 | |||
984 | pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn) | 992 | pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn) |
985 | { | 993 | { |
986 | unsigned long addr; | 994 | unsigned long addr; |
@@ -991,7 +999,7 @@ pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn) | |||
991 | return page_to_pfn(bad_page); | 999 | return page_to_pfn(bad_page); |
992 | } | 1000 | } |
993 | 1001 | ||
994 | return hva_to_pfn(kvm, addr); | 1002 | return hva_to_pfn(kvm, addr, false); |
995 | } | 1003 | } |
996 | EXPORT_SYMBOL_GPL(gfn_to_pfn); | 1004 | EXPORT_SYMBOL_GPL(gfn_to_pfn); |
997 | 1005 | ||
@@ -999,7 +1007,7 @@ pfn_t gfn_to_pfn_memslot(struct kvm *kvm, | |||
999 | struct kvm_memory_slot *slot, gfn_t gfn) | 1007 | struct kvm_memory_slot *slot, gfn_t gfn) |
1000 | { | 1008 | { |
1001 | unsigned long addr = gfn_to_hva_memslot(slot, gfn); | 1009 | unsigned long addr = gfn_to_hva_memslot(slot, gfn); |
1002 | return hva_to_pfn(kvm, addr); | 1010 | return hva_to_pfn(kvm, addr, false); |
1003 | } | 1011 | } |
1004 | 1012 | ||
1005 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) | 1013 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) |