diff options
-rw-r--r-- | arch/ia64/kvm/kvm-ia64.c | 8 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 3 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/x86/kvm/svm.c | 13 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 11 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 4 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 2 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 90 |
9 files changed, 108 insertions, 28 deletions
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index f6471c882667..5fdeec5fddcf 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c | |||
@@ -124,7 +124,7 @@ long ia64_pal_vp_create(u64 *vpd, u64 *host_iva, u64 *opt_handler) | |||
124 | 124 | ||
125 | static DEFINE_SPINLOCK(vp_lock); | 125 | static DEFINE_SPINLOCK(vp_lock); |
126 | 126 | ||
127 | void kvm_arch_hardware_enable(void *garbage) | 127 | int kvm_arch_hardware_enable(void *garbage) |
128 | { | 128 | { |
129 | long status; | 129 | long status; |
130 | long tmp_base; | 130 | long tmp_base; |
@@ -137,7 +137,7 @@ void kvm_arch_hardware_enable(void *garbage) | |||
137 | slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT); | 137 | slot = ia64_itr_entry(0x3, KVM_VMM_BASE, pte, KVM_VMM_SHIFT); |
138 | local_irq_restore(saved_psr); | 138 | local_irq_restore(saved_psr); |
139 | if (slot < 0) | 139 | if (slot < 0) |
140 | return; | 140 | return -EINVAL; |
141 | 141 | ||
142 | spin_lock(&vp_lock); | 142 | spin_lock(&vp_lock); |
143 | status = ia64_pal_vp_init_env(kvm_vsa_base ? | 143 | status = ia64_pal_vp_init_env(kvm_vsa_base ? |
@@ -145,7 +145,7 @@ void kvm_arch_hardware_enable(void *garbage) | |||
145 | __pa(kvm_vm_buffer), KVM_VM_BUFFER_BASE, &tmp_base); | 145 | __pa(kvm_vm_buffer), KVM_VM_BUFFER_BASE, &tmp_base); |
146 | if (status != 0) { | 146 | if (status != 0) { |
147 | printk(KERN_WARNING"kvm: Failed to Enable VT Support!!!!\n"); | 147 | printk(KERN_WARNING"kvm: Failed to Enable VT Support!!!!\n"); |
148 | return ; | 148 | return -EINVAL; |
149 | } | 149 | } |
150 | 150 | ||
151 | if (!kvm_vsa_base) { | 151 | if (!kvm_vsa_base) { |
@@ -154,6 +154,8 @@ void kvm_arch_hardware_enable(void *garbage) | |||
154 | } | 154 | } |
155 | spin_unlock(&vp_lock); | 155 | spin_unlock(&vp_lock); |
156 | ia64_ptr_entry(0x3, slot); | 156 | ia64_ptr_entry(0x3, slot); |
157 | |||
158 | return 0; | ||
157 | } | 159 | } |
158 | 160 | ||
159 | void kvm_arch_hardware_disable(void *garbage) | 161 | void kvm_arch_hardware_disable(void *garbage) |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 95af62217b6b..5902bbc2411e 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -78,8 +78,9 @@ int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
78 | return r; | 78 | return r; |
79 | } | 79 | } |
80 | 80 | ||
81 | void kvm_arch_hardware_enable(void *garbage) | 81 | int kvm_arch_hardware_enable(void *garbage) |
82 | { | 82 | { |
83 | return 0; | ||
83 | } | 84 | } |
84 | 85 | ||
85 | void kvm_arch_hardware_disable(void *garbage) | 86 | void kvm_arch_hardware_disable(void *garbage) |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 00e2ce8e91f5..544505893c9f 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -74,9 +74,10 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
74 | static unsigned long long *facilities; | 74 | static unsigned long long *facilities; |
75 | 75 | ||
76 | /* Section: not file related */ | 76 | /* Section: not file related */ |
77 | void kvm_arch_hardware_enable(void *garbage) | 77 | int kvm_arch_hardware_enable(void *garbage) |
78 | { | 78 | { |
79 | /* every s390 is virtualization enabled ;-) */ | 79 | /* every s390 is virtualization enabled ;-) */ |
80 | return 0; | ||
80 | } | 81 | } |
81 | 82 | ||
82 | void kvm_arch_hardware_disable(void *garbage) | 83 | void kvm_arch_hardware_disable(void *garbage) |
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index a46e2dd9aca8..295c7c4d9c90 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -459,7 +459,7 @@ struct descriptor_table { | |||
459 | struct kvm_x86_ops { | 459 | struct kvm_x86_ops { |
460 | int (*cpu_has_kvm_support)(void); /* __init */ | 460 | int (*cpu_has_kvm_support)(void); /* __init */ |
461 | int (*disabled_by_bios)(void); /* __init */ | 461 | int (*disabled_by_bios)(void); /* __init */ |
462 | void (*hardware_enable)(void *dummy); /* __init */ | 462 | int (*hardware_enable)(void *dummy); |
463 | void (*hardware_disable)(void *dummy); | 463 | void (*hardware_disable)(void *dummy); |
464 | void (*check_processor_compatibility)(void *rtn); | 464 | void (*check_processor_compatibility)(void *rtn); |
465 | int (*hardware_setup)(void); /* __init */ | 465 | int (*hardware_setup)(void); /* __init */ |
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index f54c4f9d2865..59fe4d54da11 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -316,7 +316,7 @@ static void svm_hardware_disable(void *garbage) | |||
316 | cpu_svm_disable(); | 316 | cpu_svm_disable(); |
317 | } | 317 | } |
318 | 318 | ||
319 | static void svm_hardware_enable(void *garbage) | 319 | static int svm_hardware_enable(void *garbage) |
320 | { | 320 | { |
321 | 321 | ||
322 | struct svm_cpu_data *svm_data; | 322 | struct svm_cpu_data *svm_data; |
@@ -325,16 +325,20 @@ static void svm_hardware_enable(void *garbage) | |||
325 | struct desc_struct *gdt; | 325 | struct desc_struct *gdt; |
326 | int me = raw_smp_processor_id(); | 326 | int me = raw_smp_processor_id(); |
327 | 327 | ||
328 | rdmsrl(MSR_EFER, efer); | ||
329 | if (efer & EFER_SVME) | ||
330 | return -EBUSY; | ||
331 | |||
328 | if (!has_svm()) { | 332 | if (!has_svm()) { |
329 | printk(KERN_ERR "svm_cpu_init: err EOPNOTSUPP on %d\n", me); | 333 | printk(KERN_ERR "svm_cpu_init: err EOPNOTSUPP on %d\n", me); |
330 | return; | 334 | return -EINVAL; |
331 | } | 335 | } |
332 | svm_data = per_cpu(svm_data, me); | 336 | svm_data = per_cpu(svm_data, me); |
333 | 337 | ||
334 | if (!svm_data) { | 338 | if (!svm_data) { |
335 | printk(KERN_ERR "svm_cpu_init: svm_data is NULL on %d\n", | 339 | printk(KERN_ERR "svm_cpu_init: svm_data is NULL on %d\n", |
336 | me); | 340 | me); |
337 | return; | 341 | return -EINVAL; |
338 | } | 342 | } |
339 | 343 | ||
340 | svm_data->asid_generation = 1; | 344 | svm_data->asid_generation = 1; |
@@ -345,11 +349,12 @@ static void svm_hardware_enable(void *garbage) | |||
345 | gdt = (struct desc_struct *)gdt_descr.base; | 349 | gdt = (struct desc_struct *)gdt_descr.base; |
346 | svm_data->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS); | 350 | svm_data->tss_desc = (struct kvm_ldttss_desc *)(gdt + GDT_ENTRY_TSS); |
347 | 351 | ||
348 | rdmsrl(MSR_EFER, efer); | ||
349 | wrmsrl(MSR_EFER, efer | EFER_SVME); | 352 | wrmsrl(MSR_EFER, efer | EFER_SVME); |
350 | 353 | ||
351 | wrmsrl(MSR_VM_HSAVE_PA, | 354 | wrmsrl(MSR_VM_HSAVE_PA, |
352 | page_to_pfn(svm_data->save_area) << PAGE_SHIFT); | 355 | page_to_pfn(svm_data->save_area) << PAGE_SHIFT); |
356 | |||
357 | return 0; | ||
353 | } | 358 | } |
354 | 359 | ||
355 | static void svm_cpu_uninit(int cpu) | 360 | static void svm_cpu_uninit(int cpu) |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 73cb5dd960cf..a187570e4837 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -1138,12 +1138,15 @@ static __init int vmx_disabled_by_bios(void) | |||
1138 | /* locked but not enabled */ | 1138 | /* locked but not enabled */ |
1139 | } | 1139 | } |
1140 | 1140 | ||
1141 | static void hardware_enable(void *garbage) | 1141 | static int hardware_enable(void *garbage) |
1142 | { | 1142 | { |
1143 | int cpu = raw_smp_processor_id(); | 1143 | int cpu = raw_smp_processor_id(); |
1144 | u64 phys_addr = __pa(per_cpu(vmxarea, cpu)); | 1144 | u64 phys_addr = __pa(per_cpu(vmxarea, cpu)); |
1145 | u64 old; | 1145 | u64 old; |
1146 | 1146 | ||
1147 | if (read_cr4() & X86_CR4_VMXE) | ||
1148 | return -EBUSY; | ||
1149 | |||
1147 | INIT_LIST_HEAD(&per_cpu(vcpus_on_cpu, cpu)); | 1150 | INIT_LIST_HEAD(&per_cpu(vcpus_on_cpu, cpu)); |
1148 | rdmsrl(MSR_IA32_FEATURE_CONTROL, old); | 1151 | rdmsrl(MSR_IA32_FEATURE_CONTROL, old); |
1149 | if ((old & (FEATURE_CONTROL_LOCKED | | 1152 | if ((old & (FEATURE_CONTROL_LOCKED | |
@@ -1158,6 +1161,10 @@ static void hardware_enable(void *garbage) | |||
1158 | asm volatile (ASM_VMX_VMXON_RAX | 1161 | asm volatile (ASM_VMX_VMXON_RAX |
1159 | : : "a"(&phys_addr), "m"(phys_addr) | 1162 | : : "a"(&phys_addr), "m"(phys_addr) |
1160 | : "memory", "cc"); | 1163 | : "memory", "cc"); |
1164 | |||
1165 | ept_sync_global(); | ||
1166 | |||
1167 | return 0; | ||
1161 | } | 1168 | } |
1162 | 1169 | ||
1163 | static void vmclear_local_vcpus(void) | 1170 | static void vmclear_local_vcpus(void) |
@@ -4040,8 +4047,6 @@ static int __init vmx_init(void) | |||
4040 | if (bypass_guest_pf) | 4047 | if (bypass_guest_pf) |
4041 | kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull); | 4048 | kvm_mmu_set_nonpresent_ptes(~0xffeull, 0ull); |
4042 | 4049 | ||
4043 | ept_sync_global(); | ||
4044 | |||
4045 | return 0; | 4050 | return 0; |
4046 | 4051 | ||
4047 | out3: | 4052 | out3: |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 829e3063e2ab..3d83de8bcbf4 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -4691,9 +4691,9 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu) | |||
4691 | return kvm_x86_ops->vcpu_reset(vcpu); | 4691 | return kvm_x86_ops->vcpu_reset(vcpu); |
4692 | } | 4692 | } |
4693 | 4693 | ||
4694 | void kvm_arch_hardware_enable(void *garbage) | 4694 | int kvm_arch_hardware_enable(void *garbage) |
4695 | { | 4695 | { |
4696 | kvm_x86_ops->hardware_enable(garbage); | 4696 | return kvm_x86_ops->hardware_enable(garbage); |
4697 | } | 4697 | } |
4698 | 4698 | ||
4699 | void kvm_arch_hardware_disable(void *garbage) | 4699 | void kvm_arch_hardware_disable(void *garbage) |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index c0a1cc35f080..b985a29d8175 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -345,7 +345,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu); | |||
345 | void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu); | 345 | void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu); |
346 | 346 | ||
347 | int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu); | 347 | int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu); |
348 | void kvm_arch_hardware_enable(void *garbage); | 348 | int kvm_arch_hardware_enable(void *garbage); |
349 | void kvm_arch_hardware_disable(void *garbage); | 349 | void kvm_arch_hardware_disable(void *garbage); |
350 | int kvm_arch_hardware_setup(void); | 350 | int kvm_arch_hardware_setup(void); |
351 | void kvm_arch_hardware_unsetup(void); | 351 | void kvm_arch_hardware_unsetup(void); |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 38e4d2c34ac1..70c8cbea0a99 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -69,6 +69,8 @@ DEFINE_SPINLOCK(kvm_lock); | |||
69 | LIST_HEAD(vm_list); | 69 | LIST_HEAD(vm_list); |
70 | 70 | ||
71 | static cpumask_var_t cpus_hardware_enabled; | 71 | static cpumask_var_t cpus_hardware_enabled; |
72 | static int kvm_usage_count = 0; | ||
73 | static atomic_t hardware_enable_failed; | ||
72 | 74 | ||
73 | struct kmem_cache *kvm_vcpu_cache; | 75 | struct kmem_cache *kvm_vcpu_cache; |
74 | EXPORT_SYMBOL_GPL(kvm_vcpu_cache); | 76 | EXPORT_SYMBOL_GPL(kvm_vcpu_cache); |
@@ -79,6 +81,8 @@ struct dentry *kvm_debugfs_dir; | |||
79 | 81 | ||
80 | static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, | 82 | static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, |
81 | unsigned long arg); | 83 | unsigned long arg); |
84 | static int hardware_enable_all(void); | ||
85 | static void hardware_disable_all(void); | ||
82 | 86 | ||
83 | static bool kvm_rebooting; | 87 | static bool kvm_rebooting; |
84 | 88 | ||
@@ -339,6 +343,7 @@ static const struct mmu_notifier_ops kvm_mmu_notifier_ops = { | |||
339 | 343 | ||
340 | static struct kvm *kvm_create_vm(void) | 344 | static struct kvm *kvm_create_vm(void) |
341 | { | 345 | { |
346 | int r = 0; | ||
342 | struct kvm *kvm = kvm_arch_create_vm(); | 347 | struct kvm *kvm = kvm_arch_create_vm(); |
343 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET | 348 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET |
344 | struct page *page; | 349 | struct page *page; |
@@ -346,6 +351,11 @@ static struct kvm *kvm_create_vm(void) | |||
346 | 351 | ||
347 | if (IS_ERR(kvm)) | 352 | if (IS_ERR(kvm)) |
348 | goto out; | 353 | goto out; |
354 | |||
355 | r = hardware_enable_all(); | ||
356 | if (r) | ||
357 | goto out_err_nodisable; | ||
358 | |||
349 | #ifdef CONFIG_HAVE_KVM_IRQCHIP | 359 | #ifdef CONFIG_HAVE_KVM_IRQCHIP |
350 | INIT_HLIST_HEAD(&kvm->mask_notifier_list); | 360 | INIT_HLIST_HEAD(&kvm->mask_notifier_list); |
351 | INIT_HLIST_HEAD(&kvm->irq_ack_notifier_list); | 361 | INIT_HLIST_HEAD(&kvm->irq_ack_notifier_list); |
@@ -354,8 +364,8 @@ static struct kvm *kvm_create_vm(void) | |||
354 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET | 364 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET |
355 | page = alloc_page(GFP_KERNEL | __GFP_ZERO); | 365 | page = alloc_page(GFP_KERNEL | __GFP_ZERO); |
356 | if (!page) { | 366 | if (!page) { |
357 | kfree(kvm); | 367 | r = -ENOMEM; |
358 | return ERR_PTR(-ENOMEM); | 368 | goto out_err; |
359 | } | 369 | } |
360 | kvm->coalesced_mmio_ring = | 370 | kvm->coalesced_mmio_ring = |
361 | (struct kvm_coalesced_mmio_ring *)page_address(page); | 371 | (struct kvm_coalesced_mmio_ring *)page_address(page); |
@@ -363,15 +373,13 @@ static struct kvm *kvm_create_vm(void) | |||
363 | 373 | ||
364 | #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) | 374 | #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) |
365 | { | 375 | { |
366 | int err; | ||
367 | kvm->mmu_notifier.ops = &kvm_mmu_notifier_ops; | 376 | kvm->mmu_notifier.ops = &kvm_mmu_notifier_ops; |
368 | err = mmu_notifier_register(&kvm->mmu_notifier, current->mm); | 377 | r = mmu_notifier_register(&kvm->mmu_notifier, current->mm); |
369 | if (err) { | 378 | if (r) { |
370 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET | 379 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET |
371 | put_page(page); | 380 | put_page(page); |
372 | #endif | 381 | #endif |
373 | kfree(kvm); | 382 | goto out_err; |
374 | return ERR_PTR(err); | ||
375 | } | 383 | } |
376 | } | 384 | } |
377 | #endif | 385 | #endif |
@@ -395,6 +403,12 @@ static struct kvm *kvm_create_vm(void) | |||
395 | #endif | 403 | #endif |
396 | out: | 404 | out: |
397 | return kvm; | 405 | return kvm; |
406 | |||
407 | out_err: | ||
408 | hardware_disable_all(); | ||
409 | out_err_nodisable: | ||
410 | kfree(kvm); | ||
411 | return ERR_PTR(r); | ||
398 | } | 412 | } |
399 | 413 | ||
400 | /* | 414 | /* |
@@ -453,6 +467,7 @@ static void kvm_destroy_vm(struct kvm *kvm) | |||
453 | kvm_arch_flush_shadow(kvm); | 467 | kvm_arch_flush_shadow(kvm); |
454 | #endif | 468 | #endif |
455 | kvm_arch_destroy_vm(kvm); | 469 | kvm_arch_destroy_vm(kvm); |
470 | hardware_disable_all(); | ||
456 | mmdrop(mm); | 471 | mmdrop(mm); |
457 | } | 472 | } |
458 | 473 | ||
@@ -1644,11 +1659,21 @@ static struct miscdevice kvm_dev = { | |||
1644 | static void hardware_enable(void *junk) | 1659 | static void hardware_enable(void *junk) |
1645 | { | 1660 | { |
1646 | int cpu = raw_smp_processor_id(); | 1661 | int cpu = raw_smp_processor_id(); |
1662 | int r; | ||
1647 | 1663 | ||
1648 | if (cpumask_test_cpu(cpu, cpus_hardware_enabled)) | 1664 | if (cpumask_test_cpu(cpu, cpus_hardware_enabled)) |
1649 | return; | 1665 | return; |
1666 | |||
1650 | cpumask_set_cpu(cpu, cpus_hardware_enabled); | 1667 | cpumask_set_cpu(cpu, cpus_hardware_enabled); |
1651 | kvm_arch_hardware_enable(NULL); | 1668 | |
1669 | r = kvm_arch_hardware_enable(NULL); | ||
1670 | |||
1671 | if (r) { | ||
1672 | cpumask_clear_cpu(cpu, cpus_hardware_enabled); | ||
1673 | atomic_inc(&hardware_enable_failed); | ||
1674 | printk(KERN_INFO "kvm: enabling virtualization on " | ||
1675 | "CPU%d failed\n", cpu); | ||
1676 | } | ||
1652 | } | 1677 | } |
1653 | 1678 | ||
1654 | static void hardware_disable(void *junk) | 1679 | static void hardware_disable(void *junk) |
@@ -1661,11 +1686,52 @@ static void hardware_disable(void *junk) | |||
1661 | kvm_arch_hardware_disable(NULL); | 1686 | kvm_arch_hardware_disable(NULL); |
1662 | } | 1687 | } |
1663 | 1688 | ||
1689 | static void hardware_disable_all_nolock(void) | ||
1690 | { | ||
1691 | BUG_ON(!kvm_usage_count); | ||
1692 | |||
1693 | kvm_usage_count--; | ||
1694 | if (!kvm_usage_count) | ||
1695 | on_each_cpu(hardware_disable, NULL, 1); | ||
1696 | } | ||
1697 | |||
1698 | static void hardware_disable_all(void) | ||
1699 | { | ||
1700 | spin_lock(&kvm_lock); | ||
1701 | hardware_disable_all_nolock(); | ||
1702 | spin_unlock(&kvm_lock); | ||
1703 | } | ||
1704 | |||
1705 | static int hardware_enable_all(void) | ||
1706 | { | ||
1707 | int r = 0; | ||
1708 | |||
1709 | spin_lock(&kvm_lock); | ||
1710 | |||
1711 | kvm_usage_count++; | ||
1712 | if (kvm_usage_count == 1) { | ||
1713 | atomic_set(&hardware_enable_failed, 0); | ||
1714 | on_each_cpu(hardware_enable, NULL, 1); | ||
1715 | |||
1716 | if (atomic_read(&hardware_enable_failed)) { | ||
1717 | hardware_disable_all_nolock(); | ||
1718 | r = -EBUSY; | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | spin_unlock(&kvm_lock); | ||
1723 | |||
1724 | return r; | ||
1725 | } | ||
1726 | |||
1664 | static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, | 1727 | static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, |
1665 | void *v) | 1728 | void *v) |
1666 | { | 1729 | { |
1667 | int cpu = (long)v; | 1730 | int cpu = (long)v; |
1668 | 1731 | ||
1732 | if (!kvm_usage_count) | ||
1733 | return NOTIFY_OK; | ||
1734 | |||
1669 | val &= ~CPU_TASKS_FROZEN; | 1735 | val &= ~CPU_TASKS_FROZEN; |
1670 | switch (val) { | 1736 | switch (val) { |
1671 | case CPU_DYING: | 1737 | case CPU_DYING: |
@@ -1868,13 +1934,15 @@ static void kvm_exit_debug(void) | |||
1868 | 1934 | ||
1869 | static int kvm_suspend(struct sys_device *dev, pm_message_t state) | 1935 | static int kvm_suspend(struct sys_device *dev, pm_message_t state) |
1870 | { | 1936 | { |
1871 | hardware_disable(NULL); | 1937 | if (kvm_usage_count) |
1938 | hardware_disable(NULL); | ||
1872 | return 0; | 1939 | return 0; |
1873 | } | 1940 | } |
1874 | 1941 | ||
1875 | static int kvm_resume(struct sys_device *dev) | 1942 | static int kvm_resume(struct sys_device *dev) |
1876 | { | 1943 | { |
1877 | hardware_enable(NULL); | 1944 | if (kvm_usage_count) |
1945 | hardware_enable(NULL); | ||
1878 | return 0; | 1946 | return 0; |
1879 | } | 1947 | } |
1880 | 1948 | ||
@@ -1949,7 +2017,6 @@ int kvm_init(void *opaque, unsigned int vcpu_size, | |||
1949 | goto out_free_1; | 2017 | goto out_free_1; |
1950 | } | 2018 | } |
1951 | 2019 | ||
1952 | on_each_cpu(hardware_enable, NULL, 1); | ||
1953 | r = register_cpu_notifier(&kvm_cpu_notifier); | 2020 | r = register_cpu_notifier(&kvm_cpu_notifier); |
1954 | if (r) | 2021 | if (r) |
1955 | goto out_free_2; | 2022 | goto out_free_2; |
@@ -1999,7 +2066,6 @@ out_free_3: | |||
1999 | unregister_reboot_notifier(&kvm_reboot_notifier); | 2066 | unregister_reboot_notifier(&kvm_reboot_notifier); |
2000 | unregister_cpu_notifier(&kvm_cpu_notifier); | 2067 | unregister_cpu_notifier(&kvm_cpu_notifier); |
2001 | out_free_2: | 2068 | out_free_2: |
2002 | on_each_cpu(hardware_disable, NULL, 1); | ||
2003 | out_free_1: | 2069 | out_free_1: |
2004 | kvm_arch_hardware_unsetup(); | 2070 | kvm_arch_hardware_unsetup(); |
2005 | out_free_0a: | 2071 | out_free_0a: |