diff options
author | Izik Eidus <izike@qumranet.com> | 2007-10-24 17:57:46 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:52:56 -0500 |
commit | e0d62c7f48605119a7f9fa632e77561c89928963 (patch) | |
tree | eb11b29780f12433897a720a7c9db719663152cf | |
parent | 210c7c4d7f200f00ec34960a8c96bb990cbd266d (diff) |
KVM: Add kernel-internal memory slots
Reserve a few memory slots for kernel internal use. This is good for case
you have to register memory region and you want to be sure it was not
registered from userspace, and for case you want to register a memory region
that won't be seen from userspace.
Signed-off-by: Izik Eidus <izike@qumranet.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
-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); |