With it, add a new hidden flag that will be used to enable the REX2 prefix and EVEX map4.
Reviewed-by: Chang S. Bae <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]> --- target/i386/cpu.h | 3 ++ target/i386/tcg/tcg-cpu.h | 18 ++++++++--- target/i386/helper.c | 11 +++++++ target/i386/tcg/fpu_helper.c | 59 +++++++++++++++++++++++++++++++++--- target/i386/tcg/tcg-cpu.c | 5 +-- 5 files changed, 85 insertions(+), 11 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 3f69b0a066a..c8619666f07 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -191,6 +191,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) @@ -218,6 +219,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 */ @@ -2771,6 +2773,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..919c2f3ee3b 100644 --- a/target/i386/tcg/tcg-cpu.h +++ b/target/i386/tcg/tcg-cpu.h @@ -32,6 +32,7 @@ #define XSAVE_AVX_OFFSET 0x240 #define XSAVE_BNDREG_OFFSET 0x3c0 #define XSAVE_BNDCSR_OFFSET 0x400 +#define XSAVE_APX_OFFSET XSAVE_BNDREG_OFFSET #define XSAVE_OPMASK_OFFSET 0x440 #define XSAVE_ZMM_HI256_OFFSET 0x480 #define XSAVE_HI16_ZMM_OFFSET 0x680 @@ -52,9 +53,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 +78,9 @@ 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, apx_state) != XSAVE_APX_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 4133b5f244c..cb25018ecbb 100644 --- a/target/i386/helper.c +++ b/target/i386/helper.c @@ -36,6 +36,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) @@ -250,6 +260,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 56d093da8c9..fb473c28f7b 100644 --- a/target/i386/tcg/fpu_helper.c +++ b/target/i386/tcg/fpu_helper.c @@ -2709,6 +2709,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; @@ -2773,14 +2786,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)); @@ -2974,6 +2992,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(); @@ -3045,7 +3086,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)); @@ -3054,7 +3095,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)); } @@ -3072,6 +3113,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 @@ -3253,6 +3303,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 2402608fe90..9db9795a3b2 100644 --- a/target/i386/tcg/tcg-cpu.c +++ b/target/i386/tcg/tcg-cpu.c @@ -200,12 +200,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.55.0
