diff options
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/kvm_main.c | 29 |
1 files changed, 28 insertions, 1 deletions
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; |