aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIzik Eidus <izike@qumranet.com>2007-10-24 17:57:46 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:56 -0500
commite0d62c7f48605119a7f9fa632e77561c89928963 (patch)
treeeb11b29780f12433897a720a7c9db719663152cf
parent210c7c4d7f200f00ec34960a8c96bb990cbd266d (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.h6
-rw-r--r--drivers/kvm/kvm_main.c22
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,
529int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); 532int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
530int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); 533int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len);
531struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); 534struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
535int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn);
532void mark_page_dirty(struct kvm *kvm, gfn_t gfn); 536void mark_page_dirty(struct kvm *kvm, gfn_t gfn);
533 537
534enum emulation_result { 538enum 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
1015int 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}
1029EXPORT_SYMBOL_GPL(kvm_is_visible_gfn);
1030
1013struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) 1031struct 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);