EFER loading fixes, including SVME bit

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4659 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2008-06-04 13:35:58 +00:00
parent f2289cb692
commit 5efc27bbb6
3 changed files with 24 additions and 27 deletions

View File

@ -148,7 +148,7 @@
#define HF_GIF_SHIFT 20 /* if set CPU takes interrupts */
#define HF_HIF_SHIFT 21 /* shadow copy of IF_MASK when in SVM */
#define HF_NMI_SHIFT 22 /* CPU serving NMI */
#define HF_SVME_SHIFT 23 /* SVME enabled (copy of EFER.SVME */
#define HF_SVME_SHIFT 23 /* SVME enabled (copy of EFER.SVME) */
#define HF_SVMI_SHIFT 24 /* SVM intercepts are active */
#define HF_CPL_MASK (3 << HF_CPL_SHIFT)

View File

@ -397,3 +397,14 @@ static inline int cpu_halted(CPUState *env) {
return EXCP_HALTED;
}
/* load efer and update the corresponding hflags. XXX: do consistency
checks with cpuid bits ? */
static inline void cpu_load_efer(CPUState *env, uint64_t val)
{
env->efer = val;
env->hflags &= ~(HF_LMA_MASK | HF_SVME_MASK);
if (env->efer & MSR_EFER_LMA)
env->hflags |= HF_LMA_MASK;
if (env->efer & MSR_EFER_SVME)
env->hflags |= HF_SVME_MASK;
}

View File

@ -1435,8 +1435,7 @@ void do_smm_enter(void)
/* init SMM cpu state */
#ifdef TARGET_X86_64
env->efer = 0;
env->hflags &= ~HF_LMA_MASK;
cpu_load_efer(env, 0);
#endif
load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK));
env->eip = 0x00008000;
@ -1463,11 +1462,7 @@ void helper_rsm(void)
sm_state = env->smbase + 0x8000;
#ifdef TARGET_X86_64
env->efer = ldq_phys(sm_state + 0x7ed0);
if (env->efer & MSR_EFER_LMA)
env->hflags |= HF_LMA_MASK;
else
env->hflags &= ~HF_LMA_MASK;
cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0));
for(i = 0; i < 6; i++) {
offset = 0x7e00 + i * 16;
@ -3069,8 +3064,10 @@ void helper_wrmsr(void)
update_mask |= MSR_EFER_FFXSR;
if (env->cpuid_ext2_features & CPUID_EXT2_NX)
update_mask |= MSR_EFER_NXE;
env->efer = (env->efer & ~update_mask) |
(val & update_mask);
if (env->cpuid_ext3_features & CPUID_EXT3_SVM)
update_mask |= MSR_EFER_SVME;
cpu_load_efer(env, (env->efer & ~update_mask) |
(val & update_mask));
}
break;
case MSR_STAR:
@ -4873,10 +4870,8 @@ void helper_vmrun(void)
}
#ifdef TARGET_X86_64
env->efer = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer));
env->hflags &= ~HF_LMA_MASK;
if (env->efer & MSR_EFER_LMA)
env->hflags |= HF_LMA_MASK;
cpu_load_efer(env,
ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)));
#endif
env->eflags = 0;
load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)),
@ -5224,20 +5219,11 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
env->cr[8] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8));
cpu_set_apic_tpr(env, env->cr[8]);
}
/* we need to set the efer after the crs so the hidden flags get set properly */
/* we need to set the efer after the crs so the hidden flags get
set properly */
#ifdef TARGET_X86_64
env->efer = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer));
env->hflags &= ~HF_LMA_MASK;
if (env->efer & MSR_EFER_LMA)
env->hflags |= HF_LMA_MASK;
/* XXX: should also emulate the VM_CR MSR */
env->hflags &= ~HF_SVME_MASK;
if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
if (env->efer & MSR_EFER_SVME)
env->hflags |= HF_SVME_MASK;
} else {
env->efer &= ~MSR_EFER_SVME;
}
cpu_load_efer(env,
ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer)));
#endif
env->eflags = 0;