diff options
author | Jan Kiszka <jan.kiszka@siemens.com> | 2010-11-09 11:02:49 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-01-12 04:29:09 -0500 |
commit | d89f5eff70a31237ffa1e21c51d23ca532110aea (patch) | |
tree | 13b47648a564d8382e08d7e5937ea30ff0fb838c | |
parent | 9d893c6bc177b6ac5a1e937f4fdc359d272d68ff (diff) |
KVM: Clean up vm creation and release
IA64 support forces us to abstract the allocation of the kvm structure.
But instead of mixing this up with arch-specific initialization and
doing the same on destruction, split both steps. This allows to move
generic destruction calls into generic code.
It also fixes error clean-up on failures of kvm_create_vm for IA64.
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | arch/ia64/include/asm/kvm_host.h | 4 | ||||
-rw-r--r-- | arch/ia64/kvm/kvm-ia64.c | 28 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 20 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 23 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 12 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 15 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 19 |
7 files changed, 49 insertions, 72 deletions
diff --git a/arch/ia64/include/asm/kvm_host.h b/arch/ia64/include/asm/kvm_host.h index 2f229e5de498..2689ee54a1c9 100644 --- a/arch/ia64/include/asm/kvm_host.h +++ b/arch/ia64/include/asm/kvm_host.h | |||
@@ -590,6 +590,10 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu); | |||
590 | int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run); | 590 | int kvm_pal_emul(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run); |
591 | void kvm_sal_emul(struct kvm_vcpu *vcpu); | 591 | void kvm_sal_emul(struct kvm_vcpu *vcpu); |
592 | 592 | ||
593 | #define __KVM_HAVE_ARCH_VM_ALLOC 1 | ||
594 | struct kvm *kvm_arch_alloc_vm(void); | ||
595 | void kvm_arch_free_vm(struct kvm *kvm); | ||
596 | |||
593 | #endif /* __ASSEMBLY__*/ | 597 | #endif /* __ASSEMBLY__*/ |
594 | 598 | ||
595 | #endif | 599 | #endif |
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index f56a6316e134..48a48bdc59c3 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c | |||
@@ -749,7 +749,7 @@ out: | |||
749 | return r; | 749 | return r; |
750 | } | 750 | } |
751 | 751 | ||
752 | static struct kvm *kvm_alloc_kvm(void) | 752 | struct kvm *kvm_arch_alloc_vm(void) |
753 | { | 753 | { |
754 | 754 | ||
755 | struct kvm *kvm; | 755 | struct kvm *kvm; |
@@ -760,7 +760,7 @@ static struct kvm *kvm_alloc_kvm(void) | |||
760 | vm_base = __get_free_pages(GFP_KERNEL, get_order(KVM_VM_DATA_SIZE)); | 760 | vm_base = __get_free_pages(GFP_KERNEL, get_order(KVM_VM_DATA_SIZE)); |
761 | 761 | ||
762 | if (!vm_base) | 762 | if (!vm_base) |
763 | return ERR_PTR(-ENOMEM); | 763 | return NULL; |
764 | 764 | ||
765 | memset((void *)vm_base, 0, KVM_VM_DATA_SIZE); | 765 | memset((void *)vm_base, 0, KVM_VM_DATA_SIZE); |
766 | kvm = (struct kvm *)(vm_base + | 766 | kvm = (struct kvm *)(vm_base + |
@@ -806,10 +806,12 @@ static void kvm_build_io_pmt(struct kvm *kvm) | |||
806 | #define GUEST_PHYSICAL_RR4 0x2739 | 806 | #define GUEST_PHYSICAL_RR4 0x2739 |
807 | #define VMM_INIT_RR 0x1660 | 807 | #define VMM_INIT_RR 0x1660 |
808 | 808 | ||
809 | static void kvm_init_vm(struct kvm *kvm) | 809 | int kvm_arch_init_vm(struct kvm *kvm) |
810 | { | 810 | { |
811 | BUG_ON(!kvm); | 811 | BUG_ON(!kvm); |
812 | 812 | ||
813 | kvm->arch.is_sn2 = ia64_platform_is("sn2"); | ||
814 | |||
813 | kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0; | 815 | kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0; |
814 | kvm->arch.metaphysical_rr4 = GUEST_PHYSICAL_RR4; | 816 | kvm->arch.metaphysical_rr4 = GUEST_PHYSICAL_RR4; |
815 | kvm->arch.vmm_init_rr = VMM_INIT_RR; | 817 | kvm->arch.vmm_init_rr = VMM_INIT_RR; |
@@ -823,21 +825,8 @@ static void kvm_init_vm(struct kvm *kvm) | |||
823 | 825 | ||
824 | /* Reserve bit 0 of irq_sources_bitmap for userspace irq source */ | 826 | /* Reserve bit 0 of irq_sources_bitmap for userspace irq source */ |
825 | set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap); | 827 | set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap); |
826 | } | ||
827 | |||
828 | struct kvm *kvm_arch_create_vm(void) | ||
829 | { | ||
830 | struct kvm *kvm = kvm_alloc_kvm(); | ||
831 | |||
832 | if (IS_ERR(kvm)) | ||
833 | return ERR_PTR(-ENOMEM); | ||
834 | |||
835 | kvm->arch.is_sn2 = ia64_platform_is("sn2"); | ||
836 | |||
837 | kvm_init_vm(kvm); | ||
838 | |||
839 | return kvm; | ||
840 | 828 | ||
829 | return 0; | ||
841 | } | 830 | } |
842 | 831 | ||
843 | static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm, | 832 | static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm, |
@@ -1357,7 +1346,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, | |||
1357 | return -EINVAL; | 1346 | return -EINVAL; |
1358 | } | 1347 | } |
1359 | 1348 | ||
1360 | static void free_kvm(struct kvm *kvm) | 1349 | void kvm_arch_free_vm(struct kvm *kvm) |
1361 | { | 1350 | { |
1362 | unsigned long vm_base = kvm->arch.vm_base; | 1351 | unsigned long vm_base = kvm->arch.vm_base; |
1363 | 1352 | ||
@@ -1399,9 +1388,6 @@ void kvm_arch_destroy_vm(struct kvm *kvm) | |||
1399 | #endif | 1388 | #endif |
1400 | kfree(kvm->arch.vioapic); | 1389 | kfree(kvm->arch.vioapic); |
1401 | kvm_release_vm_pages(kvm); | 1390 | kvm_release_vm_pages(kvm); |
1402 | kvm_free_physmem(kvm); | ||
1403 | cleanup_srcu_struct(&kvm->srcu); | ||
1404 | free_kvm(kvm); | ||
1405 | } | 1391 | } |
1406 | 1392 | ||
1407 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) | 1393 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 38f756f25053..99758460efde 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -145,18 +145,12 @@ void kvm_arch_check_processor_compat(void *rtn) | |||
145 | *(int *)rtn = kvmppc_core_check_processor_compat(); | 145 | *(int *)rtn = kvmppc_core_check_processor_compat(); |
146 | } | 146 | } |
147 | 147 | ||
148 | struct kvm *kvm_arch_create_vm(void) | 148 | int kvm_arch_init_vm(struct kvm *kvm) |
149 | { | 149 | { |
150 | struct kvm *kvm; | 150 | return 0; |
151 | |||
152 | kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL); | ||
153 | if (!kvm) | ||
154 | return ERR_PTR(-ENOMEM); | ||
155 | |||
156 | return kvm; | ||
157 | } | 151 | } |
158 | 152 | ||
159 | static void kvmppc_free_vcpus(struct kvm *kvm) | 153 | void kvm_arch_destroy_vm(struct kvm *kvm) |
160 | { | 154 | { |
161 | unsigned int i; | 155 | unsigned int i; |
162 | struct kvm_vcpu *vcpu; | 156 | struct kvm_vcpu *vcpu; |
@@ -176,14 +170,6 @@ void kvm_arch_sync_events(struct kvm *kvm) | |||
176 | { | 170 | { |
177 | } | 171 | } |
178 | 172 | ||
179 | void kvm_arch_destroy_vm(struct kvm *kvm) | ||
180 | { | ||
181 | kvmppc_free_vcpus(kvm); | ||
182 | kvm_free_physmem(kvm); | ||
183 | cleanup_srcu_struct(&kvm->srcu); | ||
184 | kfree(kvm); | ||
185 | } | ||
186 | |||
187 | int kvm_dev_ioctl_check_extension(long ext) | 173 | int kvm_dev_ioctl_check_extension(long ext) |
188 | { | 174 | { |
189 | int r; | 175 | int r; |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 985d825494f1..bade533ba288 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -164,24 +164,18 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
164 | return r; | 164 | return r; |
165 | } | 165 | } |
166 | 166 | ||
167 | struct kvm *kvm_arch_create_vm(void) | 167 | int kvm_arch_init_vm(struct kvm *kvm) |
168 | { | 168 | { |
169 | struct kvm *kvm; | ||
170 | int rc; | 169 | int rc; |
171 | char debug_name[16]; | 170 | char debug_name[16]; |
172 | 171 | ||
173 | rc = s390_enable_sie(); | 172 | rc = s390_enable_sie(); |
174 | if (rc) | 173 | if (rc) |
175 | goto out_nokvm; | 174 | goto out_err; |
176 | |||
177 | rc = -ENOMEM; | ||
178 | kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL); | ||
179 | if (!kvm) | ||
180 | goto out_nokvm; | ||
181 | 175 | ||
182 | kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL); | 176 | kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL); |
183 | if (!kvm->arch.sca) | 177 | if (!kvm->arch.sca) |
184 | goto out_nosca; | 178 | goto out_err; |
185 | 179 | ||
186 | sprintf(debug_name, "kvm-%u", current->pid); | 180 | sprintf(debug_name, "kvm-%u", current->pid); |
187 | 181 | ||
@@ -195,13 +189,11 @@ struct kvm *kvm_arch_create_vm(void) | |||
195 | debug_register_view(kvm->arch.dbf, &debug_sprintf_view); | 189 | debug_register_view(kvm->arch.dbf, &debug_sprintf_view); |
196 | VM_EVENT(kvm, 3, "%s", "vm created"); | 190 | VM_EVENT(kvm, 3, "%s", "vm created"); |
197 | 191 | ||
198 | return kvm; | 192 | return 0; |
199 | out_nodbf: | 193 | out_nodbf: |
200 | free_page((unsigned long)(kvm->arch.sca)); | 194 | free_page((unsigned long)(kvm->arch.sca)); |
201 | out_nosca: | 195 | out_err: |
202 | kfree(kvm); | 196 | return rc; |
203 | out_nokvm: | ||
204 | return ERR_PTR(rc); | ||
205 | } | 197 | } |
206 | 198 | ||
207 | void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) | 199 | void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) |
@@ -240,11 +232,8 @@ void kvm_arch_sync_events(struct kvm *kvm) | |||
240 | void kvm_arch_destroy_vm(struct kvm *kvm) | 232 | void kvm_arch_destroy_vm(struct kvm *kvm) |
241 | { | 233 | { |
242 | kvm_free_vcpus(kvm); | 234 | kvm_free_vcpus(kvm); |
243 | kvm_free_physmem(kvm); | ||
244 | free_page((unsigned long)(kvm->arch.sca)); | 235 | free_page((unsigned long)(kvm->arch.sca)); |
245 | debug_unregister(kvm->arch.dbf); | 236 | debug_unregister(kvm->arch.dbf); |
246 | cleanup_srcu_struct(&kvm->srcu); | ||
247 | kfree(kvm); | ||
248 | } | 237 | } |
249 | 238 | ||
250 | /* Section: vcpu related */ | 239 | /* Section: vcpu related */ |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 5daead833669..b7ee61d5bc81 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -5961,13 +5961,8 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) | |||
5961 | free_page((unsigned long)vcpu->arch.pio_data); | 5961 | free_page((unsigned long)vcpu->arch.pio_data); |
5962 | } | 5962 | } |
5963 | 5963 | ||
5964 | struct kvm *kvm_arch_create_vm(void) | 5964 | int kvm_arch_init_vm(struct kvm *kvm) |
5965 | { | 5965 | { |
5966 | struct kvm *kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL); | ||
5967 | |||
5968 | if (!kvm) | ||
5969 | return ERR_PTR(-ENOMEM); | ||
5970 | |||
5971 | INIT_LIST_HEAD(&kvm->arch.active_mmu_pages); | 5966 | INIT_LIST_HEAD(&kvm->arch.active_mmu_pages); |
5972 | INIT_LIST_HEAD(&kvm->arch.assigned_dev_head); | 5967 | INIT_LIST_HEAD(&kvm->arch.assigned_dev_head); |
5973 | 5968 | ||
@@ -5976,7 +5971,7 @@ struct kvm *kvm_arch_create_vm(void) | |||
5976 | 5971 | ||
5977 | spin_lock_init(&kvm->arch.tsc_write_lock); | 5972 | spin_lock_init(&kvm->arch.tsc_write_lock); |
5978 | 5973 | ||
5979 | return kvm; | 5974 | return 0; |
5980 | } | 5975 | } |
5981 | 5976 | ||
5982 | static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu) | 5977 | static void kvm_unload_vcpu_mmu(struct kvm_vcpu *vcpu) |
@@ -6021,13 +6016,10 @@ void kvm_arch_destroy_vm(struct kvm *kvm) | |||
6021 | kfree(kvm->arch.vpic); | 6016 | kfree(kvm->arch.vpic); |
6022 | kfree(kvm->arch.vioapic); | 6017 | kfree(kvm->arch.vioapic); |
6023 | kvm_free_vcpus(kvm); | 6018 | kvm_free_vcpus(kvm); |
6024 | kvm_free_physmem(kvm); | ||
6025 | if (kvm->arch.apic_access_page) | 6019 | if (kvm->arch.apic_access_page) |
6026 | put_page(kvm->arch.apic_access_page); | 6020 | put_page(kvm->arch.apic_access_page); |
6027 | if (kvm->arch.ept_identity_pagetable) | 6021 | if (kvm->arch.ept_identity_pagetable) |
6028 | put_page(kvm->arch.ept_identity_pagetable); | 6022 | put_page(kvm->arch.ept_identity_pagetable); |
6029 | cleanup_srcu_struct(&kvm->srcu); | ||
6030 | kfree(kvm); | ||
6031 | } | 6023 | } |
6032 | 6024 | ||
6033 | int kvm_arch_prepare_memory_region(struct kvm *kvm, | 6025 | int kvm_arch_prepare_memory_region(struct kvm *kvm, |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index bcf71c7730f0..2d63f2c0137c 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/preempt.h> | 17 | #include <linux/preempt.h> |
18 | #include <linux/msi.h> | 18 | #include <linux/msi.h> |
19 | #include <linux/slab.h> | ||
19 | #include <asm/signal.h> | 20 | #include <asm/signal.h> |
20 | 21 | ||
21 | #include <linux/kvm.h> | 22 | #include <linux/kvm.h> |
@@ -441,7 +442,19 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu); | |||
441 | 442 | ||
442 | void kvm_free_physmem(struct kvm *kvm); | 443 | void kvm_free_physmem(struct kvm *kvm); |
443 | 444 | ||
444 | struct kvm *kvm_arch_create_vm(void); | 445 | #ifndef __KVM_HAVE_ARCH_VM_ALLOC |
446 | static inline struct kvm *kvm_arch_alloc_vm(void) | ||
447 | { | ||
448 | return kzalloc(sizeof(struct kvm), GFP_KERNEL); | ||
449 | } | ||
450 | |||
451 | static inline void kvm_arch_free_vm(struct kvm *kvm) | ||
452 | { | ||
453 | kfree(kvm); | ||
454 | } | ||
455 | #endif | ||
456 | |||
457 | int kvm_arch_init_vm(struct kvm *kvm); | ||
445 | void kvm_arch_destroy_vm(struct kvm *kvm); | 458 | void kvm_arch_destroy_vm(struct kvm *kvm); |
446 | void kvm_free_all_assigned_devices(struct kvm *kvm); | 459 | void kvm_free_all_assigned_devices(struct kvm *kvm); |
447 | void kvm_arch_sync_events(struct kvm *kvm); | 460 | void kvm_arch_sync_events(struct kvm *kvm); |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index fce0578eab0e..4023264c4cd5 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -383,11 +383,15 @@ static int kvm_init_mmu_notifier(struct kvm *kvm) | |||
383 | 383 | ||
384 | static struct kvm *kvm_create_vm(void) | 384 | static struct kvm *kvm_create_vm(void) |
385 | { | 385 | { |
386 | int r = 0, i; | 386 | int r, i; |
387 | struct kvm *kvm = kvm_arch_create_vm(); | 387 | struct kvm *kvm = kvm_arch_alloc_vm(); |
388 | 388 | ||
389 | if (IS_ERR(kvm)) | 389 | if (!kvm) |
390 | goto out; | 390 | return ERR_PTR(-ENOMEM); |
391 | |||
392 | r = kvm_arch_init_vm(kvm); | ||
393 | if (r) | ||
394 | goto out_err_nodisable; | ||
391 | 395 | ||
392 | r = hardware_enable_all(); | 396 | r = hardware_enable_all(); |
393 | if (r) | 397 | if (r) |
@@ -427,7 +431,7 @@ static struct kvm *kvm_create_vm(void) | |||
427 | spin_lock(&kvm_lock); | 431 | spin_lock(&kvm_lock); |
428 | list_add(&kvm->vm_list, &vm_list); | 432 | list_add(&kvm->vm_list, &vm_list); |
429 | spin_unlock(&kvm_lock); | 433 | spin_unlock(&kvm_lock); |
430 | out: | 434 | |
431 | return kvm; | 435 | return kvm; |
432 | 436 | ||
433 | out_err: | 437 | out_err: |
@@ -438,7 +442,7 @@ out_err_nodisable: | |||
438 | for (i = 0; i < KVM_NR_BUSES; i++) | 442 | for (i = 0; i < KVM_NR_BUSES; i++) |
439 | kfree(kvm->buses[i]); | 443 | kfree(kvm->buses[i]); |
440 | kfree(kvm->memslots); | 444 | kfree(kvm->memslots); |
441 | kfree(kvm); | 445 | kvm_arch_free_vm(kvm); |
442 | return ERR_PTR(r); | 446 | return ERR_PTR(r); |
443 | } | 447 | } |
444 | 448 | ||
@@ -512,6 +516,9 @@ static void kvm_destroy_vm(struct kvm *kvm) | |||
512 | kvm_arch_flush_shadow(kvm); | 516 | kvm_arch_flush_shadow(kvm); |
513 | #endif | 517 | #endif |
514 | kvm_arch_destroy_vm(kvm); | 518 | kvm_arch_destroy_vm(kvm); |
519 | kvm_free_physmem(kvm); | ||
520 | cleanup_srcu_struct(&kvm->srcu); | ||
521 | kvm_arch_free_vm(kvm); | ||
515 | hardware_disable_all(); | 522 | hardware_disable_all(); |
516 | mmdrop(mm); | 523 | mmdrop(mm); |
517 | } | 524 | } |