mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-11 06:25:30 +00:00
target-i386: fix confusion in xcr0 bit position vs. mask
The xsave and xrstor helpers are accessing the x86_ext_save_areas array using a bit mask instead of a bit position. Provide two sets of XSTATE_* definitions and use XSTATE_*_BIT when a bit position is requested. Backports commit cfc3b074de4b4ccee2540edbf8cfdb026dc19943 from qemu
This commit is contained in:
parent
26951bf754
commit
abb0408274
|
@ -2418,7 +2418,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||||
*ecx = MAX(*ecx, esa->offset + esa->size);
|
*ecx = MAX(*ecx, esa->offset + esa->size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*eax |= ena_mask & (XSTATE_FP | XSTATE_SSE);
|
*eax |= ena_mask & (XSTATE_FP_MASK | XSTATE_SSE_MASK);
|
||||||
*ebx = *ecx;
|
*ebx = *ecx;
|
||||||
} else if (count == 1) {
|
} else if (count == 1) {
|
||||||
*eax = env->features[FEAT_XSAVE];
|
*eax = env->features[FEAT_XSAVE];
|
||||||
|
@ -2652,15 +2652,15 @@ static void x86_cpu_reset(CPUState *s)
|
||||||
cpu_watchpoint_remove_all(s, BP_CPU);
|
cpu_watchpoint_remove_all(s, BP_CPU);
|
||||||
|
|
||||||
cr4 = 0;
|
cr4 = 0;
|
||||||
xcr0 = XSTATE_FP;
|
xcr0 = XSTATE_FP_MASK;
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
/* Enable all the features for user-mode. */
|
/* Enable all the features for user-mode. */
|
||||||
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
|
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
|
||||||
xcr0 |= XSTATE_SSE;
|
xcr0 |= XSTATE_SSE_MASK;
|
||||||
}
|
}
|
||||||
if (env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_MPX) {
|
if (env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_MPX) {
|
||||||
xcr0 |= XSTATE_BNDREGS | XSTATE_BNDCSR;
|
xcr0 |= XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK;
|
||||||
}
|
}
|
||||||
if (env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) {
|
if (env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) {
|
||||||
cr4 |= CR4_OSFXSR_MASK | CR4_OSXSAVE_MASK;
|
cr4 |= CR4_OSFXSR_MASK | CR4_OSXSAVE_MASK;
|
||||||
|
|
|
@ -412,15 +412,15 @@
|
||||||
#define XSTATE_Hi16_ZMM_BIT 7
|
#define XSTATE_Hi16_ZMM_BIT 7
|
||||||
#define XSTATE_PKRU_BIT 9
|
#define XSTATE_PKRU_BIT 9
|
||||||
|
|
||||||
#define XSTATE_FP (1ULL << 0)
|
#define XSTATE_FP_MASK (1ULL << XSTATE_FP_BIT)
|
||||||
#define XSTATE_SSE (1ULL << 1)
|
#define XSTATE_SSE_MASK (1ULL << XSTATE_SSE_BIT)
|
||||||
#define XSTATE_YMM (1ULL << 2)
|
#define XSTATE_YMM_MASK (1ULL << XSTATE_YMM_BIT)
|
||||||
#define XSTATE_BNDREGS (1ULL << 3)
|
#define XSTATE_BNDREGS_MASK (1ULL << XSTATE_BNDREGS_BIT)
|
||||||
#define XSTATE_BNDCSR (1ULL << 4)
|
#define XSTATE_BNDCSR_MASK (1ULL << XSTATE_BNDCSR_BIT)
|
||||||
#define XSTATE_OPMASK (1ULL << 5)
|
#define XSTATE_OPMASK_MASK (1ULL << XSTATE_OPMASK_BIT)
|
||||||
#define XSTATE_ZMM_Hi256 (1ULL << 6)
|
#define XSTATE_ZMM_Hi256_MASK (1ULL << XSTATE_ZMM_Hi256_BIT)
|
||||||
#define XSTATE_Hi16_ZMM (1ULL << 7)
|
#define XSTATE_Hi16_ZMM_MASK (1ULL << XSTATE_Hi16_ZMM_BIT)
|
||||||
#define XSTATE_PKRU (1ULL << 9)
|
#define XSTATE_PKRU_MASK (1ULL << XSTATE_PKRU_BIT)
|
||||||
|
|
||||||
|
|
||||||
/* CPUID feature words */
|
/* CPUID feature words */
|
||||||
|
|
|
@ -1244,7 +1244,7 @@ static uint64_t get_xinuse(CPUX86State *env)
|
||||||
indicate in use. That said, the state of BNDREGS is important
|
indicate in use. That said, the state of BNDREGS is important
|
||||||
enough to track in HFLAGS, so we might as well use that here. */
|
enough to track in HFLAGS, so we might as well use that here. */
|
||||||
if ((env->hflags & HF_MPX_IU_MASK) == 0) {
|
if ((env->hflags & HF_MPX_IU_MASK) == 0) {
|
||||||
inuse &= ~XSTATE_BNDREGS;
|
inuse &= ~XSTATE_BNDREGS_MASK;
|
||||||
}
|
}
|
||||||
return inuse;
|
return inuse;
|
||||||
}
|
}
|
||||||
|
@ -1268,22 +1268,22 @@ static void do_xsave(CPUX86State *env, target_ulong ptr, uint64_t rfbm,
|
||||||
rfbm &= env->xcr0;
|
rfbm &= env->xcr0;
|
||||||
opt &= rfbm;
|
opt &= rfbm;
|
||||||
|
|
||||||
if (opt & XSTATE_FP) {
|
if (opt & XSTATE_FP_MASK) {
|
||||||
do_xsave_fpu(env, ptr, ra);
|
do_xsave_fpu(env, ptr, ra);
|
||||||
}
|
}
|
||||||
if (rfbm & XSTATE_SSE) {
|
if (rfbm & XSTATE_SSE_MASK) {
|
||||||
/* Note that saving MXCSR is not suppressed by XSAVEOPT. */
|
/* Note that saving MXCSR is not suppressed by XSAVEOPT. */
|
||||||
do_xsave_mxcsr(env, ptr, ra);
|
do_xsave_mxcsr(env, ptr, ra);
|
||||||
}
|
}
|
||||||
if (opt & XSTATE_SSE) {
|
if (opt & XSTATE_SSE_MASK) {
|
||||||
do_xsave_sse(env, ptr, ra);
|
do_xsave_sse(env, ptr, ra);
|
||||||
}
|
}
|
||||||
if (opt & XSTATE_BNDREGS) {
|
if (opt & XSTATE_BNDREGS_MASK) {
|
||||||
target_ulong off = x86_ext_save_areas[XSTATE_BNDREGS].offset;
|
target_ulong off = x86_ext_save_areas[XSTATE_BNDREGS_BIT].offset;
|
||||||
do_xsave_bndregs(env, ptr + off, ra);
|
do_xsave_bndregs(env, ptr + off, ra);
|
||||||
}
|
}
|
||||||
if (opt & XSTATE_BNDCSR) {
|
if (opt & XSTATE_BNDCSR_MASK) {
|
||||||
target_ulong off = x86_ext_save_areas[XSTATE_BNDCSR].offset;
|
target_ulong off = x86_ext_save_areas[XSTATE_BNDCSR_BIT].offset;
|
||||||
do_xsave_bndcsr(env, ptr + off, ra);
|
do_xsave_bndcsr(env, ptr + off, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1428,19 +1428,19 @@ void helper_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
|
||||||
raise_exception_ra(env, EXCP0D_GPF, ra);
|
raise_exception_ra(env, EXCP0D_GPF, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rfbm & XSTATE_FP) {
|
if (rfbm & XSTATE_FP_MASK) {
|
||||||
if (xstate_bv & XSTATE_FP) {
|
if (xstate_bv & XSTATE_FP_MASK) {
|
||||||
do_xrstor_fpu(env, ptr, ra);
|
do_xrstor_fpu(env, ptr, ra);
|
||||||
} else {
|
} else {
|
||||||
helper_fninit(env);
|
helper_fninit(env);
|
||||||
memset(env->fpregs, 0, sizeof(env->fpregs));
|
memset(env->fpregs, 0, sizeof(env->fpregs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rfbm & XSTATE_SSE) {
|
if (rfbm & XSTATE_SSE_MASK) {
|
||||||
/* Note that the standard form of XRSTOR loads MXCSR from memory
|
/* Note that the standard form of XRSTOR loads MXCSR from memory
|
||||||
whether or not the XSTATE_BV bit is set. */
|
whether or not the XSTATE_BV bit is set. */
|
||||||
do_xrstor_mxcsr(env, ptr, ra);
|
do_xrstor_mxcsr(env, ptr, ra);
|
||||||
if (xstate_bv & XSTATE_SSE) {
|
if (xstate_bv & XSTATE_SSE_MASK) {
|
||||||
do_xrstor_sse(env, ptr, ra);
|
do_xrstor_sse(env, ptr, ra);
|
||||||
} else {
|
} else {
|
||||||
/* ??? When AVX is implemented, we may have to be more
|
/* ??? When AVX is implemented, we may have to be more
|
||||||
|
@ -1448,9 +1448,9 @@ void helper_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
|
||||||
memset(env->xmm_regs, 0, sizeof(env->xmm_regs));
|
memset(env->xmm_regs, 0, sizeof(env->xmm_regs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rfbm & XSTATE_BNDREGS) {
|
if (rfbm & XSTATE_BNDREGS_MASK) {
|
||||||
if (xstate_bv & XSTATE_BNDREGS) {
|
if (xstate_bv & XSTATE_BNDREGS_MASK) {
|
||||||
target_ulong off = x86_ext_save_areas[XSTATE_BNDREGS].offset;
|
target_ulong off = x86_ext_save_areas[XSTATE_BNDREGS_BIT].offset;
|
||||||
do_xrstor_bndregs(env, ptr + off, ra);
|
do_xrstor_bndregs(env, ptr + off, ra);
|
||||||
env->hflags |= HF_MPX_IU_MASK;
|
env->hflags |= HF_MPX_IU_MASK;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1458,9 +1458,9 @@ void helper_xrstor(CPUX86State *env, target_ulong ptr, uint64_t rfbm)
|
||||||
env->hflags &= ~HF_MPX_IU_MASK;
|
env->hflags &= ~HF_MPX_IU_MASK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rfbm & XSTATE_BNDCSR) {
|
if (rfbm & XSTATE_BNDCSR_MASK) {
|
||||||
if (xstate_bv & XSTATE_BNDCSR) {
|
if (xstate_bv & XSTATE_BNDCSR_MASK) {
|
||||||
target_ulong off = x86_ext_save_areas[XSTATE_BNDCSR].offset;
|
target_ulong off = x86_ext_save_areas[XSTATE_BNDCSR_BIT].offset;
|
||||||
do_xrstor_bndcsr(env, ptr + off, ra);
|
do_xrstor_bndcsr(env, ptr + off, ra);
|
||||||
} else {
|
} else {
|
||||||
memset(&env->bndcs_regs, 0, sizeof(env->bndcs_regs));
|
memset(&env->bndcs_regs, 0, sizeof(env->bndcs_regs));
|
||||||
|
@ -1499,7 +1499,7 @@ void helper_xsetbv(CPUX86State *env, uint32_t ecx, uint64_t mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only XCR0 is defined at present; the FPU may not be disabled. */
|
/* Only XCR0 is defined at present; the FPU may not be disabled. */
|
||||||
if (ecx != 0 || (mask & XSTATE_FP) == 0) {
|
if (ecx != 0 || (mask & XSTATE_FP_MASK) == 0) {
|
||||||
goto do_gpf;
|
goto do_gpf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1511,7 +1511,8 @@ void helper_xsetbv(CPUX86State *env, uint32_t ecx, uint64_t mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disallow enabling only half of MPX. */
|
/* Disallow enabling only half of MPX. */
|
||||||
if ((mask ^ (mask * (XSTATE_BNDCSR / XSTATE_BNDREGS))) & XSTATE_BNDCSR) {
|
if ((mask ^ (mask * (XSTATE_BNDCSR_MASK / XSTATE_BNDREGS_MASK)))
|
||||||
|
& XSTATE_BNDCSR_MASK) {
|
||||||
goto do_gpf;
|
goto do_gpf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ void cpu_sync_bndcs_hflags(CPUX86State *env)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((env->cr[4] & CR4_OSXSAVE_MASK)
|
if ((env->cr[4] & CR4_OSXSAVE_MASK)
|
||||||
&& (env->xcr0 & XSTATE_BNDCSR)
|
&& (env->xcr0 & XSTATE_BNDCSR_MASK)
|
||||||
&& (bndcsr & BNDCFG_ENABLE)) {
|
&& (bndcsr & BNDCFG_ENABLE)) {
|
||||||
hflags |= HF_MPX_EN_MASK;
|
hflags |= HF_MPX_EN_MASK;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue