# HG changeset patch # User Travis Betak # Date 1173133271 21600 # Node ID 4bda617b2099aaa4147540b9a41e92c66255d070 # Parent e464aa6237ef87f4df78e3cb27fdc6d5b04a0109 [SVM] Cleanup guest writes to EFER diff -r e464aa6237ef -r 4bda617b2099 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Mon Mar 05 16:18:10 2007 -0600 +++ b/xen/arch/x86/hvm/svm/svm.c Mon Mar 05 16:21:11 2007 -0600 @@ -258,15 +258,23 @@ static inline int long_mode_do_msr_write goto gp_fault; } + /* + * update the VMCB's EFER with the intended value along with + * that crucial EFER.SVME bit =) + */ + vmcb->efer = msr_content | EFER_SVME; + #ifdef __x86_64__ - /* LME: 0 -> 1 */ - if ( (msr_content & EFER_LME) - && !svm_lme_is_set(v) ) + + /* + * Check for EFER.LME transitions from 0->1 or 1->0. Do the + * sanity checks and then make sure that both EFER.LME and + * EFER.LMA are cleared. + */ + if ( (msr_content & EFER_LME) && !svm_lme_is_set(v) ) { - /* - * setting EFER.LME is illegal if the guest currently has - * enabled or CR4.PAE is not set - */ + /* EFER.LME transition from 0 to 1 */ + if ( svm_paging_enabled(v) || !svm_cr4_pae_is_set(v) ) { @@ -274,18 +282,26 @@ static inline int long_mode_do_msr_write "in paging mode or PAE bit is not set\n"); goto gp_fault; } + + vmcb->efer &= ~(EFER_LME | EFER_LMA); + } + else if ( !(msr_content & EFER_LME) && svm_lme_is_set(v) ) + { + /* EFER.LME transistion from 1 to 0 */ - v->arch.hvm_svm.cpu_shadow_efer |= EFER_LME; - } - - /* We have already recorded that we want LME, so it will be set - * next time CR0 gets updated. So we clear that bit and continue. - */ - if ((msr_content ^ vmcb->efer) & EFER_LME) - msr_content &= ~EFER_LME; - /* No update for LME/LMA since it have no effect */ -#endif - vmcb->efer = msr_content | EFER_SVME; + if ( svm_paging_enabled(v) ) + { + gdprintk(XENLOG_WARNING, + "Trying to clear EFER.LME while paging enabled\n"); + goto gp_fault; + } + + vmcb->efer &= ~(EFER_LME | EFER_LMA); + } +#endif /* __x86_64__ */ + + /* update the guest EFER's shadow with the intended value */ + v->arch.hvm_svm.cpu_shadow_efer = msr_content; break; #ifdef __x86_64__