diff options
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/kvm_main.c | 90 |
1 files changed, 78 insertions, 12 deletions
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: |