On Wed, Sep 26, 2012 at 01:18:43PM -0700, H. Peter Anvin wrote: > From: "H. Peter Anvin" <h...@linux.intel.com> > > This patch implements Supervisor Mode Execution Prevention (SMEP) and > Supervisor Mode Access Prevention (SMAP) for x86. The purpose of the > patch, obviously, is to help kernel developers debug the support for > those features. > > A fair bit of the code relates to the handling of CPUID features. The > CPUID code probably would get greatly simplified if all the feature > bit words were unified into a single vector object, but in the > interest of producing a minimal patch for SMEP/SMAP, and because I had > very limited time for this project, I followed the existing style. > > [ v2: don't change the definition of the qemu64 CPU shorthand, since > that breaks loading old snapshots. Per Anthony Liguori this can be > fixed once the CPU feature set is snapshot. > > Change the coding style slightly to conform to checkpatch.pl. ] > > Signed-off-by: H. Peter Anvin <h...@linux.intel.com> > --- > target-i386/cc_helper.c | 10 +++ > target-i386/cpu.c | 34 ++++++++--- > target-i386/cpu.h | 33 ++++++++-- > target-i386/helper.c | 150 > ++++++++++++++++++++++++++++++++++++++--------- > target-i386/helper.h | 2 + > target-i386/translate.c | 27 +++++++-- > 6 files changed, 207 insertions(+), 49 deletions(-) > > diff --git a/target-i386/cc_helper.c b/target-i386/cc_helper.c > index 07892f9..9422003 100644 > --- a/target-i386/cc_helper.c > +++ b/target-i386/cc_helper.c > @@ -353,6 +353,16 @@ void helper_sti(CPUX86State *env) > env->eflags |= IF_MASK; > } > > +void helper_clac(CPUX86State *env) > +{ > + env->eflags &= ~AC_MASK; > +} > + > +void helper_stac(CPUX86State *env) > +{ > + env->eflags |= AC_MASK; > +} > + > #if 0 > /* vm86plus instructions */ > void helper_cli_vm(CPUX86State *env) > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > index fd4fe28..f186439 100644 > --- a/target-i386/cpu.c > +++ b/target-i386/cpu.c > @@ -100,6 +100,13 @@ static const char *svm_feature_name[] = { > NULL, NULL, NULL, NULL, > }; > > +static const char *cpuid_7_0_ebx_feature_name[] = { > + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "smep", > + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, > + NULL, NULL, NULL, NULL, "smap", NULL, NULL, NULL, > + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, > +}; > + > /* collects per-function cpuid data > */ > typedef struct model_features_t { > @@ -215,14 +222,17 @@ static void add_flagname_to_bitmaps(const char > *flagname, uint32_t *features, > uint32_t *ext2_features, > uint32_t *ext3_features, > uint32_t *kvm_features, > - uint32_t *svm_features) > + uint32_t *svm_features, > + uint32_t *cpuid_7_0_ebx_features) > { > if (!lookup_feature(features, flagname, NULL, feature_name) && > !lookup_feature(ext_features, flagname, NULL, ext_feature_name) && > !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) && > !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) && > !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name) && > - !lookup_feature(svm_features, flagname, NULL, svm_feature_name)) > + !lookup_feature(svm_features, flagname, NULL, svm_feature_name) && > + !lookup_feature(cpuid_7_0_ebx_features, flagname, NULL, > + cpuid_7_0_ebx_feature_name)) > fprintf(stderr, "CPU feature %s not found\n", flagname); > } > > @@ -284,6 +294,7 @@ typedef struct x86_def_t { > #define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \ > CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A) > #define TCG_SVM_FEATURES 0 > +#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP) > > /* maintains list of cpu model definitions > */ > @@ -1091,10 +1102,12 @@ static int cpu_x86_find_by_name(x86_def_t > *x86_cpu_def, const char *cpu_model) > uint32_t plus_features = 0, plus_ext_features = 0; > uint32_t plus_ext2_features = 0, plus_ext3_features = 0; > uint32_t plus_kvm_features = 0, plus_svm_features = 0; > + uint32_t plus_7_0_ebx_features = 0; > /* Features to be removed */ > uint32_t minus_features = 0, minus_ext_features = 0; > uint32_t minus_ext2_features = 0, minus_ext3_features = 0; > uint32_t minus_kvm_features = 0, minus_svm_features = 0; > + uint32_t minus_7_0_ebx_features = 0; > uint32_t numvalue; > > for (def = x86_defs; def; def = def->next) > @@ -1121,8 +1134,8 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, > const char *cpu_model) > #endif > > add_flagname_to_bitmaps("hypervisor", &plus_features, > - &plus_ext_features, &plus_ext2_features, &plus_ext3_features, > - &plus_kvm_features, &plus_svm_features); > + &plus_ext_features, &plus_ext2_features, &plus_ext3_features, > + &plus_kvm_features, &plus_svm_features, &plus_7_0_ebx_features); > > featurestr = strtok(NULL, ","); > > @@ -1132,12 +1145,12 @@ static int cpu_x86_find_by_name(x86_def_t > *x86_cpu_def, const char *cpu_model) > add_flagname_to_bitmaps(featurestr + 1, &plus_features, > &plus_ext_features, &plus_ext2_features, > &plus_ext3_features, &plus_kvm_features, > - &plus_svm_features); > + &plus_svm_features, &plus_7_0_ebx_features); > } else if (featurestr[0] == '-') { > add_flagname_to_bitmaps(featurestr + 1, &minus_features, > &minus_ext_features, &minus_ext2_features, > &minus_ext3_features, &minus_kvm_features, > - &minus_svm_features); > + &minus_svm_features, &minus_7_0_ebx_features); > } else if ((val = strchr(featurestr, '='))) { > *val = 0; val++; > if (!strcmp(featurestr, "family")) { > @@ -1243,16 +1256,21 @@ static int cpu_x86_find_by_name(x86_def_t > *x86_cpu_def, const char *cpu_model) > x86_cpu_def->ext3_features |= plus_ext3_features; > x86_cpu_def->kvm_features |= plus_kvm_features; > x86_cpu_def->svm_features |= plus_svm_features; > + x86_cpu_def->cpuid_7_0_ebx_features |= plus_7_0_ebx_features; > x86_cpu_def->features &= ~minus_features; > x86_cpu_def->ext_features &= ~minus_ext_features; > x86_cpu_def->ext2_features &= ~minus_ext2_features; > x86_cpu_def->ext3_features &= ~minus_ext3_features; > x86_cpu_def->kvm_features &= ~minus_kvm_features; > x86_cpu_def->svm_features &= ~minus_svm_features; > + x86_cpu_def->cpuid_7_0_ebx_features &= ~minus_7_0_ebx_features; > if (check_cpuid) { > if (check_features_against_host(x86_cpu_def) && enforce_cpuid) > goto error; > } > + if (x86_cpu_def->cpuid_7_0_ebx_features && x86_cpu_def->level < 7) { > + x86_cpu_def->level = 7; > + } > g_free(s); > return 0; > > @@ -1368,7 +1386,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) > env->cpuid_kvm_features = def->kvm_features; > env->cpuid_svm_features = def->svm_features; > env->cpuid_ext4_features = def->ext4_features; > - env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features; > + env->cpuid_7_0_ebx_features = def->cpuid_7_0_ebx_features; > env->cpuid_xlevel2 = def->xlevel2; > object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000, > "tsc-frequency", &error); > @@ -1545,7 +1563,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, > uint32_t count, > /* Structured Extended Feature Flags Enumeration Leaf */ > if (count == 0) { > *eax = 0; /* Maximum ECX value for sub-leaves */ > - *ebx = env->cpuid_7_0_ebx; /* Feature flags */ > + *ebx = env->cpuid_7_0_ebx_features; /* Feature flags */ > *ecx = 0; /* Reserved */ > *edx = 0; /* Reserved */ > } else { > diff --git a/target-i386/cpu.h b/target-i386/cpu.h > index d7ea2f9..3cb9c08 100644 > --- a/target-i386/cpu.h > +++ b/target-i386/cpu.h > @@ -123,8 +123,8 @@ > > /* hidden flags - used internally by qemu to represent additional cpu > states. Only the CPL, INHIBIT_IRQ, SMM and SVMI are not > - redundant. We avoid using the IOPL_MASK, TF_MASK and VM_MASK bit > - position to ease oring with eflags. */ > + redundant. We avoid using the IOPL_MASK, TF_MASK, VM_MASK and AC_MASK > + bit positions to ease oring with eflags. */ > /* current cpl */ > #define HF_CPL_SHIFT 0 > /* true if soft mmu is being used */ > @@ -147,10 +147,12 @@ > #define HF_CS64_SHIFT 15 /* only used on x86_64: 64 bit code segment > */ > #define HF_RF_SHIFT 16 /* must be same as eflags */ > #define HF_VM_SHIFT 17 /* must be same as eflags */ > +#define HF_AC_SHIFT 18 /* must be same as eflags */ > #define HF_SMM_SHIFT 19 /* CPU in SMM mode */ > #define HF_SVME_SHIFT 20 /* SVME enabled (copy of EFER.SVME) */ > #define HF_SVMI_SHIFT 21 /* SVM intercepts are active */ > #define HF_OSFXSR_SHIFT 22 /* CR4.OSFXSR */ > +#define HF_SMAP_SHIFT 23 /* CR4.SMAP */ > > #define HF_CPL_MASK (3 << HF_CPL_SHIFT) > #define HF_SOFTMMU_MASK (1 << HF_SOFTMMU_SHIFT) > @@ -168,10 +170,12 @@ > #define HF_CS64_MASK (1 << HF_CS64_SHIFT) > #define HF_RF_MASK (1 << HF_RF_SHIFT) > #define HF_VM_MASK (1 << HF_VM_SHIFT) > +#define HF_AC_MASK (1 << HF_AC_SHIFT) > #define HF_SMM_MASK (1 << HF_SMM_SHIFT) > #define HF_SVME_MASK (1 << HF_SVME_SHIFT) > #define HF_SVMI_MASK (1 << HF_SVMI_SHIFT) > #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT) > +#define HF_SMAP_MASK (1 << HF_SMAP_SHIFT) > > /* hflags2 */ > > @@ -210,6 +214,13 @@ > #define CR4_OSFXSR_SHIFT 9 > #define CR4_OSFXSR_MASK (1 << CR4_OSFXSR_SHIFT) > #define CR4_OSXMMEXCPT_MASK (1 << 10) > +#define CR4_VMXE_MASK (1 << 13) > +#define CR4_SMXE_MASK (1 << 14) > +#define CR4_FSGSBASE_MASK (1 << 16) > +#define CR4_PCIDE_MASK (1 << 17) > +#define CR4_OSXSAVE_MASK (1 << 18) > +#define CR4_SMEP_MASK (1 << 20) > +#define CR4_SMAP_MASK (1 << 21) > > #define DR6_BD (1 << 13) > #define DR6_BS (1 << 14) > @@ -462,6 +473,9 @@ > #define CPUID_SVM_PAUSEFILTER (1 << 10) > #define CPUID_SVM_PFTHRESHOLD (1 << 12) > > +#define CPUID_7_0_EBX_SMEP (1 << 7) > +#define CPUID_7_0_EBX_SMAP (1 << 20) > + > #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */ > #define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */ > #define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */ > @@ -637,7 +651,7 @@ typedef struct { > #define CPU_NB_REGS CPU_NB_REGS32 > #endif > > -#define NB_MMU_MODES 2 > +#define NB_MMU_MODES 3 > > typedef enum TPRAccess { > TPR_ACCESS_READ, > @@ -767,7 +781,7 @@ typedef struct CPUX86State { > uint32_t cpuid_xlevel2; > uint32_t cpuid_ext4_features; > /* Flags from CPUID[EAX=7,ECX=0].EBX */ > - uint32_t cpuid_7_0_ebx; > + uint32_t cpuid_7_0_ebx_features; > > /* MTRRs */ > uint64_t mtrr_fixed[11]; > @@ -1006,10 +1020,15 @@ static inline CPUX86State *cpu_init(const char > *cpu_model) > /* MMU modes definitions */ > #define MMU_MODE0_SUFFIX _kernel > #define MMU_MODE1_SUFFIX _user > -#define MMU_USER_IDX 1 > +#define MMU_MODE2_SUFFIX _ksmap /* Kernel with SMAP override */ > +#define MMU_KERNEL_IDX 0 > +#define MMU_USER_IDX 1 > +#define MMU_KSMAP_IDX 2 > static inline int cpu_mmu_index (CPUX86State *env) > { > - return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0; > + return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX : > + ((env->hflags & HF_SMAP_MASK) && (env->eflags & AC_MASK)) > + ? MMU_KSMAP_IDX : MMU_KERNEL_IDX; > } > > #undef EAX > @@ -1095,7 +1114,7 @@ static inline void cpu_get_tb_cpu_state(CPUX86State > *env, target_ulong *pc, > *cs_base = env->segs[R_CS].base; > *pc = *cs_base + env->eip; > *flags = env->hflags | > - (env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK)); > + (env->eflags & (IOPL_MASK | TF_MASK | RF_MASK | VM_MASK | AC_MASK)); > } > > void do_cpu_init(X86CPU *cpu); > diff --git a/target-i386/helper.c b/target-i386/helper.c > index 8a5da3d..c635667 100644 > --- a/target-i386/helper.c > +++ b/target-i386/helper.c > @@ -443,17 +443,27 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t > new_cr4) > #if defined(DEBUG_MMU) > printf("CR4 update: CR4=%08x\n", (uint32_t)env->cr[4]); > #endif > - if ((new_cr4 & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK)) != > - (env->cr[4] & (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK))) { > + if ((new_cr4 ^ env->cr[4]) & > + (CR4_PGE_MASK | CR4_PAE_MASK | CR4_PSE_MASK | > + CR4_SMEP_MASK | CR4_SMAP_MASK)) { > tlb_flush(env, 1); > } > /* SSE handling */ > - if (!(env->cpuid_features & CPUID_SSE)) > + if (!(env->cpuid_features & CPUID_SSE)) { > new_cr4 &= ~CR4_OSFXSR_MASK; > - if (new_cr4 & CR4_OSFXSR_MASK) > + } > + env->hflags &= ~HF_OSFXSR_MASK; > + if (new_cr4 & CR4_OSFXSR_MASK) { > env->hflags |= HF_OSFXSR_MASK; > - else > - env->hflags &= ~HF_OSFXSR_MASK; > + } > + > + if (!(env->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP)) { > + new_cr4 &= ~CR4_SMAP_MASK; > + } > + env->hflags &= ~HF_SMAP_MASK; > + if (new_cr4 & CR4_SMAP_MASK) { > + env->hflags |= HF_SMAP_MASK; > + } > > env->cr[4] = new_cr4; > } > @@ -591,17 +601,38 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, > target_ulong addr, > /* 2 MB page */ > page_size = 2048 * 1024; > ptep ^= PG_NX_MASK; > - if ((ptep & PG_NX_MASK) && is_write1 == 2) > + if ((ptep & PG_NX_MASK) && is_write1 == 2) { > goto do_fault_protect; > - if (is_user) { > - if (!(ptep & PG_USER_MASK)) > + } > + switch (mmu_idx) { > + case MMU_USER_IDX: > + if (!(ptep & PG_USER_MASK)) { > goto do_fault_protect; > - if (is_write && !(ptep & PG_RW_MASK)) > + } > + if (is_write && !(ptep & PG_RW_MASK)) { > goto do_fault_protect; > - } else { > + } > + break; > + > + case MMU_KERNEL_IDX: > + if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && > + (ptep & PG_USER_MASK)) { > + goto do_fault_protect; > + } > + /* fall through */ > + case MMU_KSMAP_IDX: > + if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) && > + (ptep & PG_USER_MASK)) { > + goto do_fault_protect; > + } > if ((env->cr[0] & CR0_WP_MASK) && > - is_write && !(ptep & PG_RW_MASK)) > + is_write && !(ptep & PG_RW_MASK)) { > goto do_fault_protect; > + } > + break; > + > + default: /* cannot happen */ > + break; > } > is_dirty = is_write && !(pde & PG_DIRTY_MASK); > if (!(pde & PG_ACCESSED_MASK) || is_dirty) { > @@ -635,15 +666,35 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, > target_ulong addr, > ptep ^= PG_NX_MASK; > if ((ptep & PG_NX_MASK) && is_write1 == 2) > goto do_fault_protect; > - if (is_user) { > - if (!(ptep & PG_USER_MASK)) > + switch (mmu_idx) { > + case MMU_USER_IDX: > + if (!(ptep & PG_USER_MASK)) { > goto do_fault_protect; > - if (is_write && !(ptep & PG_RW_MASK)) > + } > + if (is_write && !(ptep & PG_RW_MASK)) { > goto do_fault_protect; > - } else { > + } > + break; > + > + case MMU_KERNEL_IDX: > + if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && > + (ptep & PG_USER_MASK)) { > + goto do_fault_protect; > + } > + /* fall through */ > + case MMU_KSMAP_IDX: > + if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) && > + (ptep & PG_USER_MASK)) { > + goto do_fault_protect; > + } > if ((env->cr[0] & CR0_WP_MASK) && > - is_write && !(ptep & PG_RW_MASK)) > + is_write && !(ptep & PG_RW_MASK)) { > goto do_fault_protect; > + } > + break; > + > + default: /* cannot happen */ > + break; > } > is_dirty = is_write && !(pte & PG_DIRTY_MASK); > if (!(pte & PG_ACCESSED_MASK) || is_dirty) { > @@ -670,15 +721,35 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, > target_ulong addr, > /* if PSE bit is set, then we use a 4MB page */ > if ((pde & PG_PSE_MASK) && (env->cr[4] & CR4_PSE_MASK)) { > page_size = 4096 * 1024; > - if (is_user) { > - if (!(pde & PG_USER_MASK)) > + switch (mmu_idx) { > + case MMU_USER_IDX: > + if (!(pde & PG_USER_MASK)) { > goto do_fault_protect; > - if (is_write && !(pde & PG_RW_MASK)) > + } > + if (is_write && !(pde & PG_RW_MASK)) { > goto do_fault_protect; > - } else { > + } > + break; > + > + case MMU_KERNEL_IDX: > + if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && > + (pde & PG_USER_MASK)) { > + goto do_fault_protect; > + } > + /* fall through */ > + case MMU_KSMAP_IDX: > + if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) && > + (pde & PG_USER_MASK)) { > + goto do_fault_protect; > + } > if ((env->cr[0] & CR0_WP_MASK) && > - is_write && !(pde & PG_RW_MASK)) > + is_write && !(pde & PG_RW_MASK)) { > goto do_fault_protect; > + } > + break; > + > + default: /* cannot happen */ > + break; > } > is_dirty = is_write && !(pde & PG_DIRTY_MASK); > if (!(pde & PG_ACCESSED_MASK) || is_dirty) { > @@ -707,15 +778,35 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, > target_ulong addr, > } > /* combine pde and pte user and rw protections */ > ptep = pte & pde; > - if (is_user) { > - if (!(ptep & PG_USER_MASK)) > + switch (mmu_idx) { > + case MMU_USER_IDX: > + if (!(ptep & PG_USER_MASK)) { > goto do_fault_protect; > - if (is_write && !(ptep & PG_RW_MASK)) > + } > + if (is_write && !(ptep & PG_RW_MASK)) { > goto do_fault_protect; > - } else { > + } > + break; > + > + case MMU_KERNEL_IDX: > + if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && > + (ptep & PG_USER_MASK)) { > + goto do_fault_protect; > + } > + /* fall through */ > + case MMU_KSMAP_IDX: > + if (is_write1 == 2 && (env->cr[4] & CR4_SMEP_MASK) && > + (ptep & PG_USER_MASK)) { > + goto do_fault_protect; > + } > if ((env->cr[0] & CR0_WP_MASK) && > - is_write && !(ptep & PG_RW_MASK)) > + is_write && !(ptep & PG_RW_MASK)) { > goto do_fault_protect; > + } > + break; > + > + default: /* cannot happen */ > + break; > } > is_dirty = is_write && !(pte & PG_DIRTY_MASK); > if (!(pte & PG_ACCESSED_MASK) || is_dirty) { > @@ -762,8 +853,9 @@ int cpu_x86_handle_mmu_fault(CPUX86State *env, > target_ulong addr, > if (is_user) > error_code |= PG_ERROR_U_MASK; > if (is_write1 == 2 && > - (env->efer & MSR_EFER_NXE) && > - (env->cr[4] & CR4_PAE_MASK)) > + (((env->efer & MSR_EFER_NXE) && > + (env->cr[4] & CR4_PAE_MASK)) || > + (env->cr[4] & CR4_SMEP_MASK))) > error_code |= PG_ERROR_I_D_MASK; > if (env->intercept_exceptions & (1 << EXCP0E_PAGE)) { > /* cr2 is not modified in case of exceptions */ > diff --git a/target-i386/helper.h b/target-i386/helper.h > index ab6af63..93850ce 100644 > --- a/target-i386/helper.h > +++ b/target-i386/helper.h > @@ -67,6 +67,8 @@ DEF_HELPER_3(raise_interrupt, void, env, int, int) > DEF_HELPER_2(raise_exception, void, env, int) > DEF_HELPER_1(cli, void, env) > DEF_HELPER_1(sti, void, env) > +DEF_HELPER_1(clac, void, env) > +DEF_HELPER_1(stac, void, env) > DEF_HELPER_1(set_inhibit_irq, void, env) > DEF_HELPER_1(reset_inhibit_irq, void, env) > DEF_HELPER_3(boundw, void, env, tl, int) > diff --git a/target-i386/translate.c b/target-i386/translate.c > index eb0cabc..b33d20a 100644 > --- a/target-i386/translate.c > +++ b/target-i386/translate.c > @@ -107,6 +107,7 @@ typedef struct DisasContext { > int cpuid_ext_features; > int cpuid_ext2_features; > int cpuid_ext3_features; > + int cpuid_7_0_ebx_features; > } DisasContext; > > static void gen_eob(DisasContext *s); > @@ -6555,7 +6556,7 @@ static target_ulong disas_insn(DisasContext *s, > target_ulong pc_start) > } > gen_pop_update(s); > s->cc_op = CC_OP_EFLAGS; > - /* abort translation because TF flag may change */ > + /* abort translation because TF/AC flag may change */ > gen_jmp_im(s->pc - s->cs_base); > gen_eob(s); > } > @@ -7205,6 +7206,24 @@ static target_ulong disas_insn(DisasContext *s, > target_ulong pc_start) > gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - > pc_start)); > gen_eob(s); > break; > + case 2: /* clac */ > + if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) || > + s->cpl != 0) { > + goto illegal_op; > + } > + gen_helper_clac(cpu_env); > + gen_jmp_im(s->pc - s->cs_base); > + gen_eob(s); > + break; > + case 3: /* stac */ > + if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_SMAP) || > + s->cpl != 0) { > + goto illegal_op; > + } > + gen_helper_stac(cpu_env); > + gen_jmp_im(s->pc - s->cs_base); > + gen_eob(s); > + break; > default: > goto illegal_op; > } > @@ -7900,15 +7919,13 @@ static inline void > gen_intermediate_code_internal(CPUX86State *env, > /* select memory access functions */ > dc->mem_index = 0; > if (flags & HF_SOFTMMU_MASK) { > - if (dc->cpl == 3) > - dc->mem_index = 2 * 4; > - else > - dc->mem_index = 1 * 4; > + dc->mem_index = (cpu_mmu_index(env) + 1) << 2; > } > dc->cpuid_features = env->cpuid_features; > dc->cpuid_ext_features = env->cpuid_ext_features; > dc->cpuid_ext2_features = env->cpuid_ext2_features; > dc->cpuid_ext3_features = env->cpuid_ext3_features; > + dc->cpuid_7_0_ebx_features = env->cpuid_7_0_ebx_features; > #ifdef TARGET_X86_64 > dc->lma = (flags >> HF_LMA_SHIFT) & 1; > dc->code64 = (flags >> HF_CS64_SHIFT) & 1;
I haven't tried it, but it looks fine to me. Reviewed-by: Aurelien Jarno <aurel...@aurel32.net> -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurel...@aurel32.net http://www.aurel32.net