Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=1b6c016818a562aaea22b1a1b05b15c796b0c2f0
Commit:     1b6c016818a562aaea22b1a1b05b15c796b0c2f0
Parent:     a52b1752c077cb919b71167c54968a0b91673281
Author:     Avi Kivity <[EMAIL PROTECTED]>
AuthorDate: Thu May 24 13:03:52 2007 +0300
Committer:  Avi Kivity <[EMAIL PROTECTED]>
CommitDate: Mon Jul 16 12:05:51 2007 +0300

    KVM: Keep track of which cpus have virtualization enabled
    
    By keeping track of which cpus have virtualization enabled, we
    prevent double-enable or double-disable during hotplug, which is a
    very fatal oops.
    
    Signed-off-by: Avi Kivity <[EMAIL PROTECTED]>
---
 drivers/kvm/kvm_main.c |   45 +++++++++++++++++++++++++++++++++------------
 1 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index ea02719..3226ad4 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -50,8 +50,12 @@ MODULE_LICENSE("GPL");
 static DEFINE_SPINLOCK(kvm_lock);
 static LIST_HEAD(vm_list);
 
+static cpumask_t cpus_hardware_enabled;
+
 struct kvm_arch_ops *kvm_arch_ops;
 
+static void hardware_disable(void *ignored);
+
 #define STAT_OFFSET(x) offsetof(struct kvm_vcpu, stat.x)
 
 static struct kvm_stats_debugfs_item {
@@ -2930,7 +2934,7 @@ static int kvm_reboot(struct notifier_block *notifier, 
unsigned long val,
                 * in vmx root mode.
                 */
                printk(KERN_INFO "kvm: exiting hardware virtualization\n");
-               on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
+               on_each_cpu(hardware_disable, NULL, 0, 1);
        }
        return NOTIFY_OK;
 }
@@ -2973,6 +2977,27 @@ static void decache_vcpus_on_cpu(int cpu)
        spin_unlock(&kvm_lock);
 }
 
+static void hardware_enable(void *junk)
+{
+       int cpu = raw_smp_processor_id();
+
+       if (cpu_isset(cpu, cpus_hardware_enabled))
+               return;
+       cpu_set(cpu, cpus_hardware_enabled);
+       kvm_arch_ops->hardware_enable(NULL);
+}
+
+static void hardware_disable(void *junk)
+{
+       int cpu = raw_smp_processor_id();
+
+       if (!cpu_isset(cpu, cpus_hardware_enabled))
+               return;
+       cpu_clear(cpu, cpus_hardware_enabled);
+       decache_vcpus_on_cpu(cpu);
+       kvm_arch_ops->hardware_disable(NULL);
+}
+
 static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
                           void *v)
 {
@@ -2985,16 +3010,13 @@ static int kvm_cpu_hotplug(struct notifier_block 
*notifier, unsigned long val,
        case CPU_UP_CANCELED_FROZEN:
                printk(KERN_INFO "kvm: disabling virtualization on CPU%d\n",
                       cpu);
-               decache_vcpus_on_cpu(cpu);
-               smp_call_function_single(cpu, kvm_arch_ops->hardware_disable,
-                                        NULL, 0, 1);
+               smp_call_function_single(cpu, hardware_disable, NULL, 0, 1);
                break;
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
                printk(KERN_INFO "kvm: enabling virtualization on CPU%d\n",
                       cpu);
-               smp_call_function_single(cpu, kvm_arch_ops->hardware_enable,
-                                        NULL, 0, 1);
+               smp_call_function_single(cpu, hardware_enable, NULL, 0, 1);
                break;
        }
        return NOTIFY_OK;
@@ -3088,14 +3110,13 @@ static void kvm_exit_debug(void)
 
 static int kvm_suspend(struct sys_device *dev, pm_message_t state)
 {
-       decache_vcpus_on_cpu(raw_smp_processor_id());
-       on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
+       on_each_cpu(hardware_disable, NULL, 0, 0);
        return 0;
 }
 
 static int kvm_resume(struct sys_device *dev)
 {
-       on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1);
+       on_each_cpu(hardware_disable, NULL, 0, 0);
        return 0;
 }
 
@@ -3136,7 +3157,7 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module 
*module)
        if (r < 0)
                goto out;
 
-       on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1);
+       on_each_cpu(hardware_enable, NULL, 0, 1);
        r = register_cpu_notifier(&kvm_cpu_notifier);
        if (r)
                goto out_free_1;
@@ -3168,7 +3189,7 @@ out_free_2:
        unregister_reboot_notifier(&kvm_reboot_notifier);
        unregister_cpu_notifier(&kvm_cpu_notifier);
 out_free_1:
-       on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
+       on_each_cpu(hardware_disable, NULL, 0, 1);
        kvm_arch_ops->hardware_unsetup();
 out:
        kvm_arch_ops = NULL;
@@ -3182,7 +3203,7 @@ void kvm_exit_arch(void)
        sysdev_class_unregister(&kvm_sysdev_class);
        unregister_reboot_notifier(&kvm_reboot_notifier);
        unregister_cpu_notifier(&kvm_cpu_notifier);
-       on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1);
+       on_each_cpu(hardware_disable, NULL, 0, 1);
        kvm_arch_ops->hardware_unsetup();
        kvm_arch_ops = NULL;
 }
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to