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 /arch/x86/kvm/svm.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 'arch/x86/kvm/svm.c')
-rw-r--r-- | arch/x86/kvm/svm.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 992ab7115871..9390a31c06f4 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -27,6 +27,8 @@ | |||
27 | 27 | ||
28 | #include <asm/desc.h> | 28 | #include <asm/desc.h> |
29 | 29 | ||
30 | #define __ex(x) __kvm_handle_fault_on_reboot(x) | ||
31 | |||
30 | MODULE_AUTHOR("Qumranet"); | 32 | MODULE_AUTHOR("Qumranet"); |
31 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
32 | 34 | ||
@@ -129,17 +131,17 @@ static inline void push_irq(struct kvm_vcpu *vcpu, u8 irq) | |||
129 | 131 | ||
130 | static inline void clgi(void) | 132 | static inline void clgi(void) |
131 | { | 133 | { |
132 | asm volatile (SVM_CLGI); | 134 | asm volatile (__ex(SVM_CLGI)); |
133 | } | 135 | } |
134 | 136 | ||
135 | static inline void stgi(void) | 137 | static inline void stgi(void) |
136 | { | 138 | { |
137 | asm volatile (SVM_STGI); | 139 | asm volatile (__ex(SVM_STGI)); |
138 | } | 140 | } |
139 | 141 | ||
140 | static inline void invlpga(unsigned long addr, u32 asid) | 142 | static inline void invlpga(unsigned long addr, u32 asid) |
141 | { | 143 | { |
142 | asm volatile (SVM_INVLPGA :: "a"(addr), "c"(asid)); | 144 | asm volatile (__ex(SVM_INVLPGA) :: "a"(addr), "c"(asid)); |
143 | } | 145 | } |
144 | 146 | ||
145 | static inline unsigned long kvm_read_cr2(void) | 147 | static inline unsigned long kvm_read_cr2(void) |
@@ -1758,17 +1760,17 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
1758 | /* Enter guest mode */ | 1760 | /* Enter guest mode */ |
1759 | "push %%rax \n\t" | 1761 | "push %%rax \n\t" |
1760 | "mov %c[vmcb](%[svm]), %%rax \n\t" | 1762 | "mov %c[vmcb](%[svm]), %%rax \n\t" |
1761 | SVM_VMLOAD "\n\t" | 1763 | __ex(SVM_VMLOAD) "\n\t" |
1762 | SVM_VMRUN "\n\t" | 1764 | __ex(SVM_VMRUN) "\n\t" |
1763 | SVM_VMSAVE "\n\t" | 1765 | __ex(SVM_VMSAVE) "\n\t" |
1764 | "pop %%rax \n\t" | 1766 | "pop %%rax \n\t" |
1765 | #else | 1767 | #else |
1766 | /* Enter guest mode */ | 1768 | /* Enter guest mode */ |
1767 | "push %%eax \n\t" | 1769 | "push %%eax \n\t" |
1768 | "mov %c[vmcb](%[svm]), %%eax \n\t" | 1770 | "mov %c[vmcb](%[svm]), %%eax \n\t" |
1769 | SVM_VMLOAD "\n\t" | 1771 | __ex(SVM_VMLOAD) "\n\t" |
1770 | SVM_VMRUN "\n\t" | 1772 | __ex(SVM_VMRUN) "\n\t" |
1771 | SVM_VMSAVE "\n\t" | 1773 | __ex(SVM_VMSAVE) "\n\t" |
1772 | "pop %%eax \n\t" | 1774 | "pop %%eax \n\t" |
1773 | #endif | 1775 | #endif |
1774 | 1776 | ||