Commit 5efc27bbb695017a7386cb9acef247b9dd29f2b6
1 parent
f2289cb6
EFER loading fixes, including SVME bit
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4659 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
24 additions
and
27 deletions
target-i386/cpu.h
| @@ -148,7 +148,7 @@ | @@ -148,7 +148,7 @@ | ||
| 148 | #define HF_GIF_SHIFT 20 /* if set CPU takes interrupts */ | 148 | #define HF_GIF_SHIFT 20 /* if set CPU takes interrupts */ |
| 149 | #define HF_HIF_SHIFT 21 /* shadow copy of IF_MASK when in SVM */ | 149 | #define HF_HIF_SHIFT 21 /* shadow copy of IF_MASK when in SVM */ |
| 150 | #define HF_NMI_SHIFT 22 /* CPU serving NMI */ | 150 | #define HF_NMI_SHIFT 22 /* CPU serving NMI */ |
| 151 | -#define HF_SVME_SHIFT 23 /* SVME enabled (copy of EFER.SVME */ | 151 | +#define HF_SVME_SHIFT 23 /* SVME enabled (copy of EFER.SVME) */ |
| 152 | #define HF_SVMI_SHIFT 24 /* SVM intercepts are active */ | 152 | #define HF_SVMI_SHIFT 24 /* SVM intercepts are active */ |
| 153 | 153 | ||
| 154 | #define HF_CPL_MASK (3 << HF_CPL_SHIFT) | 154 | #define HF_CPL_MASK (3 << HF_CPL_SHIFT) |
target-i386/exec.h
| @@ -397,3 +397,14 @@ static inline int cpu_halted(CPUState *env) { | @@ -397,3 +397,14 @@ static inline int cpu_halted(CPUState *env) { | ||
| 397 | return EXCP_HALTED; | 397 | return EXCP_HALTED; |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | +/* load efer and update the corresponding hflags. XXX: do consistency | ||
| 401 | + checks with cpuid bits ? */ | ||
| 402 | +static inline void cpu_load_efer(CPUState *env, uint64_t val) | ||
| 403 | +{ | ||
| 404 | + env->efer = val; | ||
| 405 | + env->hflags &= ~(HF_LMA_MASK | HF_SVME_MASK); | ||
| 406 | + if (env->efer & MSR_EFER_LMA) | ||
| 407 | + env->hflags |= HF_LMA_MASK; | ||
| 408 | + if (env->efer & MSR_EFER_SVME) | ||
| 409 | + env->hflags |= HF_SVME_MASK; | ||
| 410 | +} |
target-i386/op_helper.c
| @@ -1435,8 +1435,7 @@ void do_smm_enter(void) | @@ -1435,8 +1435,7 @@ void do_smm_enter(void) | ||
| 1435 | /* init SMM cpu state */ | 1435 | /* init SMM cpu state */ |
| 1436 | 1436 | ||
| 1437 | #ifdef TARGET_X86_64 | 1437 | #ifdef TARGET_X86_64 |
| 1438 | - env->efer = 0; | ||
| 1439 | - env->hflags &= ~HF_LMA_MASK; | 1438 | + cpu_load_efer(env, 0); |
| 1440 | #endif | 1439 | #endif |
| 1441 | load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); | 1440 | load_eflags(0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); |
| 1442 | env->eip = 0x00008000; | 1441 | env->eip = 0x00008000; |
| @@ -1463,11 +1462,7 @@ void helper_rsm(void) | @@ -1463,11 +1462,7 @@ void helper_rsm(void) | ||
| 1463 | 1462 | ||
| 1464 | sm_state = env->smbase + 0x8000; | 1463 | sm_state = env->smbase + 0x8000; |
| 1465 | #ifdef TARGET_X86_64 | 1464 | #ifdef TARGET_X86_64 |
| 1466 | - env->efer = ldq_phys(sm_state + 0x7ed0); | ||
| 1467 | - if (env->efer & MSR_EFER_LMA) | ||
| 1468 | - env->hflags |= HF_LMA_MASK; | ||
| 1469 | - else | ||
| 1470 | - env->hflags &= ~HF_LMA_MASK; | 1465 | + cpu_load_efer(env, ldq_phys(sm_state + 0x7ed0)); |
| 1471 | 1466 | ||
| 1472 | for(i = 0; i < 6; i++) { | 1467 | for(i = 0; i < 6; i++) { |
| 1473 | offset = 0x7e00 + i * 16; | 1468 | offset = 0x7e00 + i * 16; |
| @@ -3069,8 +3064,10 @@ void helper_wrmsr(void) | @@ -3069,8 +3064,10 @@ void helper_wrmsr(void) | ||
| 3069 | update_mask |= MSR_EFER_FFXSR; | 3064 | update_mask |= MSR_EFER_FFXSR; |
| 3070 | if (env->cpuid_ext2_features & CPUID_EXT2_NX) | 3065 | if (env->cpuid_ext2_features & CPUID_EXT2_NX) |
| 3071 | update_mask |= MSR_EFER_NXE; | 3066 | update_mask |= MSR_EFER_NXE; |
| 3072 | - env->efer = (env->efer & ~update_mask) | | ||
| 3073 | - (val & update_mask); | 3067 | + if (env->cpuid_ext3_features & CPUID_EXT3_SVM) |
| 3068 | + update_mask |= MSR_EFER_SVME; | ||
| 3069 | + cpu_load_efer(env, (env->efer & ~update_mask) | | ||
| 3070 | + (val & update_mask)); | ||
| 3074 | } | 3071 | } |
| 3075 | break; | 3072 | break; |
| 3076 | case MSR_STAR: | 3073 | case MSR_STAR: |
| @@ -4873,10 +4870,8 @@ void helper_vmrun(void) | @@ -4873,10 +4870,8 @@ void helper_vmrun(void) | ||
| 4873 | } | 4870 | } |
| 4874 | 4871 | ||
| 4875 | #ifdef TARGET_X86_64 | 4872 | #ifdef TARGET_X86_64 |
| 4876 | - env->efer = ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer)); | ||
| 4877 | - env->hflags &= ~HF_LMA_MASK; | ||
| 4878 | - if (env->efer & MSR_EFER_LMA) | ||
| 4879 | - env->hflags |= HF_LMA_MASK; | 4873 | + cpu_load_efer(env, |
| 4874 | + ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.efer))); | ||
| 4880 | #endif | 4875 | #endif |
| 4881 | env->eflags = 0; | 4876 | env->eflags = 0; |
| 4882 | load_eflags(ldq_phys(env->vm_vmcb + offsetof(struct vmcb, save.rflags)), | 4877 | 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) | @@ -5224,20 +5219,11 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1) | ||
| 5224 | env->cr[8] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8)); | 5219 | env->cr[8] = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.cr8)); |
| 5225 | cpu_set_apic_tpr(env, env->cr[8]); | 5220 | cpu_set_apic_tpr(env, env->cr[8]); |
| 5226 | } | 5221 | } |
| 5227 | - /* we need to set the efer after the crs so the hidden flags get set properly */ | 5222 | + /* we need to set the efer after the crs so the hidden flags get |
| 5223 | + set properly */ | ||
| 5228 | #ifdef TARGET_X86_64 | 5224 | #ifdef TARGET_X86_64 |
| 5229 | - env->efer = ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer)); | ||
| 5230 | - env->hflags &= ~HF_LMA_MASK; | ||
| 5231 | - if (env->efer & MSR_EFER_LMA) | ||
| 5232 | - env->hflags |= HF_LMA_MASK; | ||
| 5233 | - /* XXX: should also emulate the VM_CR MSR */ | ||
| 5234 | - env->hflags &= ~HF_SVME_MASK; | ||
| 5235 | - if (env->cpuid_ext3_features & CPUID_EXT3_SVM) { | ||
| 5236 | - if (env->efer & MSR_EFER_SVME) | ||
| 5237 | - env->hflags |= HF_SVME_MASK; | ||
| 5238 | - } else { | ||
| 5239 | - env->efer &= ~MSR_EFER_SVME; | ||
| 5240 | - } | 5225 | + cpu_load_efer(env, |
| 5226 | + ldq_phys(env->vm_hsave + offsetof(struct vmcb, save.efer))); | ||
| 5241 | #endif | 5227 | #endif |
| 5242 | 5228 | ||
| 5243 | env->eflags = 0; | 5229 | env->eflags = 0; |