aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/kvm_main.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-02-12 03:54:47 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-12 12:48:41 -0500
commit774c47f1d78e373a6bd2964f4e278d1ce26c21cb (patch)
tree665fe9939425d7b4a16b97241e784f4183bd9558 /drivers/kvm/kvm_main.c
parent8d0be2b3bf4a55606967d7d84e56c52521e94333 (diff)
[PATCH] KVM: cpu hotplug support
On hotplug, we execute the hardware extension enable sequence. On unplug, we decache any vcpus that last ran on the exiting cpu, and execute the hardware extension disable sequence. Signed-off-by: Avi Kivity <avi@qumranet.com> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
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;