diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/kvm/kvm.h | 6 | ||||
-rw-r--r-- | drivers/kvm/kvm_main.c | 22 |
2 files changed, 26 insertions, 2 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index f3dda088e34b..82c3b13e5d0a 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h | |||
@@ -41,6 +41,8 @@ | |||
41 | #define KVM_MAX_VCPUS 4 | 41 | #define KVM_MAX_VCPUS 4 |
42 | #define KVM_ALIAS_SLOTS 4 | 42 | #define KVM_ALIAS_SLOTS 4 |
43 | #define KVM_MEMORY_SLOTS 8 | 43 | #define KVM_MEMORY_SLOTS 8 |
44 | /* memory slots that does not exposed to userspace */ | ||
45 | #define KVM_PRIVATE_MEM_SLOTS 4 | ||
44 | #define KVM_PERMILLE_MMU_PAGES 20 | 46 | #define KVM_PERMILLE_MMU_PAGES 20 |
45 | #define KVM_MIN_ALLOC_MMU_PAGES 64 | 47 | #define KVM_MIN_ALLOC_MMU_PAGES 64 |
46 | #define KVM_NUM_MMU_PAGES 1024 | 48 | #define KVM_NUM_MMU_PAGES 1024 |
@@ -361,7 +363,8 @@ struct kvm { | |||
361 | int naliases; | 363 | int naliases; |
362 | struct kvm_mem_alias aliases[KVM_ALIAS_SLOTS]; | 364 | struct kvm_mem_alias aliases[KVM_ALIAS_SLOTS]; |
363 | int nmemslots; | 365 | int nmemslots; |
364 | struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS]; | 366 | struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS + |
367 | KVM_PRIVATE_MEM_SLOTS]; | ||
365 | /* | 368 | /* |
366 | * Hash table of struct kvm_mmu_page. | 369 | * Hash table of struct kvm_mmu_page. |
367 | */ | 370 | */ |
@@ -529,6 +532,7 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data, | |||
529 | int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); | 532 | int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); |
530 | int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); | 533 | int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); |
531 | struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); | 534 | struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); |
535 | int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn); | ||
532 | void mark_page_dirty(struct kvm *kvm, gfn_t gfn); | 536 | void mark_page_dirty(struct kvm *kvm, gfn_t gfn); |
533 | 537 | ||
534 | enum emulation_result { | 538 | enum emulation_result { |
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 5113cbf75674..a044856bd02b 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -660,7 +660,7 @@ int kvm_set_memory_region(struct kvm *kvm, | |||
660 | goto out; | 660 | goto out; |
661 | if (mem->guest_phys_addr & (PAGE_SIZE - 1)) | 661 | if (mem->guest_phys_addr & (PAGE_SIZE - 1)) |
662 | goto out; | 662 | goto out; |
663 | if (mem->slot >= KVM_MEMORY_SLOTS) | 663 | if (mem->slot >= KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS) |
664 | goto out; | 664 | goto out; |
665 | if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr) | 665 | if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr) |
666 | goto out; | 666 | goto out; |
@@ -797,6 +797,8 @@ static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm, | |||
797 | kvm_userspace_memory_region *mem, | 797 | kvm_userspace_memory_region *mem, |
798 | int user_alloc) | 798 | int user_alloc) |
799 | { | 799 | { |
800 | if (mem->slot >= KVM_MEMORY_SLOTS) | ||
801 | return -EINVAL; | ||
800 | return kvm_set_memory_region(kvm, mem, user_alloc); | 802 | return kvm_set_memory_region(kvm, mem, user_alloc); |
801 | } | 803 | } |
802 | 804 | ||
@@ -1010,6 +1012,22 @@ struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn) | |||
1010 | return __gfn_to_memslot(kvm, gfn); | 1012 | return __gfn_to_memslot(kvm, gfn); |
1011 | } | 1013 | } |
1012 | 1014 | ||
1015 | int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn) | ||
1016 | { | ||
1017 | int i; | ||
1018 | |||
1019 | gfn = unalias_gfn(kvm, gfn); | ||
1020 | for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { | ||
1021 | struct kvm_memory_slot *memslot = &kvm->memslots[i]; | ||
1022 | |||
1023 | if (gfn >= memslot->base_gfn | ||
1024 | && gfn < memslot->base_gfn + memslot->npages) | ||
1025 | return 1; | ||
1026 | } | ||
1027 | return 0; | ||
1028 | } | ||
1029 | EXPORT_SYMBOL_GPL(kvm_is_visible_gfn); | ||
1030 | |||
1013 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) | 1031 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) |
1014 | { | 1032 | { |
1015 | struct kvm_memory_slot *slot; | 1033 | struct kvm_memory_slot *slot; |
@@ -3087,6 +3105,8 @@ static struct page *kvm_vm_nopage(struct vm_area_struct *vma, | |||
3087 | struct page *page; | 3105 | struct page *page; |
3088 | 3106 | ||
3089 | pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; | 3107 | pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; |
3108 | if (!kvm_is_visible_gfn(kvm, pgoff)) | ||
3109 | return NOPAGE_SIGBUS; | ||
3090 | page = gfn_to_page(kvm, pgoff); | 3110 | page = gfn_to_page(kvm, pgoff); |
3091 | if (is_error_page(page)) { | 3111 | if (is_error_page(page)) { |
3092 | kvm_release_page(page); | 3112 | kvm_release_page(page); |