diff options
author | Avi Kivity <avi@qumranet.com> | 2008-05-13 06:23:38 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-07-20 05:41:43 -0400 |
commit | 4ecac3fd6dc2629ad76a658a486f081c44aef10e (patch) | |
tree | a078acb4c626432ac8cf887b911d912f4a316d06 /virt/kvm/kvm_main.c | |
parent | 1b7fcd3263e5f12dba43d27b64e1578bec070c28 (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/kvm/kvm_main.c')
-rw-r--r-- | virt/kvm/kvm_main.c | 15 |
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; | |||
65 | static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, | 65 | static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, |
66 | unsigned long arg); | 66 | unsigned long arg); |
67 | 67 | ||
68 | bool kvm_rebooting; | ||
69 | |||
68 | static inline int valid_vcpu(int n) | 70 | static 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 | |||
1307 | asmlinkage 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 | } | ||
1316 | EXPORT_SYMBOL_GPL(kvm_handle_fault_on_reboot); | ||
1317 | |||
1304 | static int kvm_reboot(struct notifier_block *notifier, unsigned long val, | 1318 | static 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; |