diff -r 5ce41defa1fa xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Wed Jan 26 16:11:41 2011 +0000 +++ b/xen/arch/x86/hvm/svm/svm.c Sun Jan 30 23:38:00 2011 -0600 @@ -157,6 +157,7 @@ static int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c) { + bool_t lma = !!(v->arch.hvm_vcpu.guest_efer & EFER_LMA); struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; c->cr0 = v->arch.hvm_vcpu.guest_cr[0]; @@ -164,9 +165,20 @@ c->cr3 = v->arch.hvm_vcpu.guest_cr[3]; c->cr4 = v->arch.hvm_vcpu.guest_cr[4]; - c->sysenter_cs = v->arch.hvm_svm.guest_sysenter_cs; - c->sysenter_esp = v->arch.hvm_svm.guest_sysenter_esp; - c->sysenter_eip = v->arch.hvm_svm.guest_sysenter_eip; + /* SYSENTER MSRs aren't intercepted under 32bit mode. So the data should + * be copied from VMCB save area under 32bit mode. */ + if ( lma ) + { + c->sysenter_cs = v->arch.hvm_svm.guest_sysenter_cs; + c->sysenter_esp = v->arch.hvm_svm.guest_sysenter_esp; + c->sysenter_eip = v->arch.hvm_svm.guest_sysenter_eip; + } + else + { + c->sysenter_cs = vmcb->sysenter_cs; + c->sysenter_esp = vmcb->sysenter_esp; + c->sysenter_eip = vmcb->sysenter_eip; + } c->pending_event = 0; c->error_code = 0; @@ -185,8 +197,12 @@ { unsigned long mfn = 0; p2m_type_t p2mt; + bool_t lma; struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; struct p2m_domain *p2m = p2m_get_hostp2m(v->domain); + + /* Note: Please make sure guest_efer been restored at this point. */ + lma = !!(v->arch.hvm_vcpu.guest_efer & EFER_LMA); if ( c->pending_valid && ((c->pending_type == 1) || (c->pending_type > 6) || @@ -224,9 +240,19 @@ hvm_update_guest_cr(v, 2); hvm_update_guest_cr(v, 4); - v->arch.hvm_svm.guest_sysenter_cs = c->sysenter_cs; - v->arch.hvm_svm.guest_sysenter_esp = c->sysenter_esp; - v->arch.hvm_svm.guest_sysenter_eip = c->sysenter_eip; + /* Copy data into VMCB save area under 32bit mode */ + if ( lma ) + { + v->arch.hvm_svm.guest_sysenter_cs = c->sysenter_cs; + v->arch.hvm_svm.guest_sysenter_esp = c->sysenter_esp; + v->arch.hvm_svm.guest_sysenter_eip = c->sysenter_eip; + } + else + { + vmcb->sysenter_cs = c->sysenter_cs; + vmcb->sysenter_esp = c->sysenter_esp; + vmcb->sysenter_eip = c->sysenter_eip; + } if ( paging_mode_hap(v->domain) ) {