Revision | 07929f2ab2ab9c9e01d4ae79f48f2b2476b715c8 (tree) |
---|---|
Time | 2016-02-15 12:50:00 |
Author | Richard Henderson <rth@twid...> |
Commiter | Richard Henderson |
target-i386: Implement FSGSBASE
Signed-off-by: Richard Henderson <rth@twiddle.net>
@@ -358,9 +358,9 @@ static const char *cpuid_6_feature_name[] = { | ||
358 | 358 | #define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \ |
359 | 359 | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \ |
360 | 360 | CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT | \ |
361 | - CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_MPX) | |
361 | + CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_FSGSBASE) | |
362 | 362 | /* missing: |
363 | - CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2, | |
363 | + CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2, | |
364 | 364 | CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM, |
365 | 365 | CPUID_7_0_EBX_RDSEED */ |
366 | 366 | #define TCG_7_0_ECX_FEATURES 0 |
@@ -2730,6 +2730,9 @@ static void x86_cpu_reset(CPUState *s) | ||
2730 | 2730 | if (env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) { |
2731 | 2731 | cr4 |= CR4_OSFXSR_MASK | CR4_OSXSAVE_MASK; |
2732 | 2732 | } |
2733 | + if (env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_FSGSBASE) { | |
2734 | + cr4 |= CR4_FSGSBASE_MASK; | |
2735 | + } | |
2733 | 2736 | #endif |
2734 | 2737 | |
2735 | 2738 | env->xcr0 = xcr0; |
@@ -15,6 +15,7 @@ DEF_HELPER_2(idivl_EAX, void, env, tl) | ||
15 | 15 | DEF_HELPER_2(divq_EAX, void, env, tl) |
16 | 16 | DEF_HELPER_2(idivq_EAX, void, env, tl) |
17 | 17 | #endif |
18 | +DEF_HELPER_FLAGS_2(cr4_testbit, TCG_CALL_NO_WG, void, env, i32) | |
18 | 19 | |
19 | 20 | DEF_HELPER_FLAGS_2(bndck, TCG_CALL_NO_WG, void, env, i32) |
20 | 21 | DEF_HELPER_FLAGS_3(bndldx32, TCG_CALL_NO_WG, i64, env, tl, tl) |
@@ -470,3 +470,13 @@ target_ulong helper_pext(target_ulong src, target_ulong mask) | ||
470 | 470 | #include "shift_helper_template.h" |
471 | 471 | #undef SHIFT |
472 | 472 | #endif |
473 | + | |
474 | +/* Test that BIT is enabled in CR4. If not, raise an illegal opcode | |
475 | + exception. This reduces the requirements for rare CR4 bits being | |
476 | + mapped into HFLAGS. */ | |
477 | +void helper_cr4_testbit(CPUX86State *env, uint32_t bit) | |
478 | +{ | |
479 | + if (unlikely((env->cr[4] & bit) == 0)) { | |
480 | + raise_exception_ra(env, EXCP06_ILLOP, GETPC()); | |
481 | + } | |
482 | +} |
@@ -7902,6 +7902,40 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, | ||
7902 | 7902 | gen_nop_modrm(env, s, modrm); |
7903 | 7903 | break; |
7904 | 7904 | |
7905 | + case 0xc0 ... 0xc7: /* rdfsbase (f3 0f ae /0) */ | |
7906 | + case 0xc8 ... 0xc8: /* rdgsbase (f3 0f ae /1) */ | |
7907 | + case 0xd0 ... 0xd7: /* wrfsbase (f3 0f ae /2) */ | |
7908 | + case 0xd8 ... 0xd8: /* wrgsbase (f3 0f ae /3) */ | |
7909 | + if (CODE64(s) | |
7910 | + && (prefixes & PREFIX_REPZ) | |
7911 | + && !(prefixes & PREFIX_LOCK) | |
7912 | + && (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) { | |
7913 | + TCGv base, treg, src, dst; | |
7914 | + | |
7915 | + /* Preserve hflags bits by testing CR4 at runtime. */ | |
7916 | + tcg_gen_movi_i32(cpu_tmp2_i32, CR4_FSGSBASE_MASK); | |
7917 | + gen_helper_cr4_testbit(cpu_env, cpu_tmp2_i32); | |
7918 | + | |
7919 | + base = cpu_seg_base[modrm & 8 ? R_GS : R_FS]; | |
7920 | + treg = cpu_regs[(modrm & 7) | REX_B(s)]; | |
7921 | + | |
7922 | + if (modrm & 0x10) { | |
7923 | + /* wr*base */ | |
7924 | + dst = base, src = treg; | |
7925 | + } else { | |
7926 | + /* rd*base */ | |
7927 | + dst = treg, src = base; | |
7928 | + } | |
7929 | + | |
7930 | + if (s->dflag == MO_32) { | |
7931 | + tcg_gen_ext32u_tl(dst, src); | |
7932 | + } else { | |
7933 | + tcg_gen_mov_tl(dst, src); | |
7934 | + } | |
7935 | + break; | |
7936 | + } | |
7937 | + goto illegal_op; | |
7938 | + | |
7905 | 7939 | case 0xf8: /* sfence / pcommit */ |
7906 | 7940 | if (prefixes & PREFIX_DATA) { |
7907 | 7941 | /* pcommit */ |