diff options
author | Avi Kivity <avi@redhat.com> | 2010-07-06 11:30:49 +0300 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-07-06 11:41:31 +0300 |
commit | da38f43859467a8048365b9e1cce99ccbc62b6e2 (patch) | |
tree | b36e9200ded220e1e7499dad8f64c742db451088 /arch/x86 | |
parent | 815c4163b6c8ebf8152f42b0a5fd015cfdcedc78 (diff) | |
download | op-kernel-dev-da38f43859467a8048365b9e1cce99ccbc62b6e2.zip op-kernel-dev-da38f43859467a8048365b9e1cce99ccbc62b6e2.tar.gz |
KVM: VMX: Fix host MSR_KERNEL_GS_BASE corruption
enter_lmode() and exit_lmode() modify the guest's EFER.LMA before calling
vmx_set_efer(). However, the latter function depends on the value of EFER.LMA
to determine whether MSR_KERNEL_GS_BASE needs reloading, via
vmx_load_host_state(). With EFER.LMA changing under its feet, it took the
wrong choice and corrupted userspace's %gs.
This causes 32-on-64 host userspace to fault.
Fix not touching EFER.LMA; instead ask vmx_set_efer() to change it.
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kvm/vmx.c | 7 |
1 files changed, 2 insertions, 5 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 859a01a..ee03679 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1744,18 +1744,15 @@ static void enter_lmode(struct kvm_vcpu *vcpu) (guest_tr_ar & ~AR_TYPE_MASK) | AR_TYPE_BUSY_64_TSS); } - vcpu->arch.efer |= EFER_LMA; - vmx_set_efer(vcpu, vcpu->arch.efer); + vmx_set_efer(vcpu, vcpu->arch.efer | EFER_LMA); } static void exit_lmode(struct kvm_vcpu *vcpu) { - vcpu->arch.efer &= ~EFER_LMA; - vmcs_write32(VM_ENTRY_CONTROLS, vmcs_read32(VM_ENTRY_CONTROLS) & ~VM_ENTRY_IA32E_MODE); - vmx_set_efer(vcpu, vcpu->arch.efer); + vmx_set_efer(vcpu, vcpu->arch.efer & ~EFER_LMA); } #endif |