Finally allow TCG to set the CPUID bit for the APXF feature. The effect of APX is about 0.5% larger binaries and about 1% less TCG ops. QEMU seems to produce about 1% *more* assembly instructions, because the optimizer could already produce roughly the same ops as NDD or NF instructions, and the new PUSH2/POP2 instructions include a stack alignment check that isn't there in non-APX code.
Signed-off-by: Paolo Bonzini <[email protected]> --- configs/targets/x86_64-bsd-user.mak | 2 +- configs/targets/x86_64-linux-user.mak | 2 +- target/i386/cpu.c | 34 ++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/configs/targets/x86_64-bsd-user.mak b/configs/targets/x86_64-bsd-user.mak index d754186347f..26b7cfad4e2 100644 --- a/configs/targets/x86_64-bsd-user.mak +++ b/configs/targets/x86_64-bsd-user.mak @@ -1,4 +1,4 @@ TARGET_ARCH=x86_64 TARGET_BASE_ARCH=i386 -TARGET_XML_FILES= i386-64bit.xml +TARGET_XML_FILES= i386-64bit.xml i386-64bit-apx.xml TARGET_LONG_BITS=64 diff --git a/configs/targets/x86_64-linux-user.mak b/configs/targets/x86_64-linux-user.mak index 7f9527fd1de..cad68746bdb 100644 --- a/configs/targets/x86_64-linux-user.mak +++ b/configs/targets/x86_64-linux-user.mak @@ -2,5 +2,5 @@ TARGET_ARCH=x86_64 TARGET_BASE_ARCH=i386 TARGET_SYSTBL_ABI=common,64 TARGET_SYSTBL=syscall_64.tbl -TARGET_XML_FILES= i386-64bit.xml i386-64bit-linux.xml +TARGET_XML_FILES= i386-64bit.xml i386-64bit-linux.xml i386-64bit-apx.xml TARGET_LONG_BITS=64 diff --git a/target/i386/cpu.c b/target/i386/cpu.c index b6ad69d5047..62cce7d3105 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1005,7 +1005,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, #define TCG_7_1_EAX_FEATURES (CPUID_7_1_EAX_FZRM | CPUID_7_1_EAX_FSRS | \ CPUID_7_1_EAX_FSRC | CPUID_7_1_EAX_CMPCCXADD) #define TCG_7_1_ECX_FEATURES 0 -#define TCG_7_1_EDX_FEATURES 0 +#define TCG_7_1_EDX_FEATURES CPUID_7_1_EDX_APXF #define TCG_7_2_EDX_FEATURES 0 #define TCG_APM_FEATURES 0 #define TCG_6_EAX_FEATURES CPUID_6_EAX_ARAT @@ -1017,7 +1017,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, #define TCG_SGX_12_0_EBX_FEATURES 0 #define TCG_SGX_12_1_EAX_FEATURES 0 #define TCG_24_0_EBX_FEATURES 0 -#define TCG_29_0_EBX_FEATURES 0 +#define TCG_29_0_EBX_FEATURES CPUID_29_0_EBX_APX_NCI_NDD_NF #define TCG_1E_1_EAX_FEATURES 0 #define TCG_24_1_ECX_FEATURES 0 @@ -1554,7 +1554,7 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = { }, .tcg_features = XSTATE_FP_MASK | XSTATE_SSE_MASK | XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK | - XSTATE_PKRU_MASK, + XSTATE_PKRU_MASK | XSTATE_APX_MASK, .migratable_flags = XSTATE_FP_MASK | XSTATE_SSE_MASK | XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | XSTATE_ZMM_Hi256_MASK | XSTATE_Hi16_ZMM_MASK | @@ -9722,9 +9722,37 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp) * inside x86_cpu_parse_featurestr() too. */ if (xcc->max_features) { + /* + * TCG supports both MPX and APX. Since they they cannot be enabled together, + * disable one---prefer APX if none was chosen explicitly. + */ + uint64_t feat7_1_edx = env->user_features[FEAT_7_1_EDX] & CPUID_7_1_EDX_APXF + ? env->features[FEAT_7_1_EDX] + : x86_cpu_get_supported_feature_word(cpu, FEAT_7_1_EDX); + uint64_t feat7_0_ebx = env->user_features[FEAT_7_0_EBX] & CPUID_7_0_EBX_MPX + ? env->features[FEAT_7_0_EBX] + : x86_cpu_get_supported_feature_word(cpu, FEAT_7_0_EBX); + + bool apx = feat7_1_edx & CPUID_7_1_EDX_APXF; + bool mpx = feat7_0_ebx & CPUID_7_0_EBX_MPX; + if (apx && mpx) { + if (env->user_features[FEAT_7_1_EDX] & CPUID_7_1_EDX_APXF + || !(env->user_features[FEAT_7_0_EBX] & CPUID_7_0_EBX_MPX)) { + mpx = false; + } else { + apx = false; + } + } + for (w = 0; w < FEATURE_WORDS; w++) { /* Override only features that weren't set explicitly by the user. */ uint64_t no_autoenable_flags = env->user_features[w] | feature_word_info[w].no_autoenable_flags; + if (w == FEAT_7_1_EDX && mpx) { + no_autoenable_flags |= CPUID_7_1_EDX_APXF; + } + if (w == FEAT_7_0_EBX && apx) { + no_autoenable_flags |= CPUID_7_0_EBX_MPX; + } env->features[w] |= x86_cpu_get_supported_feature_word(cpu, w) & ~no_autoenable_flags; } -- 2.55.0
