diff options
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r-- | drivers/kvm/kvm_main.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index a6cd1c1fe29a..291d298868fc 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/highmem.h> | 34 | #include <linux/highmem.h> |
35 | #include <linux/file.h> | 35 | #include <linux/file.h> |
36 | #include <asm/desc.h> | 36 | #include <asm/desc.h> |
37 | #include <linux/cpu.h> | ||
37 | 38 | ||
38 | #include "x86_emulate.h" | 39 | #include "x86_emulate.h" |
39 | #include "segment_descriptor.h" | 40 | #include "segment_descriptor.h" |
@@ -2039,6 +2040,64 @@ static struct notifier_block kvm_reboot_notifier = { | |||
2039 | .priority = 0, | 2040 | .priority = 0, |
2040 | }; | 2041 | }; |
2041 | 2042 | ||
2043 | /* | ||
2044 | * Make sure that a cpu that is being hot-unplugged does not have any vcpus | ||
2045 | * cached on it. | ||
2046 | */ | ||
2047 | static void decache_vcpus_on_cpu(int cpu) | ||
2048 | { | ||
2049 | struct kvm *vm; | ||
2050 | struct kvm_vcpu *vcpu; | ||
2051 | int i; | ||
2052 | |||
2053 | spin_lock(&kvm_lock); | ||
2054 | list_for_each_entry(vm, &vm_list, vm_list) | ||
2055 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | ||
2056 | vcpu = &vm->vcpus[i]; | ||
2057 | /* | ||
2058 | * If the vcpu is locked, then it is running on some | ||
2059 | * other cpu and therefore it is not cached on the | ||
2060 | * cpu in question. | ||
2061 | * | ||
2062 | * If it's not locked, check the last cpu it executed | ||
2063 | * on. | ||
2064 | */ | ||
2065 | if (mutex_trylock(&vcpu->mutex)) { | ||
2066 | if (vcpu->cpu == cpu) { | ||
2067 | kvm_arch_ops->vcpu_decache(vcpu); | ||
2068 | vcpu->cpu = -1; | ||
2069 | } | ||
2070 | mutex_unlock(&vcpu->mutex); | ||
2071 | } | ||
2072 | } | ||
2073 | spin_unlock(&kvm_lock); | ||
2074 | } | ||
2075 | |||
2076 | static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, | ||
2077 | void *v) | ||
2078 | { | ||
2079 | int cpu = (long)v; | ||
2080 | |||
2081 | switch (val) { | ||
2082 | case CPU_DEAD: | ||
2083 | case CPU_UP_CANCELED: | ||
2084 | decache_vcpus_on_cpu(cpu); | ||
2085 | smp_call_function_single(cpu, kvm_arch_ops->hardware_disable, | ||
2086 | NULL, 0, 1); | ||
2087 | break; | ||
2088 | case CPU_UP_PREPARE: | ||
2089 | smp_call_function_single(cpu, kvm_arch_ops->hardware_enable, | ||
2090 | NULL, 0, 1); | ||
2091 | break; | ||
2092 | } | ||
2093 | return NOTIFY_OK; | ||
2094 | } | ||
2095 | |||
2096 | static struct notifier_block kvm_cpu_notifier = { | ||
2097 | .notifier_call = kvm_cpu_hotplug, | ||
2098 | .priority = 20, /* must be > scheduler priority */ | ||
2099 | }; | ||
2100 | |||
2042 | static __init void kvm_init_debug(void) | 2101 | static __init void kvm_init_debug(void) |
2043 | { | 2102 | { |
2044 | struct kvm_stats_debugfs_item *p; | 2103 | struct kvm_stats_debugfs_item *p; |
@@ -2085,6 +2144,9 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) | |||
2085 | return r; | 2144 | return r; |
2086 | 2145 | ||
2087 | on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1); | 2146 | on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1); |
2147 | r = register_cpu_notifier(&kvm_cpu_notifier); | ||
2148 | if (r) | ||
2149 | goto out_free_1; | ||
2088 | register_reboot_notifier(&kvm_reboot_notifier); | 2150 | register_reboot_notifier(&kvm_reboot_notifier); |
2089 | 2151 | ||
2090 | kvm_chardev_ops.owner = module; | 2152 | kvm_chardev_ops.owner = module; |
@@ -2099,6 +2161,8 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) | |||
2099 | 2161 | ||
2100 | out_free: | 2162 | out_free: |
2101 | unregister_reboot_notifier(&kvm_reboot_notifier); | 2163 | unregister_reboot_notifier(&kvm_reboot_notifier); |
2164 | unregister_cpu_notifier(&kvm_cpu_notifier); | ||
2165 | out_free_1: | ||
2102 | on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); | 2166 | on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); |
2103 | kvm_arch_ops->hardware_unsetup(); | 2167 | kvm_arch_ops->hardware_unsetup(); |
2104 | return r; | 2168 | return r; |