aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm
diff options
context:
space:
mode:
authorXiao Guangrong <xiaoguangrong@cn.fujitsu.com>2010-08-22 07:10:28 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:51:26 -0400
commit887c08ac191efb103e33e589aacbc2ce1a3f131e (patch)
tree635b2da93109722e5a254041d5b193a8db99b8d9 /virt/kvm
parent45888a0c6edc305495b6bd72a30e66bc40b324c6 (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/kvm')
-rw-r--r--virt/kvm/kvm_main.c30
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
930static 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
935unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) 930unsigned 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}
944EXPORT_SYMBOL_GPL(gfn_to_hva); 939EXPORT_SYMBOL_GPL(gfn_to_hva);
945 940
946static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr) 941static 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(&current->mm->mmap_sem); 960 down_read(&current->mm->mmap_sem);
960 if (is_hwpoison_address(addr)) { 961 if (is_hwpoison_address(addr)) {
961 up_read(&current->mm->mmap_sem); 962 up_read(&current->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(&current->mm->mmap_sem); 971 up_read(&current->mm->mmap_sem);
972return_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
986pfn_t hva_to_pfn_atomic(struct kvm *kvm, unsigned long addr)
987{
988 return hva_to_pfn(kvm, addr, true);
989}
990EXPORT_SYMBOL_GPL(hva_to_pfn_atomic);
991
984pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn) 992pfn_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}
996EXPORT_SYMBOL_GPL(gfn_to_pfn); 1004EXPORT_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
1005struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) 1013struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)