aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/kvm_main.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-03-30 09:54:30 -0400
committerAvi Kivity <avi@qumranet.com>2007-05-03 03:52:28 -0400
commite8207547d2f7b2f557bdb73015c1f74c32474438 (patch)
tree7e5c15bec5cf9ef45a81227b009e6449f5c6d47c /drivers/kvm/kvm_main.c
parent954bbbc236afe23b368abdf4942f313a5f6e1d50 (diff)
KVM: Add physical memory aliasing feature
With this, we can specify that accesses to one physical memory range will be remapped to another. This is useful for the vga window at 0xa0000 which is used as a movable window into the (much larger) framebuffer. Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r--drivers/kvm/kvm_main.c89
1 files changed, 86 insertions, 3 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index a0ec5dda3305..e495855727e2 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -846,7 +846,73 @@ out:
846 return r; 846 return r;
847} 847}
848 848
849struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn) 849/*
850 * Set a new alias region. Aliases map a portion of physical memory into
851 * another portion. This is useful for memory windows, for example the PC
852 * VGA region.
853 */
854static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
855 struct kvm_memory_alias *alias)
856{
857 int r, n;
858 struct kvm_mem_alias *p;
859
860 r = -EINVAL;
861 /* General sanity checks */
862 if (alias->memory_size & (PAGE_SIZE - 1))
863 goto out;
864 if (alias->guest_phys_addr & (PAGE_SIZE - 1))
865 goto out;
866 if (alias->slot >= KVM_ALIAS_SLOTS)
867 goto out;
868 if (alias->guest_phys_addr + alias->memory_size
869 < alias->guest_phys_addr)
870 goto out;
871 if (alias->target_phys_addr + alias->memory_size
872 < alias->target_phys_addr)
873 goto out;
874
875 spin_lock(&kvm->lock);
876
877 p = &kvm->aliases[alias->slot];
878 p->base_gfn = alias->guest_phys_addr >> PAGE_SHIFT;
879 p->npages = alias->memory_size >> PAGE_SHIFT;
880 p->target_gfn = alias->target_phys_addr >> PAGE_SHIFT;
881
882 for (n = KVM_ALIAS_SLOTS; n > 0; --n)
883 if (kvm->aliases[n - 1].npages)
884 break;
885 kvm->naliases = n;
886
887 spin_unlock(&kvm->lock);
888
889 vcpu_load(&kvm->vcpus[0]);
890 spin_lock(&kvm->lock);
891 kvm_mmu_zap_all(&kvm->vcpus[0]);
892 spin_unlock(&kvm->lock);
893 vcpu_put(&kvm->vcpus[0]);
894
895 return 0;
896
897out:
898 return r;
899}
900
901static gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
902{
903 int i;
904 struct kvm_mem_alias *alias;
905
906 for (i = 0; i < kvm->naliases; ++i) {
907 alias = &kvm->aliases[i];
908 if (gfn >= alias->base_gfn
909 && gfn < alias->base_gfn + alias->npages)
910 return alias->target_gfn + gfn - alias->base_gfn;
911 }
912 return gfn;
913}
914
915static struct kvm_memory_slot *__gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
850{ 916{
851 int i; 917 int i;
852 918
@@ -859,13 +925,19 @@ struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
859 } 925 }
860 return NULL; 926 return NULL;
861} 927}
862EXPORT_SYMBOL_GPL(gfn_to_memslot); 928
929struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn)
930{
931 gfn = unalias_gfn(kvm, gfn);
932 return __gfn_to_memslot(kvm, gfn);
933}
863 934
864struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) 935struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
865{ 936{
866 struct kvm_memory_slot *slot; 937 struct kvm_memory_slot *slot;
867 938
868 slot = gfn_to_memslot(kvm, gfn); 939 gfn = unalias_gfn(kvm, gfn);
940 slot = __gfn_to_memslot(kvm, gfn);
869 if (!slot) 941 if (!slot)
870 return NULL; 942 return NULL;
871 return slot->phys_mem[gfn - slot->base_gfn]; 943 return slot->phys_mem[gfn - slot->base_gfn];
@@ -2512,6 +2584,17 @@ static long kvm_vm_ioctl(struct file *filp,
2512 goto out; 2584 goto out;
2513 break; 2585 break;
2514 } 2586 }
2587 case KVM_SET_MEMORY_ALIAS: {
2588 struct kvm_memory_alias alias;
2589
2590 r = -EFAULT;
2591 if (copy_from_user(&alias, argp, sizeof alias))
2592 goto out;
2593 r = kvm_vm_ioctl_set_memory_alias(kvm, &alias);
2594 if (r)
2595 goto out;
2596 break;
2597 }
2515 default: 2598 default:
2516 ; 2599 ;
2517 } 2600 }