diff options
-rw-r--r-- | include/linux/kvm_host.h | 3 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 29 |
2 files changed, 31 insertions, 1 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 307d0e2c0f59..b837ec80885d 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -289,6 +289,9 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, | |||
289 | void kvm_disable_largepages(void); | 289 | void kvm_disable_largepages(void); |
290 | void kvm_arch_flush_shadow(struct kvm *kvm); | 290 | void kvm_arch_flush_shadow(struct kvm *kvm); |
291 | 291 | ||
292 | int gfn_to_page_many_atomic(struct kvm *kvm, gfn_t gfn, struct page **pages, | ||
293 | int nr_pages); | ||
294 | |||
292 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn); | 295 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn); |
293 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn); | 296 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn); |
294 | void kvm_release_page_clean(struct page *page); | 297 | void kvm_release_page_clean(struct page *page); |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 08bd304f8bc7..2eb0b7500a2a 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -927,15 +927,25 @@ int memslot_id(struct kvm *kvm, gfn_t gfn) | |||
927 | return memslot - slots->memslots; | 927 | return memslot - slots->memslots; |
928 | } | 928 | } |
929 | 929 | ||
930 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) | 930 | static unsigned long gfn_to_hva_many(struct kvm *kvm, gfn_t gfn, |
931 | gfn_t *nr_pages) | ||
931 | { | 932 | { |
932 | struct kvm_memory_slot *slot; | 933 | struct kvm_memory_slot *slot; |
933 | 934 | ||
934 | slot = gfn_to_memslot(kvm, gfn); | 935 | slot = gfn_to_memslot(kvm, gfn); |
935 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID) | 936 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID) |
936 | return bad_hva(); | 937 | return bad_hva(); |
938 | |||
939 | if (nr_pages) | ||
940 | *nr_pages = slot->npages - (gfn - slot->base_gfn); | ||
941 | |||
937 | return gfn_to_hva_memslot(slot, gfn); | 942 | return gfn_to_hva_memslot(slot, gfn); |
938 | } | 943 | } |
944 | |||
945 | unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn) | ||
946 | { | ||
947 | return gfn_to_hva_many(kvm, gfn, NULL); | ||
948 | } | ||
939 | EXPORT_SYMBOL_GPL(gfn_to_hva); | 949 | EXPORT_SYMBOL_GPL(gfn_to_hva); |
940 | 950 | ||
941 | static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic) | 951 | static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic) |
@@ -1010,6 +1020,23 @@ pfn_t gfn_to_pfn_memslot(struct kvm *kvm, | |||
1010 | return hva_to_pfn(kvm, addr, false); | 1020 | return hva_to_pfn(kvm, addr, false); |
1011 | } | 1021 | } |
1012 | 1022 | ||
1023 | int gfn_to_page_many_atomic(struct kvm *kvm, gfn_t gfn, struct page **pages, | ||
1024 | int nr_pages) | ||
1025 | { | ||
1026 | unsigned long addr; | ||
1027 | gfn_t entry; | ||
1028 | |||
1029 | addr = gfn_to_hva_many(kvm, gfn, &entry); | ||
1030 | if (kvm_is_error_hva(addr)) | ||
1031 | return -1; | ||
1032 | |||
1033 | if (entry < nr_pages) | ||
1034 | return 0; | ||
1035 | |||
1036 | return __get_user_pages_fast(addr, nr_pages, 1, pages); | ||
1037 | } | ||
1038 | EXPORT_SYMBOL_GPL(gfn_to_page_many_atomic); | ||
1039 | |||
1013 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) | 1040 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) |
1014 | { | 1041 | { |
1015 | pfn_t pfn; | 1042 | pfn_t pfn; |