Skip to content

Commit

Permalink
KVM: Keep track of which cpus have virtualization enabled
Browse files Browse the repository at this point in the history
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 <avi@qumranet.com>
  • Loading branch information
Avi Kivity committed Jul 16, 2007
1 parent a52b175 commit 1b6c016
Showing 1 changed file with 33 additions and 12 deletions.
45 changes: 33 additions & 12 deletions drivers/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -3168,7 +3189,7 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module)
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;
Expand All @@ -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;
}
Expand Down

0 comments on commit 1b6c016

Please sign in to comment.