repository: /home/avi/kvm/linux-2.6
branch: master
commit 5fdd2a196e7975d446fedf6973cbb20708f1359c
Author: Avi Kivity <[EMAIL PROTECTED]>
Date:   Thu Sep 20 12:27:28 2007 +0200

    KVM: Fix host oops due to guest changing efer
    
    If the guest changes efer from long mode with sce disabled to legacy mode,
    then load_transition_efer() zeros vmx->host_state.guest_efer_loaded, but
    the SCE-disabled efer remains in effect. So when we return to the host,
    we disable SCE and syscalls no longer work.
    
    Fix by (a) not touching vmx->host_state.guest_efer_loaded if we're not
    setting it, and instead (b) clearing it explicitly when we switch back.
    Also switch back when the guest writes to efer so we start from a clean
    slate.
    
    Signed-off-by: Avi Kivity <[EMAIL PROTECTED]>

diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index 7f168ad..c342981 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -354,17 +354,24 @@ static void load_transition_efer(struct vcpu_vmx *vmx)
        if (guest_efer & EFER_LMA)
                ignore_bits &= ~(u64)EFER_SCE;
 #endif
-       vmx->host_state.guest_efer_loaded
-               = (guest_efer & ~ignore_bits) != (host_efer & ~ignore_bits);
-
-       if (!vmx->host_state.guest_efer_loaded)
+       if ((guest_efer & ~ignore_bits) == (host_efer & ~ignore_bits))
                return;
+
+       vmx->host_state.guest_efer_loaded = 1;
        guest_efer &= ~ignore_bits;
        guest_efer |= host_efer & ignore_bits;
        wrmsrl(MSR_EFER, guest_efer);
        vmx->vcpu.stat.efer_reload++;
 }
 
+static void reload_host_efer(struct vcpu_vmx *vmx)
+{
+       if (vmx->host_state.guest_efer_loaded) {
+               vmx->host_state.guest_efer_loaded = 0;
+               load_msrs(vmx->host_msrs + vmx->msr_offset_efer, 1);
+       }
+}
+
 static void vmx_save_host_state(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -439,8 +446,7 @@ static void vmx_load_host_state(struct vcpu_vmx *vmx)
        reload_tss();
        save_msrs(vmx->guest_msrs, vmx->save_nmsrs);
        load_msrs(vmx->host_msrs, vmx->save_nmsrs);
-       if (vmx->host_state.guest_efer_loaded)
-               load_msrs(vmx->host_msrs + vmx->msr_offset_efer, 1);
+       reload_host_efer(vmx);
 }
 
 /*
@@ -728,8 +734,10 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 
msr_index, u64 data)
 #ifdef CONFIG_X86_64
        case MSR_EFER:
                ret = kvm_set_msr_common(vcpu, msr_index, data);
-               if (vmx->host_state.loaded)
+               if (vmx->host_state.loaded) {
+                       reload_host_efer(vmx);
                        load_transition_efer(vmx);
+               }
                break;
        case MSR_FS_BASE:
                vmcs_writel(GUEST_FS_BASE, data);

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-commits mailing list
kvm-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-commits

Reply via email to