aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/kvm_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r--drivers/kvm/kvm_main.c64
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 */
2047static 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
2076static 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
2096static struct notifier_block kvm_cpu_notifier = {
2097 .notifier_call = kvm_cpu_hotplug,
2098 .priority = 20, /* must be > scheduler priority */
2099};
2100
2042static __init void kvm_init_debug(void) 2101static __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
2100out_free: 2162out_free:
2101 unregister_reboot_notifier(&kvm_reboot_notifier); 2163 unregister_reboot_notifier(&kvm_reboot_notifier);
2164 unregister_cpu_notifier(&kvm_cpu_notifier);
2165out_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;