aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2008-05-13 06:23:38 -0400
committerAvi Kivity <avi@qumranet.com>2008-07-20 05:41:43 -0400
commit4ecac3fd6dc2629ad76a658a486f081c44aef10e (patch)
treea078acb4c626432ac8cf887b911d912f4a316d06 /virt
parent1b7fcd3263e5f12dba43d27b64e1578bec070c28 (diff)
KVM: Handle virtualization instruction #UD faults during reboot
KVM turns off hardware virtualization extensions during reboot, in order to disassociate the memory used by the virtualization extensions from the processor, and in order to have the system in a consistent state. Unfortunately virtual machines may still be running while this goes on, and once virtualization extensions are turned off, any virtulization instruction will #UD on execution. Fix by adding an exception handler to virtualization instructions; if we get an exception during reboot, we simply spin waiting for the reset to complete. If it's a true exception, BUG() so we can have our stack trace. Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/kvm_main.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index f9dd20606c40..e4bf88a9ee4e 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -65,6 +65,8 @@ struct dentry *kvm_debugfs_dir;
65static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, 65static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
66 unsigned long arg); 66 unsigned long arg);
67 67
68bool kvm_rebooting;
69
68static inline int valid_vcpu(int n) 70static inline int valid_vcpu(int n)
69{ 71{
70 return likely(n >= 0 && n < KVM_MAX_VCPUS); 72 return likely(n >= 0 && n < KVM_MAX_VCPUS);
@@ -1301,6 +1303,18 @@ static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val,
1301 return NOTIFY_OK; 1303 return NOTIFY_OK;
1302} 1304}
1303 1305
1306
1307asmlinkage void kvm_handle_fault_on_reboot(void)
1308{
1309 if (kvm_rebooting)
1310 /* spin while reset goes on */
1311 while (true)
1312 ;
1313 /* Fault while not rebooting. We want the trace. */
1314 BUG();
1315}
1316EXPORT_SYMBOL_GPL(kvm_handle_fault_on_reboot);
1317
1304static int kvm_reboot(struct notifier_block *notifier, unsigned long val, 1318static int kvm_reboot(struct notifier_block *notifier, unsigned long val,
1305 void *v) 1319 void *v)
1306{ 1320{
@@ -1310,6 +1324,7 @@ static int kvm_reboot(struct notifier_block *notifier, unsigned long val,
1310 * in vmx root mode. 1324 * in vmx root mode.
1311 */ 1325 */
1312 printk(KERN_INFO "kvm: exiting hardware virtualization\n"); 1326 printk(KERN_INFO "kvm: exiting hardware virtualization\n");
1327 kvm_rebooting = true;
1313 on_each_cpu(hardware_disable, NULL, 1); 1328 on_each_cpu(hardware_disable, NULL, 1);
1314 } 1329 }
1315 return NOTIFY_OK; 1330 return NOTIFY_OK;