diff options
Diffstat (limited to 'drivers/kvm/kvm_main.c')
-rw-r--r-- | drivers/kvm/kvm_main.c | 123 |
1 files changed, 120 insertions, 3 deletions
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 099f0afd394d..af866147ff25 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c | |||
@@ -34,6 +34,8 @@ | |||
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/sysdev.h> | ||
38 | #include <linux/cpu.h> | ||
37 | 39 | ||
38 | #include "x86_emulate.h" | 40 | #include "x86_emulate.h" |
39 | #include "segment_descriptor.h" | 41 | #include "segment_descriptor.h" |
@@ -41,6 +43,9 @@ | |||
41 | MODULE_AUTHOR("Qumranet"); | 43 | MODULE_AUTHOR("Qumranet"); |
42 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
43 | 45 | ||
46 | static DEFINE_SPINLOCK(kvm_lock); | ||
47 | static LIST_HEAD(vm_list); | ||
48 | |||
44 | struct kvm_arch_ops *kvm_arch_ops; | 49 | struct kvm_arch_ops *kvm_arch_ops; |
45 | struct kvm_stat kvm_stat; | 50 | struct kvm_stat kvm_stat; |
46 | EXPORT_SYMBOL_GPL(kvm_stat); | 51 | EXPORT_SYMBOL_GPL(kvm_stat); |
@@ -230,9 +235,13 @@ static int kvm_dev_open(struct inode *inode, struct file *filp) | |||
230 | struct kvm_vcpu *vcpu = &kvm->vcpus[i]; | 235 | struct kvm_vcpu *vcpu = &kvm->vcpus[i]; |
231 | 236 | ||
232 | mutex_init(&vcpu->mutex); | 237 | mutex_init(&vcpu->mutex); |
238 | vcpu->cpu = -1; | ||
233 | vcpu->kvm = kvm; | 239 | vcpu->kvm = kvm; |
234 | vcpu->mmu.root_hpa = INVALID_PAGE; | 240 | vcpu->mmu.root_hpa = INVALID_PAGE; |
235 | INIT_LIST_HEAD(&vcpu->free_pages); | 241 | INIT_LIST_HEAD(&vcpu->free_pages); |
242 | spin_lock(&kvm_lock); | ||
243 | list_add(&kvm->vm_list, &vm_list); | ||
244 | spin_unlock(&kvm_lock); | ||
236 | } | 245 | } |
237 | filp->private_data = kvm; | 246 | filp->private_data = kvm; |
238 | return 0; | 247 | return 0; |
@@ -272,7 +281,9 @@ static void kvm_free_physmem(struct kvm *kvm) | |||
272 | 281 | ||
273 | static void kvm_free_vcpu(struct kvm_vcpu *vcpu) | 282 | static void kvm_free_vcpu(struct kvm_vcpu *vcpu) |
274 | { | 283 | { |
275 | vcpu_load(vcpu->kvm, vcpu_slot(vcpu)); | 284 | if (!vcpu_load(vcpu->kvm, vcpu_slot(vcpu))) |
285 | return; | ||
286 | |||
276 | kvm_mmu_destroy(vcpu); | 287 | kvm_mmu_destroy(vcpu); |
277 | vcpu_put(vcpu); | 288 | vcpu_put(vcpu); |
278 | kvm_arch_ops->vcpu_free(vcpu); | 289 | kvm_arch_ops->vcpu_free(vcpu); |
@@ -290,6 +301,9 @@ static int kvm_dev_release(struct inode *inode, struct file *filp) | |||
290 | { | 301 | { |
291 | struct kvm *kvm = filp->private_data; | 302 | struct kvm *kvm = filp->private_data; |
292 | 303 | ||
304 | spin_lock(&kvm_lock); | ||
305 | list_del(&kvm->vm_list); | ||
306 | spin_unlock(&kvm_lock); | ||
293 | kvm_free_vcpus(kvm); | 307 | kvm_free_vcpus(kvm); |
294 | kvm_free_physmem(kvm); | 308 | kvm_free_physmem(kvm); |
295 | kfree(kvm); | 309 | kfree(kvm); |
@@ -544,7 +558,6 @@ static int kvm_dev_ioctl_create_vcpu(struct kvm *kvm, int n) | |||
544 | FX_IMAGE_ALIGN); | 558 | FX_IMAGE_ALIGN); |
545 | vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE; | 559 | vcpu->guest_fx_image = vcpu->host_fx_image + FX_IMAGE_SIZE; |
546 | 560 | ||
547 | vcpu->cpu = -1; /* First load will set up TR */ | ||
548 | r = kvm_arch_ops->vcpu_create(vcpu); | 561 | r = kvm_arch_ops->vcpu_create(vcpu); |
549 | if (r < 0) | 562 | if (r < 0) |
550 | goto out_free_vcpus; | 563 | goto out_free_vcpus; |
@@ -1360,6 +1373,9 @@ static int kvm_dev_ioctl_run(struct kvm *kvm, struct kvm_run *kvm_run) | |||
1360 | if (!vcpu) | 1373 | if (!vcpu) |
1361 | return -ENOENT; | 1374 | return -ENOENT; |
1362 | 1375 | ||
1376 | /* re-sync apic's tpr */ | ||
1377 | vcpu->cr8 = kvm_run->cr8; | ||
1378 | |||
1363 | if (kvm_run->emulated) { | 1379 | if (kvm_run->emulated) { |
1364 | kvm_arch_ops->skip_emulated_instruction(vcpu); | 1380 | kvm_arch_ops->skip_emulated_instruction(vcpu); |
1365 | kvm_run->emulated = 0; | 1381 | kvm_run->emulated = 0; |
@@ -2025,6 +2041,64 @@ static struct notifier_block kvm_reboot_notifier = { | |||
2025 | .priority = 0, | 2041 | .priority = 0, |
2026 | }; | 2042 | }; |
2027 | 2043 | ||
2044 | /* | ||
2045 | * Make sure that a cpu that is being hot-unplugged does not have any vcpus | ||
2046 | * cached on it. | ||
2047 | */ | ||
2048 | static void decache_vcpus_on_cpu(int cpu) | ||
2049 | { | ||
2050 | struct kvm *vm; | ||
2051 | struct kvm_vcpu *vcpu; | ||
2052 | int i; | ||
2053 | |||
2054 | spin_lock(&kvm_lock); | ||
2055 | list_for_each_entry(vm, &vm_list, vm_list) | ||
2056 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | ||
2057 | vcpu = &vm->vcpus[i]; | ||
2058 | /* | ||
2059 | * If the vcpu is locked, then it is running on some | ||
2060 | * other cpu and therefore it is not cached on the | ||
2061 | * cpu in question. | ||
2062 | * | ||
2063 | * If it's not locked, check the last cpu it executed | ||
2064 | * on. | ||
2065 | */ | ||
2066 | if (mutex_trylock(&vcpu->mutex)) { | ||
2067 | if (vcpu->cpu == cpu) { | ||
2068 | kvm_arch_ops->vcpu_decache(vcpu); | ||
2069 | vcpu->cpu = -1; | ||
2070 | } | ||
2071 | mutex_unlock(&vcpu->mutex); | ||
2072 | } | ||
2073 | } | ||
2074 | spin_unlock(&kvm_lock); | ||
2075 | } | ||
2076 | |||
2077 | static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, | ||
2078 | void *v) | ||
2079 | { | ||
2080 | int cpu = (long)v; | ||
2081 | |||
2082 | switch (val) { | ||
2083 | case CPU_DEAD: | ||
2084 | case CPU_UP_CANCELED: | ||
2085 | decache_vcpus_on_cpu(cpu); | ||
2086 | smp_call_function_single(cpu, kvm_arch_ops->hardware_disable, | ||
2087 | NULL, 0, 1); | ||
2088 | break; | ||
2089 | case CPU_UP_PREPARE: | ||
2090 | smp_call_function_single(cpu, kvm_arch_ops->hardware_enable, | ||
2091 | NULL, 0, 1); | ||
2092 | break; | ||
2093 | } | ||
2094 | return NOTIFY_OK; | ||
2095 | } | ||
2096 | |||
2097 | static struct notifier_block kvm_cpu_notifier = { | ||
2098 | .notifier_call = kvm_cpu_hotplug, | ||
2099 | .priority = 20, /* must be > scheduler priority */ | ||
2100 | }; | ||
2101 | |||
2028 | static __init void kvm_init_debug(void) | 2102 | static __init void kvm_init_debug(void) |
2029 | { | 2103 | { |
2030 | struct kvm_stats_debugfs_item *p; | 2104 | struct kvm_stats_debugfs_item *p; |
@@ -2044,6 +2118,30 @@ static void kvm_exit_debug(void) | |||
2044 | debugfs_remove(debugfs_dir); | 2118 | debugfs_remove(debugfs_dir); |
2045 | } | 2119 | } |
2046 | 2120 | ||
2121 | static int kvm_suspend(struct sys_device *dev, pm_message_t state) | ||
2122 | { | ||
2123 | decache_vcpus_on_cpu(raw_smp_processor_id()); | ||
2124 | on_each_cpu(kvm_arch_ops->hardware_disable, 0, 0, 1); | ||
2125 | return 0; | ||
2126 | } | ||
2127 | |||
2128 | static int kvm_resume(struct sys_device *dev) | ||
2129 | { | ||
2130 | on_each_cpu(kvm_arch_ops->hardware_enable, 0, 0, 1); | ||
2131 | return 0; | ||
2132 | } | ||
2133 | |||
2134 | static struct sysdev_class kvm_sysdev_class = { | ||
2135 | set_kset_name("kvm"), | ||
2136 | .suspend = kvm_suspend, | ||
2137 | .resume = kvm_resume, | ||
2138 | }; | ||
2139 | |||
2140 | static struct sys_device kvm_sysdev = { | ||
2141 | .id = 0, | ||
2142 | .cls = &kvm_sysdev_class, | ||
2143 | }; | ||
2144 | |||
2047 | hpa_t bad_page_address; | 2145 | hpa_t bad_page_address; |
2048 | 2146 | ||
2049 | int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) | 2147 | int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) |
@@ -2071,8 +2169,19 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) | |||
2071 | return r; | 2169 | return r; |
2072 | 2170 | ||
2073 | on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1); | 2171 | on_each_cpu(kvm_arch_ops->hardware_enable, NULL, 0, 1); |
2172 | r = register_cpu_notifier(&kvm_cpu_notifier); | ||
2173 | if (r) | ||
2174 | goto out_free_1; | ||
2074 | register_reboot_notifier(&kvm_reboot_notifier); | 2175 | register_reboot_notifier(&kvm_reboot_notifier); |
2075 | 2176 | ||
2177 | r = sysdev_class_register(&kvm_sysdev_class); | ||
2178 | if (r) | ||
2179 | goto out_free_2; | ||
2180 | |||
2181 | r = sysdev_register(&kvm_sysdev); | ||
2182 | if (r) | ||
2183 | goto out_free_3; | ||
2184 | |||
2076 | kvm_chardev_ops.owner = module; | 2185 | kvm_chardev_ops.owner = module; |
2077 | 2186 | ||
2078 | r = misc_register(&kvm_dev); | 2187 | r = misc_register(&kvm_dev); |
@@ -2084,7 +2193,13 @@ int kvm_init_arch(struct kvm_arch_ops *ops, struct module *module) | |||
2084 | return r; | 2193 | return r; |
2085 | 2194 | ||
2086 | out_free: | 2195 | out_free: |
2196 | sysdev_unregister(&kvm_sysdev); | ||
2197 | out_free_3: | ||
2198 | sysdev_class_unregister(&kvm_sysdev_class); | ||
2199 | out_free_2: | ||
2087 | unregister_reboot_notifier(&kvm_reboot_notifier); | 2200 | unregister_reboot_notifier(&kvm_reboot_notifier); |
2201 | unregister_cpu_notifier(&kvm_cpu_notifier); | ||
2202 | out_free_1: | ||
2088 | on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); | 2203 | on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); |
2089 | kvm_arch_ops->hardware_unsetup(); | 2204 | kvm_arch_ops->hardware_unsetup(); |
2090 | return r; | 2205 | return r; |
@@ -2093,8 +2208,10 @@ out_free: | |||
2093 | void kvm_exit_arch(void) | 2208 | void kvm_exit_arch(void) |
2094 | { | 2209 | { |
2095 | misc_deregister(&kvm_dev); | 2210 | misc_deregister(&kvm_dev); |
2096 | 2211 | sysdev_unregister(&kvm_sysdev); | |
2212 | sysdev_class_unregister(&kvm_sysdev_class); | ||
2097 | unregister_reboot_notifier(&kvm_reboot_notifier); | 2213 | unregister_reboot_notifier(&kvm_reboot_notifier); |
2214 | unregister_cpu_notifier(&kvm_cpu_notifier); | ||
2098 | on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); | 2215 | on_each_cpu(kvm_arch_ops->hardware_disable, NULL, 0, 1); |
2099 | kvm_arch_ops->hardware_unsetup(); | 2216 | kvm_arch_ops->hardware_unsetup(); |
2100 | kvm_arch_ops = NULL; | 2217 | kvm_arch_ops = NULL; |