target-i386: Implement FSGSBASE

Backports commit 07929f2ab2ab9c9e01d4ae79f48f2b2476b715c8 from qemu
This commit is contained in:
Richard Henderson 2018-02-20 14:42:19 -05:00 committed by Lioncash
parent 6ca787fb48
commit 22d4f95912
No known key found for this signature in database
GPG Key ID: 4E3C3CC1031BA9C7
4 changed files with 87 additions and 5 deletions

View File

@ -324,9 +324,9 @@ static const char *cpuid_6_feature_name[] = {
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT | \
CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_MPX)
CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_FSGSBASE)
/* missing:
CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
CPUID_7_0_EBX_RDSEED */
#define TCG_7_0_ECX_FEATURES 0
@ -2665,6 +2665,9 @@ static void x86_cpu_reset(CPUState *s)
if (env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) {
cr4 |= CR4_OSFXSR_MASK | CR4_OSXSAVE_MASK;
}
if (env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_FSGSBASE) {
cr4 |= CR4_FSGSBASE_MASK;
}
#endif
env->xcr0 = xcr0;

View File

@ -17,6 +17,7 @@ DEF_HELPER_2(idivl_EAX, void, env, tl)
DEF_HELPER_2(divq_EAX, void, env, tl)
DEF_HELPER_2(idivq_EAX, void, env, tl)
#endif
DEF_HELPER_FLAGS_2(cr4_testbit, TCG_CALL_NO_WG, void, env, i32)
DEF_HELPER_FLAGS_2(bndck, TCG_CALL_NO_WG, void, env, i32)
DEF_HELPER_FLAGS_3(bndldx32, TCG_CALL_NO_WG, i64, env, tl, tl)

View File

@ -470,3 +470,13 @@ target_ulong helper_pext(target_ulong src, target_ulong mask)
#include "shift_helper_template.h"
#undef SHIFT
#endif
/* Test that BIT is enabled in CR4. If not, raise an illegal opcode
exception. This reduces the requirements for rare CR4 bits being
mapped into HFLAGS. */
void helper_cr4_testbit(CPUX86State *env, uint32_t bit)
{
if (unlikely((env->cr[4] & bit) == 0)) {
raise_exception_ra(env, EXCP06_ILLOP, GETPC());
}
}

View File

@ -8581,6 +8581,54 @@ case 0x101:
gen_nop_modrm(env, s, modrm);
break;
case 0xc0:
case 0xc1:
case 0xc2:
case 0xc3:
case 0xc4:
case 0xc5:
case 0xc6:
case 0xc7: /* rdfsbase (f3 0f ae /0) */
case 0xc8: /* rdgsbase (f3 0f ae /1) */
case 0xd0:
case 0xd1:
case 0xd2:
case 0xd3:
case 0xd4:
case 0xd5:
case 0xd6:
case 0xd7: /* wrfsbase (f3 0f ae /2) */
case 0xd8: /* wrgsbase (f3 0f ae /3) */
if (CODE64(s)
&& (prefixes & PREFIX_REPZ)
&& !(prefixes & PREFIX_LOCK)
&& (s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_FSGSBASE)) {
TCGv base, treg, src, dst;
/* Preserve hflags bits by testing CR4 at runtime. */
tcg_gen_movi_i32(tcg_ctx, cpu_tmp2_i32, CR4_FSGSBASE_MASK);
gen_helper_cr4_testbit(tcg_ctx, cpu_env, cpu_tmp2_i32);
base = *cpu_seg_base[modrm & 8 ? R_GS : R_FS];
treg = *cpu_regs[(modrm & 7) | REX_B(s)];
if (modrm & 0x10) {
/* wr*base */
dst = base, src = treg;
} else {
/* rd*base */
dst = treg, src = base;
}
if (s->dflag == MO_32) {
tcg_gen_ext32u_tl(tcg_ctx, dst, src);
} else {
tcg_gen_mov_tl(tcg_ctx, dst, src);
}
break;
}
goto illegal_op;
case 0xf8: /* sfence / pcommit */
if (prefixes & PREFIX_DATA) {
/* pcommit */
@ -8591,9 +8639,29 @@ case 0x101:
break;
}
/* fallthru */
case 0xf9 ... 0xff: /* sfence */
case 0xe8 ... 0xef: /* lfence */
case 0xf0 ... 0xf7: /* mfence */
case 0xf9:
case 0xfa:
case 0xfb:
case 0xfc:
case 0xfd:
case 0xfe:
case 0xff: /* sfence */
case 0xe8:
case 0xe9:
case 0xea:
case 0xeb:
case 0xec:
case 0xed:
case 0xee:
case 0xef: /* lfence */
case 0xf0:
case 0xf1:
case 0xf2:
case 0xf3:
case 0xf4:
case 0xf5:
case 0xf6:
case 0xf7: /* mfence */
if (!(s->cpuid_features & CPUID_SSE2)
|| (prefixes & PREFIX_LOCK)) {
goto illegal_op;