aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-i386/cpu.h2
-rw-r--r--target-i386/exec.h11
-rw-r--r--target-i386/op_helper.c38
3 files changed, 24 insertions, 27 deletions
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index d9253a14ed..76d2e7be73 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -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)
diff --git a/target-i386/exec.h b/target-i386/exec.h
index 90b82f3975..035881ec6c 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -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;
+}
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 83fa69a136..56bef6e2e5 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -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;