With it, add a new hidden flag that will be used to enable the REX2 prefix and EVEX map4.
Signed-off-by: Paolo Bonzini <[email protected]> --- target/i386/cpu.h | 3 ++ target/i386/tcg/tcg-cpu.h | 16 +++++++--- target/i386/helper.c | 11 +++++++ target/i386/tcg/fpu_helper.c | 59 +++++++++++++++++++++++++++++++++--- target/i386/tcg/tcg-cpu.c | 5 +-- 5 files changed, 83 insertions(+), 11 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index da5161fc1a5..7586ea0ed8d 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -186,6 +186,7 @@ typedef enum X86Seg { #define HF_MPX_IU_SHIFT 26 /* BND registers in-use */ #define HF_UMIP_SHIFT 27 /* CR4.UMIP */ #define HF_AVX_EN_SHIFT 28 /* AVX Enabled (CR4+XCR0) */ +#define HF_APX_EN_SHIFT 29 /* APX Enabled (CR4+XCR0) */ #define HF_CPL_MASK (3 << HF_CPL_SHIFT) #define HF_INHIBIT_IRQ_MASK (1 << HF_INHIBIT_IRQ_SHIFT) @@ -213,6 +214,7 @@ typedef enum X86Seg { #define HF_MPX_IU_MASK (1 << HF_MPX_IU_SHIFT) #define HF_UMIP_MASK (1 << HF_UMIP_SHIFT) #define HF_AVX_EN_MASK (1 << HF_AVX_EN_SHIFT) +#define HF_APX_EN_MASK (1 << HF_APX_EN_SHIFT) /* hflags2 */ @@ -2729,6 +2731,7 @@ static inline bool x86_has_cpuid_0x1f(X86CPU *cpu) /* helper.c */ void x86_cpu_set_a20(X86CPU *cpu, int a20_state); void cpu_sync_avx_hflag(CPUX86State *env); +void cpu_sync_apx_hflag(CPUX86State *env); typedef enum X86ASIdx { X86ASIdx_MEM = 0, diff --git a/target/i386/tcg/tcg-cpu.h b/target/i386/tcg/tcg-cpu.h index 85bcd61678f..451f61e2043 100644 --- a/target/i386/tcg/tcg-cpu.h +++ b/target/i386/tcg/tcg-cpu.h @@ -52,9 +52,15 @@ typedef struct X86XSaveArea { - sizeof(X86XSaveHeader) - sizeof(XSaveAVX)]; - /* MPX State: */ - XSaveBNDREG bndreg_state; - XSaveBNDCSR bndcsr_state; + /* Overlapping MPX and APX States: */ + union { + struct { + XSaveBNDREG bndreg; + XSaveBNDCSR bndcsr; + } mpx_state; + XSaveAPX apx_state; + }; + /* AVX-512 State: */ XSaveOpmask opmask_state; XSaveZMM_Hi256 zmm_hi256_state; @@ -71,8 +77,8 @@ QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.mxcsr) != XSAVE_MXCSR_OFFSET); QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.fpregs) != XSAVE_ST_SPACE_OFFSET); QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, legacy.xmm_regs) != XSAVE_XMM_SPACE_OFFSET); QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, avx_state) != XSAVE_AVX_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndreg_state) != XSAVE_BNDREG_OFFSET); -QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, bndcsr_state) != XSAVE_BNDCSR_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, mpx_state.bndreg) != XSAVE_BNDREG_OFFSET); +QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, mpx_state.bndcsr) != XSAVE_BNDCSR_OFFSET); QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, opmask_state) != XSAVE_OPMASK_OFFSET); QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, zmm_hi256_state) != XSAVE_ZMM_HI256_OFFSET); QEMU_BUILD_BUG_ON(offsetof(X86XSaveArea, hi16_zmm_state) != XSAVE_HI16_ZMM_OFFSET); diff --git a/target/i386/helper.c b/target/i386/helper.c index f9f9488eb4d..d01b12f8af7 100644 --- a/target/i386/helper.c +++ b/target/i386/helper.c @@ -35,6 +35,16 @@ #include "tcg/insn-start-words.h" #endif +void cpu_sync_apx_hflag(CPUX86State *env) +{ + if ((env->cr[4] & CR4_OSXSAVE_MASK) + && (env->xcr0 & XSTATE_APX_MASK) == XSTATE_APX_MASK) { + env->hflags |= HF_APX_EN_MASK; + } else{ + env->hflags &= ~HF_APX_EN_MASK; + } +} + void cpu_sync_avx_hflag(CPUX86State *env) { if ((env->cr[4] & CR4_OSXSAVE_MASK) @@ -249,6 +259,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4) cpu_sync_bndcs_hflags(env); cpu_sync_avx_hflag(env); + cpu_sync_apx_hflag(env); } #if !defined(CONFIG_USER_ONLY) diff --git a/target/i386/tcg/fpu_helper.c b/target/i386/tcg/fpu_helper.c index b3b23823fda..26fc9af7082 100644 --- a/target/i386/tcg/fpu_helper.c +++ b/target/i386/tcg/fpu_helper.c @@ -2691,6 +2691,19 @@ static void do_xsave_pkru(X86Access *ac, target_ulong ptr) access_stq(ac, ptr, ac->env->pkru); } +#ifdef TARGET_X86_64 +static void do_xsave_apx(X86Access *ac, target_ulong ptr) +{ + CPUX86State *env = ac->env; + int i; + + for (i = 16; i < 32; i++) { + access_stq(ac, ptr, env->regs[i]); + ptr += 8; + } +} +#endif + static void do_fxsave(X86Access *ac, target_ulong ptr) { CPUX86State *env = ac->env; @@ -2755,14 +2768,19 @@ static void do_xsave_access(X86Access *ac, target_ulong ptr, uint64_t rfbm, do_xsave_ymmh(ac, ptr + XO(avx_state)); } if (opt & XSTATE_BNDREGS_MASK) { - do_xsave_bndregs(ac, ptr + XO(bndreg_state)); + do_xsave_bndregs(ac, ptr + XO(mpx_state.bndreg)); } if (opt & XSTATE_BNDCSR_MASK) { - do_xsave_bndcsr(ac, ptr + XO(bndcsr_state)); + do_xsave_bndcsr(ac, ptr + XO(mpx_state.bndcsr)); } if (opt & XSTATE_PKRU_MASK) { do_xsave_pkru(ac, ptr + XO(pkru_state)); } +#ifdef TARGET_X86_64 + if (opt & XSTATE_APX_MASK) { + do_xsave_apx(ac, ptr + XO(apx_state)); + } +#endif /* Update the XSTATE_BV field. */ old_bv = access_ldq(ac, ptr + XO(header.xstate_bv)); @@ -2956,6 +2974,29 @@ static void do_fxrstor(X86Access *ac, target_ulong ptr) } } +#ifdef TARGET_X86_64 +static void do_xrstor_apx(X86Access *ac, target_ulong ptr) +{ + CPUX86State *env = ac->env; + int i; + + for (i = 16; i < 32; i++) { + env->regs[i] = access_ldq(ac, ptr); + ptr += 8; + } +} + +static void do_clear_apx(X86Access *ac) +{ + CPUX86State *env = ac->env; + int i; + + for (i = 16; i < 32; i++) { + env->regs[i] = 0; + } +} +#endif + void helper_fxrstor(CPUX86State *env, target_ulong ptr) { uintptr_t ra = GETPC(); @@ -3027,7 +3068,7 @@ static void do_xrstor(X86Access *ac, target_ulong ptr, } if (rfbm & XSTATE_BNDREGS_MASK) { if (xstate_bv & XSTATE_BNDREGS_MASK) { - do_xrstor_bndregs(ac, ptr + XO(bndreg_state)); + do_xrstor_bndregs(ac, ptr + XO(mpx_state.bndreg)); env->hflags |= HF_MPX_IU_MASK; } else { memset(env->bnd_regs, 0, sizeof(env->bnd_regs)); @@ -3036,7 +3077,7 @@ static void do_xrstor(X86Access *ac, target_ulong ptr, } if (rfbm & XSTATE_BNDCSR_MASK) { if (xstate_bv & XSTATE_BNDCSR_MASK) { - do_xrstor_bndcsr(ac, ptr + XO(bndcsr_state)); + do_xrstor_bndcsr(ac, ptr + XO(mpx_state.bndcsr)); } else { memset(&env->bndcs_regs, 0, sizeof(env->bndcs_regs)); } @@ -3054,6 +3095,15 @@ static void do_xrstor(X86Access *ac, target_ulong ptr, tlb_flush(cs); } } +#ifdef TARGET_X86_64 + if (rfbm & XSTATE_APX_MASK) { + if (xstate_bv & XSTATE_APX_MASK) { + do_xrstor_apx(ac, ptr + XO(apx_state)); + } else { + do_clear_apx(ac); + } + } +#endif } #undef XO @@ -3229,6 +3279,7 @@ void helper_xsetbv(CPUX86State *env, uint32_t ecx, uint64_t mask) env->xcr0 = mask; cpu_sync_bndcs_hflags(env); cpu_sync_avx_hflag(env); + cpu_sync_apx_hflag(env); return; do_gpf: diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c index 6f5dc06b3b9..2965c304e57 100644 --- a/target/i386/tcg/tcg-cpu.c +++ b/target/i386/tcg/tcg-cpu.c @@ -198,12 +198,13 @@ static void x86_tcg_cpu_xsave_init(void) XO(XSTATE_FP_BIT, legacy); XO(XSTATE_SSE_BIT, legacy); XO(XSTATE_YMM_BIT, avx_state); - XO(XSTATE_BNDREGS_BIT, bndreg_state); - XO(XSTATE_BNDCSR_BIT, bndcsr_state); + XO(XSTATE_BNDREGS_BIT, mpx_state.bndreg); + XO(XSTATE_BNDCSR_BIT, mpx_state.bndcsr); XO(XSTATE_OPMASK_BIT, opmask_state); XO(XSTATE_ZMM_Hi256_BIT, zmm_hi256_state); XO(XSTATE_Hi16_ZMM_BIT, hi16_zmm_state); XO(XSTATE_PKRU_BIT, pkru_state); + XO(XSTATE_APX_BIT, apx_state); #undef XO } -- 2.52.0
