aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kvm/arm.c
diff options
context:
space:
mode:
authorChristoffer Dall <c.dall@virtualopensystems.com>2013-01-20 18:28:07 -0500
committerChristoffer Dall <c.dall@virtualopensystems.com>2013-01-23 13:29:11 -0500
commitd5d8184d35c990b1324d9b30bcd0e4e8aa08f56d (patch)
tree7559fbc98d2b347f89f926b39715d3bf3cfbb719 /arch/arm/kvm/arm.c
parent342cd0ab0e6ca3fe7c88a78890352748b8e894a9 (diff)
KVM: ARM: Memory virtualization setup
This commit introduces the framework for guest memory management through the use of 2nd stage translation. Each VM has a pointer to a level-1 table (the pgd field in struct kvm_arch) which is used for the 2nd stage translations. Entries are added when handling guest faults (later patch) and the table itself can be allocated and freed through the following functions implemented in arch/arm/kvm/arm_mmu.c: - kvm_alloc_stage2_pgd(struct kvm *kvm); - kvm_free_stage2_pgd(struct kvm *kvm); Each entry in TLBs and caches are tagged with a VMID identifier in addition to ASIDs. The VMIDs are assigned consecutively to VMs in the order that VMs are executed, and caches and tlbs are invalidated when the VMID space has been used to allow for more than 255 simultaenously running guests. The 2nd stage pgd is allocated in kvm_arch_init_vm(). The table is freed in kvm_arch_destroy_vm(). Both functions are called from the main KVM code. We pre-allocate page table memory to be able to synchronize using a spinlock and be called under rcu_read_lock from the MMU notifiers. We steal the mmu_memory_cache implementation from x86 and adapt for our specific usage. We support MMU notifiers (thanks to Marc Zyngier) through kvm_unmap_hva and kvm_set_spte_hva. Finally, define kvm_phys_addr_ioremap() to map a device at a guest IPA, which is used by VGIC support to map the virtual CPU interface registers to the guest. This support is added by Marc Zyngier. Reviewed-by: Will Deacon <will.deacon@arm.com> Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
Diffstat (limited to 'arch/arm/kvm/arm.c')
-rw-r--r--arch/arm/kvm/arm.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 2c6b780e78a7..d810afb6cb84 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -81,12 +81,33 @@ void kvm_arch_sync_events(struct kvm *kvm)
81{ 81{
82} 82}
83 83
84/**
85 * kvm_arch_init_vm - initializes a VM data structure
86 * @kvm: pointer to the KVM struct
87 */
84int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) 88int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
85{ 89{
90 int ret = 0;
91
86 if (type) 92 if (type)
87 return -EINVAL; 93 return -EINVAL;
88 94
89 return 0; 95 ret = kvm_alloc_stage2_pgd(kvm);
96 if (ret)
97 goto out_fail_alloc;
98
99 ret = create_hyp_mappings(kvm, kvm + 1);
100 if (ret)
101 goto out_free_stage2_pgd;
102
103 /* Mark the initial VMID generation invalid */
104 kvm->arch.vmid_gen = 0;
105
106 return ret;
107out_free_stage2_pgd:
108 kvm_free_stage2_pgd(kvm);
109out_fail_alloc:
110 return ret;
90} 111}
91 112
92int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) 113int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
@@ -104,10 +125,16 @@ int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
104 return 0; 125 return 0;
105} 126}
106 127
128/**
129 * kvm_arch_destroy_vm - destroy the VM data structure
130 * @kvm: pointer to the KVM struct
131 */
107void kvm_arch_destroy_vm(struct kvm *kvm) 132void kvm_arch_destroy_vm(struct kvm *kvm)
108{ 133{
109 int i; 134 int i;
110 135
136 kvm_free_stage2_pgd(kvm);
137
111 for (i = 0; i < KVM_MAX_VCPUS; ++i) { 138 for (i = 0; i < KVM_MAX_VCPUS; ++i) {
112 if (kvm->vcpus[i]) { 139 if (kvm->vcpus[i]) {
113 kvm_arch_vcpu_free(kvm->vcpus[i]); 140 kvm_arch_vcpu_free(kvm->vcpus[i]);
@@ -196,7 +223,13 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
196 if (err) 223 if (err)
197 goto free_vcpu; 224 goto free_vcpu;
198 225
226 err = create_hyp_mappings(vcpu, vcpu + 1);
227 if (err)
228 goto vcpu_uninit;
229
199 return vcpu; 230 return vcpu;
231vcpu_uninit:
232 kvm_vcpu_uninit(vcpu);
200free_vcpu: 233free_vcpu:
201 kmem_cache_free(kvm_vcpu_cache, vcpu); 234 kmem_cache_free(kvm_vcpu_cache, vcpu);
202out: 235out:
@@ -210,6 +243,8 @@ int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
210 243
211void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) 244void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
212{ 245{
246 kvm_mmu_free_memory_caches(vcpu);
247 kmem_cache_free(kvm_vcpu_cache, vcpu);
213} 248}
214 249
215void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) 250void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)