]>
Commit | Line | Data |
---|---|---|
d86d85d9 GKH |
1 | From c8770e7ba63bb5dd8fe5f9d251275a8fa717fb78 Mon Sep 17 00:00:00 2001 |
2 | From: Avi Kivity <avi@redhat.com> | |
3 | Date: Thu, 11 Nov 2010 12:37:26 +0200 | |
4 | Subject: KVM: VMX: Fix host userspace gsbase corruption | |
5 | ||
6 | From: Avi Kivity <avi@redhat.com> | |
7 | ||
8 | commit c8770e7ba63bb5dd8fe5f9d251275a8fa717fb78 upstream. | |
9 | ||
10 | We now use load_gs_index() to load gs safely; unfortunately this also | |
11 | changes MSR_KERNEL_GS_BASE, which we managed separately. This resulted | |
12 | in confusion and breakage running 32-bit host userspace on a 64-bit kernel. | |
13 | ||
14 | Fix by | |
15 | - saving guest MSR_KERNEL_GS_BASE before we we reload the host's gs | |
16 | - doing the host save/load unconditionally, instead of only when in guest | |
17 | long mode | |
18 | ||
19 | Things can be cleaned up further, but this is the minmal fix for now. | |
20 | ||
21 | Signed-off-by: Avi Kivity <avi@redhat.com> | |
22 | Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> | |
23 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
24 | ||
25 | --- | |
26 | arch/x86/kvm/vmx.c | 15 +++++++-------- | |
27 | 1 file changed, 7 insertions(+), 8 deletions(-) | |
28 | ||
29 | --- a/arch/x86/kvm/vmx.c | |
30 | +++ b/arch/x86/kvm/vmx.c | |
31 | @@ -828,10 +828,9 @@ static void vmx_save_host_state(struct k | |
32 | #endif | |
33 | ||
34 | #ifdef CONFIG_X86_64 | |
35 | - if (is_long_mode(&vmx->vcpu)) { | |
36 | - rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); | |
37 | + rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); | |
38 | + if (is_long_mode(&vmx->vcpu)) | |
39 | wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); | |
40 | - } | |
41 | #endif | |
42 | for (i = 0; i < vmx->save_nmsrs; ++i) | |
43 | kvm_set_shared_msr(vmx->guest_msrs[i].index, | |
44 | @@ -846,11 +845,14 @@ static void __vmx_load_host_state(struct | |
45 | ||
46 | ++vmx->vcpu.stat.host_state_reload; | |
47 | vmx->host_state.loaded = 0; | |
48 | +#ifdef CONFIG_X86_64 | |
49 | + if (is_long_mode(&vmx->vcpu)) | |
50 | + rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); | |
51 | +#endif | |
52 | if (vmx->host_state.gs_ldt_reload_needed) { | |
53 | kvm_load_ldt(vmx->host_state.ldt_sel); | |
54 | #ifdef CONFIG_X86_64 | |
55 | load_gs_index(vmx->host_state.gs_sel); | |
56 | - wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs); | |
57 | #else | |
58 | loadsegment(gs, vmx->host_state.gs_sel); | |
59 | #endif | |
60 | @@ -859,10 +861,7 @@ static void __vmx_load_host_state(struct | |
61 | loadsegment(fs, vmx->host_state.fs_sel); | |
62 | reload_tss(); | |
63 | #ifdef CONFIG_X86_64 | |
64 | - if (is_long_mode(&vmx->vcpu)) { | |
65 | - rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); | |
66 | - wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); | |
67 | - } | |
68 | + wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); | |
69 | #endif | |
70 | if (current_thread_info()->status & TS_USEDFPU) | |
71 | clts(); |