diff options
Diffstat (limited to 'usr/src/uts/intel/os/cpuid.c')
| -rw-r--r-- | usr/src/uts/intel/os/cpuid.c | 583 |
1 files changed, 256 insertions, 327 deletions
diff --git a/usr/src/uts/intel/os/cpuid.c b/usr/src/uts/intel/os/cpuid.c index a723ae904e..1459c034b9 100644 --- a/usr/src/uts/intel/os/cpuid.c +++ b/usr/src/uts/intel/os/cpuid.c @@ -1634,7 +1634,12 @@ static char *x86_feature_names[NUM_X86_FEATURES] = { "ppin", "vaes", "vpclmulqdq", - "lfence_serializing" + "lfence_serializing", + "gfni", + "avx512_vp2intersect", + "avx512_bitalg", + "avx512_vbmi2", + "avx512_bf16" }; boolean_t @@ -1786,6 +1791,7 @@ struct cpuid_info { /* Intel fn: 4, AMD fn: 8000001d */ struct cpuid_regs **cpi_cache_leaves; /* Acual leaves from above */ struct cpuid_regs cpi_std[NMAX_CPI_STD]; /* 0 .. 7 */ + struct cpuid_regs cpi_sub7[1]; /* Leaf 7, sub-leaf 1 */ /* * extended function information */ @@ -1857,6 +1863,7 @@ static struct cpuid_info cpuid_info0; #define CPI_FEATURES_7_0_EBX(cpi) ((cpi)->cpi_std[7].cp_ebx) #define CPI_FEATURES_7_0_ECX(cpi) ((cpi)->cpi_std[7].cp_ecx) #define CPI_FEATURES_7_0_EDX(cpi) ((cpi)->cpi_std[7].cp_edx) +#define CPI_FEATURES_7_1_EAX(cpi) ((cpi)->cpi_sub7[0].cp_eax) #define CPI_BRANDID(cpi) BITX((cpi)->cpi_std[1].cp_ebx, 7, 0) #define CPI_CHUNKS(cpi) BITX((cpi)->cpi_std[1].cp_ebx, 15, 7) @@ -3386,6 +3393,109 @@ cpuid_basic_thermal(cpu_t *cpu, uchar_t *featureset) } /* + * This is used when we discover that we have AVX support in cpuid. This + * proceeds to scan for the rest of the AVX derived features. + */ +static void +cpuid_basic_avx(cpu_t *cpu, uchar_t *featureset) +{ + struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi; + + /* + * If we don't have AVX, don't bother with most of this. + */ + if ((cpi->cpi_std[1].cp_ecx & CPUID_INTC_ECX_AVX) == 0) + return; + + add_x86_feature(featureset, X86FSET_AVX); + + /* + * Intel says we can't check these without also + * checking AVX. + */ + if (cpi->cpi_std[1].cp_ecx & CPUID_INTC_ECX_F16C) + add_x86_feature(featureset, X86FSET_F16C); + + if (cpi->cpi_std[1].cp_ecx & CPUID_INTC_ECX_FMA) + add_x86_feature(featureset, X86FSET_FMA); + + if (cpi->cpi_std[7].cp_ebx & CPUID_INTC_EBX_7_0_BMI1) + add_x86_feature(featureset, X86FSET_BMI1); + + if (cpi->cpi_std[7].cp_ebx & CPUID_INTC_EBX_7_0_BMI2) + add_x86_feature(featureset, X86FSET_BMI2); + + if (cpi->cpi_std[7].cp_ebx & CPUID_INTC_EBX_7_0_AVX2) + add_x86_feature(featureset, X86FSET_AVX2); + + if (cpi->cpi_std[7].cp_ecx & CPUID_INTC_ECX_7_0_VAES) + add_x86_feature(featureset, X86FSET_VAES); + + if (cpi->cpi_std[7].cp_ecx & CPUID_INTC_ECX_7_0_VPCLMULQDQ) + add_x86_feature(featureset, X86FSET_VPCLMULQDQ); + + /* + * The rest of the AVX features require AVX512. Do not check them unless + * it is present. + */ + if ((cpi->cpi_std[7].cp_ebx & CPUID_INTC_EBX_7_0_AVX512F) == 0) + return; + add_x86_feature(featureset, X86FSET_AVX512F); + + if (cpi->cpi_std[7].cp_ebx & CPUID_INTC_EBX_7_0_AVX512DQ) + add_x86_feature(featureset, X86FSET_AVX512DQ); + + if (cpi->cpi_std[7].cp_ebx & CPUID_INTC_EBX_7_0_AVX512IFMA) + add_x86_feature(featureset, X86FSET_AVX512FMA); + + if (cpi->cpi_std[7].cp_ebx & CPUID_INTC_EBX_7_0_AVX512PF) + add_x86_feature(featureset, X86FSET_AVX512PF); + + if (cpi->cpi_std[7].cp_ebx & CPUID_INTC_EBX_7_0_AVX512ER) + add_x86_feature(featureset, X86FSET_AVX512ER); + + if (cpi->cpi_std[7].cp_ebx & CPUID_INTC_EBX_7_0_AVX512CD) + add_x86_feature(featureset, X86FSET_AVX512CD); + + if (cpi->cpi_std[7].cp_ebx & CPUID_INTC_EBX_7_0_AVX512BW) + add_x86_feature(featureset, X86FSET_AVX512BW); + + if (cpi->cpi_std[7].cp_ebx & CPUID_INTC_EBX_7_0_AVX512VL) + add_x86_feature(featureset, X86FSET_AVX512VL); + + if (cpi->cpi_std[7].cp_ecx & CPUID_INTC_ECX_7_0_AVX512VBMI) + add_x86_feature(featureset, X86FSET_AVX512VBMI); + + if (cpi->cpi_std[7].cp_ecx & CPUID_INTC_ECX_7_0_AVX512VBMI2) + add_x86_feature(featureset, X86FSET_AVX512_VBMI2); + + if (cpi->cpi_std[7].cp_ecx & CPUID_INTC_ECX_7_0_AVX512VNNI) + add_x86_feature(featureset, X86FSET_AVX512VNNI); + + if (cpi->cpi_std[7].cp_ecx & CPUID_INTC_ECX_7_0_AVX512BITALG) + add_x86_feature(featureset, X86FSET_AVX512_BITALG); + + if (cpi->cpi_std[7].cp_ecx & CPUID_INTC_ECX_7_0_AVX512VPOPCDQ) + add_x86_feature(featureset, X86FSET_AVX512VPOPCDQ); + + if (cpi->cpi_std[7].cp_edx & CPUID_INTC_EDX_7_0_AVX5124NNIW) + add_x86_feature(featureset, X86FSET_AVX512NNIW); + + if (cpi->cpi_std[7].cp_edx & CPUID_INTC_EDX_7_0_AVX5124FMAPS) + add_x86_feature(featureset, X86FSET_AVX512FMAPS); + + /* + * More features here are in Leaf 7, subleaf 1. Don't bother checking if + * we don't need to. + */ + if (cpi->cpi_std[7].cp_eax < 1) + return; + + if (cpi->cpi_sub7[0].cp_eax & CPUID_INTC_EAX_7_1_AVX512_BF16) + add_x86_feature(featureset, X86FSET_AVX512_BF16); +} + +/* * PPIN is the protected processor inventory number. On AMD this is an actual * feature bit. However, on Intel systems we need to read the platform * information MSR if we're on a specific model. @@ -3781,7 +3891,8 @@ cpuid_pass_basic(cpu_t *cpu, void *arg) /* * In addition to ecx and edx, Intel and AMD are storing a bunch of - * instruction set extensions in leaf 7's ebx, ecx, and edx. + * instruction set extensions in leaf 7's ebx, ecx, and edx. Note, leaf + * 7 has sub-leaves determined by ecx. */ if (cpi->cpi_maxeax >= 7) { struct cpuid_regs *ecp; @@ -3792,7 +3903,10 @@ cpuid_pass_basic(cpu_t *cpu, void *arg) /* * If XSAVE has been disabled, just ignore all of the - * extended-save-area dependent flags here. + * extended-save-area dependent flags here. By removing most of + * the leaf 7, sub-leaf 0 flags, that will ensure tha we don't + * end up looking at additional xsave dependent leaves right + * now. */ if (xsave_force_disable) { ecp->cp_ebx &= ~CPUID_INTC_EBX_7_0_BMI1; @@ -3804,6 +3918,7 @@ cpuid_pass_basic(cpu_t *cpu, void *arg) ecp->cp_edx &= ~CPUID_INTC_EDX_7_0_ALL_AVX512; ecp->cp_ecx &= ~CPUID_INTC_ECX_7_0_VAES; ecp->cp_ecx &= ~CPUID_INTC_ECX_7_0_VPCLMULQDQ; + ecp->cp_ecx &= ~CPUID_INTC_ECX_7_0_GFNI; } if (ecp->cp_ebx & CPUID_INTC_EBX_7_0_SMEP) @@ -3840,13 +3955,27 @@ cpuid_pass_basic(cpu_t *cpu, void *arg) add_x86_feature(featureset, X86FSET_PKU); if (ecp->cp_ecx & CPUID_INTC_ECX_7_0_OSPKE) add_x86_feature(featureset, X86FSET_OSPKE); + if (ecp->cp_ecx & CPUID_INTC_ECX_7_0_GFNI) + add_x86_feature(featureset, X86FSET_GFNI); + + if (ecp->cp_ebx & CPUID_INTC_EBX_7_0_CLWB) + add_x86_feature(featureset, X86FSET_CLWB); if (cpi->cpi_vendor == X86_VENDOR_Intel) { if (ecp->cp_ebx & CPUID_INTC_EBX_7_0_MPX) add_x86_feature(featureset, X86FSET_MPX); + } - if (ecp->cp_ebx & CPUID_INTC_EBX_7_0_CLWB) - add_x86_feature(featureset, X86FSET_CLWB); + /* + * If we have subleaf 1 available, grab and store that. This is + * used for more AVX and related features. + */ + if (ecp->cp_eax >= 1) { + struct cpuid_regs *c71; + c71 = &cpi->cpi_sub7[0]; + c71->cp_eax = 7; + c71->cp_ecx = 1; + (void) __cpuid_insn(c71); } } @@ -3937,105 +4066,7 @@ cpuid_pass_basic(cpu_t *cpu, void *arg) add_x86_feature(featureset, X86FSET_XSAVE); /* We only test AVX & AVX512 when there is XSAVE */ - - if (cp->cp_ecx & CPUID_INTC_ECX_AVX) { - add_x86_feature(featureset, - X86FSET_AVX); - - /* - * Intel says we can't check these without also - * checking AVX. - */ - if (cp->cp_ecx & CPUID_INTC_ECX_F16C) - add_x86_feature(featureset, - X86FSET_F16C); - - if (cp->cp_ecx & CPUID_INTC_ECX_FMA) - add_x86_feature(featureset, - X86FSET_FMA); - - if (cpi->cpi_std[7].cp_ebx & - CPUID_INTC_EBX_7_0_BMI1) - add_x86_feature(featureset, - X86FSET_BMI1); - - if (cpi->cpi_std[7].cp_ebx & - CPUID_INTC_EBX_7_0_BMI2) - add_x86_feature(featureset, - X86FSET_BMI2); - - if (cpi->cpi_std[7].cp_ebx & - CPUID_INTC_EBX_7_0_AVX2) - add_x86_feature(featureset, - X86FSET_AVX2); - - if (cpi->cpi_std[7].cp_ecx & - CPUID_INTC_ECX_7_0_VAES) - add_x86_feature(featureset, - X86FSET_VAES); - - if (cpi->cpi_std[7].cp_ecx & - CPUID_INTC_ECX_7_0_VPCLMULQDQ) - add_x86_feature(featureset, - X86FSET_VPCLMULQDQ); - } - - if (cpi->cpi_vendor == X86_VENDOR_Intel && - (cpi->cpi_std[7].cp_ebx & - CPUID_INTC_EBX_7_0_AVX512F) != 0) { - add_x86_feature(featureset, X86FSET_AVX512F); - - if (cpi->cpi_std[7].cp_ebx & - CPUID_INTC_EBX_7_0_AVX512DQ) - add_x86_feature(featureset, - X86FSET_AVX512DQ); - if (cpi->cpi_std[7].cp_ebx & - CPUID_INTC_EBX_7_0_AVX512IFMA) - add_x86_feature(featureset, - X86FSET_AVX512FMA); - if (cpi->cpi_std[7].cp_ebx & - CPUID_INTC_EBX_7_0_AVX512PF) - add_x86_feature(featureset, - X86FSET_AVX512PF); - if (cpi->cpi_std[7].cp_ebx & - CPUID_INTC_EBX_7_0_AVX512ER) - add_x86_feature(featureset, - X86FSET_AVX512ER); - if (cpi->cpi_std[7].cp_ebx & - CPUID_INTC_EBX_7_0_AVX512CD) - add_x86_feature(featureset, - X86FSET_AVX512CD); - if (cpi->cpi_std[7].cp_ebx & - CPUID_INTC_EBX_7_0_AVX512BW) - add_x86_feature(featureset, - X86FSET_AVX512BW); - if (cpi->cpi_std[7].cp_ebx & - CPUID_INTC_EBX_7_0_AVX512VL) - add_x86_feature(featureset, - X86FSET_AVX512VL); - - if (cpi->cpi_std[7].cp_ecx & - CPUID_INTC_ECX_7_0_AVX512VBMI) - add_x86_feature(featureset, - X86FSET_AVX512VBMI); - if (cpi->cpi_std[7].cp_ecx & - CPUID_INTC_ECX_7_0_AVX512VNNI) - add_x86_feature(featureset, - X86FSET_AVX512VNNI); - if (cpi->cpi_std[7].cp_ecx & - CPUID_INTC_ECX_7_0_AVX512VPOPCDQ) - add_x86_feature(featureset, - X86FSET_AVX512VPOPCDQ); - - if (cpi->cpi_std[7].cp_edx & - CPUID_INTC_EDX_7_0_AVX5124NNIW) - add_x86_feature(featureset, - X86FSET_AVX512NNIW); - if (cpi->cpi_std[7].cp_edx & - CPUID_INTC_EDX_7_0_AVX5124FMAPS) - add_x86_feature(featureset, - X86FSET_AVX512FMAPS); - } + cpuid_basic_avx(cpu, featureset); } } @@ -4761,36 +4792,16 @@ cpuid_pass_extended(cpu_t *cpu, void *_arg __unused) X86FSET_VAES); remove_x86_feature(x86_featureset, X86FSET_VPCLMULQDQ); - - CPI_FEATURES_ECX(cpi) &= - ~CPUID_INTC_ECX_XSAVE; - CPI_FEATURES_ECX(cpi) &= - ~CPUID_INTC_ECX_AVX; - CPI_FEATURES_ECX(cpi) &= - ~CPUID_INTC_ECX_F16C; - CPI_FEATURES_ECX(cpi) &= - ~CPUID_INTC_ECX_FMA; - CPI_FEATURES_7_0_EBX(cpi) &= - ~CPUID_INTC_EBX_7_0_BMI1; - CPI_FEATURES_7_0_EBX(cpi) &= - ~CPUID_INTC_EBX_7_0_BMI2; - CPI_FEATURES_7_0_EBX(cpi) &= - ~CPUID_INTC_EBX_7_0_AVX2; - CPI_FEATURES_7_0_EBX(cpi) &= - ~CPUID_INTC_EBX_7_0_MPX; - CPI_FEATURES_7_0_EBX(cpi) &= - ~CPUID_INTC_EBX_7_0_ALL_AVX512; - - CPI_FEATURES_7_0_ECX(cpi) &= - ~CPUID_INTC_ECX_7_0_ALL_AVX512; - - CPI_FEATURES_7_0_ECX(cpi) &= - ~CPUID_INTC_ECX_7_0_VAES; - CPI_FEATURES_7_0_ECX(cpi) &= - ~CPUID_INTC_ECX_7_0_VPCLMULQDQ; - - CPI_FEATURES_7_0_EDX(cpi) &= - ~CPUID_INTC_EDX_7_0_ALL_AVX512; + remove_x86_feature(x86_featureset, + X86FSET_GFNI); + remove_x86_feature(x86_featureset, + X86FSET_AVX512_VP2INT); + remove_x86_feature(x86_featureset, + X86FSET_AVX512_BITALG); + remove_x86_feature(x86_featureset, + X86FSET_AVX512_VBMI2); + remove_x86_feature(x86_featureset, + X86FSET_AVX512_BF16); xsave_force_disable = B_TRUE; } else { @@ -5420,11 +5431,93 @@ cpuid_pass_dynamic(cpu_t *cpu, void *_arg __unused) } } +typedef struct { + uint32_t avm_av; + uint32_t avm_feat; +} av_feat_map_t; + +/* + * These arrays are used to map features that we should add based on x86 + * features that are present. As a large number depend on kernel features, + * rather than rechecking and clearing CPUID everywhere, we simply map these. + * There is an array of these for each hwcap word. Some features aren't tracked + * in the kernel x86 featureset and that's ok. They will not show up in here. + */ +static const av_feat_map_t x86fset_to_av1[] = { + { AV_386_CX8, X86FSET_CX8 }, + { AV_386_SEP, X86FSET_SEP }, + { AV_386_AMD_SYSC, X86FSET_ASYSC }, + { AV_386_CMOV, X86FSET_CMOV }, + { AV_386_FXSR, X86FSET_SSE }, + { AV_386_SSE, X86FSET_SSE }, + { AV_386_SSE2, X86FSET_SSE2 }, + { AV_386_SSE3, X86FSET_SSE3 }, + { AV_386_CX16, X86FSET_CX16 }, + { AV_386_TSCP, X86FSET_TSCP }, + { AV_386_AMD_SSE4A, X86FSET_SSE4A }, + { AV_386_SSSE3, X86FSET_SSSE3 }, + { AV_386_SSE4_1, X86FSET_SSE4_1 }, + { AV_386_SSE4_2, X86FSET_SSE4_2 }, + { AV_386_AES, X86FSET_AES }, + { AV_386_PCLMULQDQ, X86FSET_PCLMULQDQ }, + { AV_386_XSAVE, X86FSET_XSAVE }, + { AV_386_AVX, X86FSET_AVX }, + { AV_386_VMX, X86FSET_VMX }, + { AV_386_AMD_SVM, X86FSET_SVM } +}; + +static const av_feat_map_t x86fset_to_av2[] = { + { AV_386_2_F16C, X86FSET_F16C }, + { AV_386_2_RDRAND, X86FSET_RDRAND }, + { AV_386_2_BMI1, X86FSET_BMI1 }, + { AV_386_2_BMI2, X86FSET_BMI2 }, + { AV_386_2_FMA, X86FSET_FMA }, + { AV_386_2_AVX2, X86FSET_AVX2 }, + { AV_386_2_ADX, X86FSET_ADX }, + { AV_386_2_RDSEED, X86FSET_RDSEED }, + { AV_386_2_AVX512F, X86FSET_AVX512F }, + { AV_386_2_AVX512DQ, X86FSET_AVX512DQ }, + { AV_386_2_AVX512IFMA, X86FSET_AVX512FMA }, + { AV_386_2_AVX512PF, X86FSET_AVX512PF }, + { AV_386_2_AVX512ER, X86FSET_AVX512ER }, + { AV_386_2_AVX512CD, X86FSET_AVX512CD }, + { AV_386_2_AVX512BW, X86FSET_AVX512BW }, + { AV_386_2_AVX512VL, X86FSET_AVX512VL }, + { AV_386_2_AVX512VBMI, X86FSET_AVX512VBMI }, + { AV_386_2_AVX512VPOPCDQ, X86FSET_AVX512VPOPCDQ }, + { AV_386_2_SHA, X86FSET_SHA }, + { AV_386_2_FSGSBASE, X86FSET_FSGSBASE }, + { AV_386_2_CLFLUSHOPT, X86FSET_CLFLUSHOPT }, + { AV_386_2_CLWB, X86FSET_CLWB }, + { AV_386_2_MONITORX, X86FSET_MONITORX }, + { AV_386_2_CLZERO, X86FSET_CLZERO }, + { AV_386_2_AVX512_VNNI, X86FSET_AVX512VNNI }, + { AV_386_2_VPCLMULQDQ, X86FSET_VPCLMULQDQ }, + { AV_386_2_VAES, X86FSET_VAES }, + { AV_386_2_GFNI, X86FSET_GFNI }, + { AV_386_2_AVX512_VP2INT, X86FSET_AVX512_VP2INT }, + { AV_386_2_AVX512_BITALG, X86FSET_AVX512_BITALG } +}; + +static const av_feat_map_t x86fset_to_av3[] = { + { AV_386_3_AVX512_VBMI2, X86FSET_AVX512_VBMI2 }, + { AV_386_3_AVX512_BF16, X86FSET_AVX512_BF16 } +}; + /* * This routine is called out of bind_hwcap() much later in the life * of the kernel (post_startup()). The job of this routine is to resolve * the hardware feature support and kernel support for those features into * what we're actually going to tell applications via the aux vector. + * + * Most of the aux vector is derived from the x86_featureset array vector where + * a given feature indicates that an aux vector should be plumbed through. This + * allows the kernel to use one tracking mechanism for these based on whether or + * not it has the required hardware support (most often xsave). Most newer + * features are added there in case we need them in the kernel. Otherwise, + * features are evaluated based on looking at the cpuid features that remain. If + * you find yourself wanting to clear out cpuid features for some reason, they + * should instead be driven by the feature set so we have a consistent view. */ static void @@ -5432,65 +5525,42 @@ cpuid_pass_resolve(cpu_t *cpu, void *arg) { uint_t *hwcap_out = (uint_t *)arg; struct cpuid_info *cpi; - uint_t hwcap_flags = 0, hwcap_flags_2 = 0; + uint_t hwcap_flags = 0, hwcap_flags_2 = 0, hwcap_flags_3 = 0; cpi = cpu->cpu_m.mcpu_cpi; + for (uint_t i = 0; i < ARRAY_SIZE(x86fset_to_av1); i++) { + if (is_x86_feature(x86_featureset, + x86fset_to_av1[i].avm_feat)) { + hwcap_flags |= x86fset_to_av1[i].avm_av; + } + } + + for (uint_t i = 0; i < ARRAY_SIZE(x86fset_to_av2); i++) { + if (is_x86_feature(x86_featureset, + x86fset_to_av2[i].avm_feat)) { + hwcap_flags_2 |= x86fset_to_av2[i].avm_av; + } + } + + for (uint_t i = 0; i < ARRAY_SIZE(x86fset_to_av3); i++) { + if (is_x86_feature(x86_featureset, + x86fset_to_av3[i].avm_feat)) { + hwcap_flags_3 |= x86fset_to_av3[i].avm_av; + } + } + + /* + * From here on out we're working through features that don't have + * corresponding kernel feature flags for various reasons that are + * mostly just due to the historical implementation. + */ if (cpi->cpi_maxeax >= 1) { uint32_t *edx = &cpi->cpi_support[STD_EDX_FEATURES]; uint32_t *ecx = &cpi->cpi_support[STD_ECX_FEATURES]; - uint32_t *ebx = &cpi->cpi_support[STD_EBX_FEATURES]; *edx = CPI_FEATURES_EDX(cpi); *ecx = CPI_FEATURES_ECX(cpi); - *ebx = CPI_FEATURES_7_0_EBX(cpi); - - /* - * [these require explicit kernel support] - */ - if (!is_x86_feature(x86_featureset, X86FSET_SEP)) - *edx &= ~CPUID_INTC_EDX_SEP; - - if (!is_x86_feature(x86_featureset, X86FSET_SSE)) - *edx &= ~(CPUID_INTC_EDX_FXSR|CPUID_INTC_EDX_SSE); - if (!is_x86_feature(x86_featureset, X86FSET_SSE2)) - *edx &= ~CPUID_INTC_EDX_SSE2; - - if (!is_x86_feature(x86_featureset, X86FSET_HTT)) - *edx &= ~CPUID_INTC_EDX_HTT; - - if (!is_x86_feature(x86_featureset, X86FSET_SSE3)) - *ecx &= ~CPUID_INTC_ECX_SSE3; - - if (!is_x86_feature(x86_featureset, X86FSET_SSSE3)) - *ecx &= ~CPUID_INTC_ECX_SSSE3; - if (!is_x86_feature(x86_featureset, X86FSET_SSE4_1)) - *ecx &= ~CPUID_INTC_ECX_SSE4_1; - if (!is_x86_feature(x86_featureset, X86FSET_SSE4_2)) - *ecx &= ~CPUID_INTC_ECX_SSE4_2; - if (!is_x86_feature(x86_featureset, X86FSET_AES)) - *ecx &= ~CPUID_INTC_ECX_AES; - if (!is_x86_feature(x86_featureset, X86FSET_PCLMULQDQ)) - *ecx &= ~CPUID_INTC_ECX_PCLMULQDQ; - if (!is_x86_feature(x86_featureset, X86FSET_XSAVE)) - *ecx &= ~(CPUID_INTC_ECX_XSAVE | - CPUID_INTC_ECX_OSXSAVE); - if (!is_x86_feature(x86_featureset, X86FSET_AVX)) - *ecx &= ~CPUID_INTC_ECX_AVX; - if (!is_x86_feature(x86_featureset, X86FSET_F16C)) - *ecx &= ~CPUID_INTC_ECX_F16C; - if (!is_x86_feature(x86_featureset, X86FSET_FMA)) - *ecx &= ~CPUID_INTC_ECX_FMA; - if (!is_x86_feature(x86_featureset, X86FSET_BMI1)) - *ebx &= ~CPUID_INTC_EBX_7_0_BMI1; - if (!is_x86_feature(x86_featureset, X86FSET_BMI2)) - *ebx &= ~CPUID_INTC_EBX_7_0_BMI2; - if (!is_x86_feature(x86_featureset, X86FSET_AVX2)) - *ebx &= ~CPUID_INTC_EBX_7_0_AVX2; - if (!is_x86_feature(x86_featureset, X86FSET_RDSEED)) - *ebx &= ~CPUID_INTC_EBX_7_0_RDSEED; - if (!is_x86_feature(x86_featureset, X86FSET_ADX)) - *ebx &= ~CPUID_INTC_EBX_7_0_ADX; /* * [no explicit support required beyond x87 fp context] @@ -5502,113 +5572,17 @@ cpuid_pass_resolve(cpu_t *cpu, void *arg) * Now map the supported feature vector to things that we * think userland will care about. */ - if (*edx & CPUID_INTC_EDX_SEP) - hwcap_flags |= AV_386_SEP; - if (*edx & CPUID_INTC_EDX_SSE) - hwcap_flags |= AV_386_FXSR | AV_386_SSE; - if (*edx & CPUID_INTC_EDX_SSE2) - hwcap_flags |= AV_386_SSE2; - if (*ecx & CPUID_INTC_ECX_SSE3) - hwcap_flags |= AV_386_SSE3; - if (*ecx & CPUID_INTC_ECX_SSSE3) - hwcap_flags |= AV_386_SSSE3; - if (*ecx & CPUID_INTC_ECX_SSE4_1) - hwcap_flags |= AV_386_SSE4_1; - if (*ecx & CPUID_INTC_ECX_SSE4_2) - hwcap_flags |= AV_386_SSE4_2; if (*ecx & CPUID_INTC_ECX_MOVBE) hwcap_flags |= AV_386_MOVBE; - if (*ecx & CPUID_INTC_ECX_AES) - hwcap_flags |= AV_386_AES; - if (*ecx & CPUID_INTC_ECX_PCLMULQDQ) - hwcap_flags |= AV_386_PCLMULQDQ; - if ((*ecx & CPUID_INTC_ECX_XSAVE) && - (*ecx & CPUID_INTC_ECX_OSXSAVE)) { - hwcap_flags |= AV_386_XSAVE; - - if (*ecx & CPUID_INTC_ECX_AVX) { - uint32_t *ecx_7 = &CPI_FEATURES_7_0_ECX(cpi); - uint32_t *edx_7 = &CPI_FEATURES_7_0_EDX(cpi); - - hwcap_flags |= AV_386_AVX; - if (*ecx & CPUID_INTC_ECX_F16C) - hwcap_flags_2 |= AV_386_2_F16C; - if (*ecx & CPUID_INTC_ECX_FMA) - hwcap_flags_2 |= AV_386_2_FMA; - - if (*ebx & CPUID_INTC_EBX_7_0_BMI1) - hwcap_flags_2 |= AV_386_2_BMI1; - if (*ebx & CPUID_INTC_EBX_7_0_BMI2) - hwcap_flags_2 |= AV_386_2_BMI2; - if (*ebx & CPUID_INTC_EBX_7_0_AVX2) - hwcap_flags_2 |= AV_386_2_AVX2; - if (*ebx & CPUID_INTC_EBX_7_0_AVX512F) - hwcap_flags_2 |= AV_386_2_AVX512F; - if (*ebx & CPUID_INTC_EBX_7_0_AVX512DQ) - hwcap_flags_2 |= AV_386_2_AVX512DQ; - if (*ebx & CPUID_INTC_EBX_7_0_AVX512IFMA) - hwcap_flags_2 |= AV_386_2_AVX512IFMA; - if (*ebx & CPUID_INTC_EBX_7_0_AVX512PF) - hwcap_flags_2 |= AV_386_2_AVX512PF; - if (*ebx & CPUID_INTC_EBX_7_0_AVX512ER) - hwcap_flags_2 |= AV_386_2_AVX512ER; - if (*ebx & CPUID_INTC_EBX_7_0_AVX512CD) - hwcap_flags_2 |= AV_386_2_AVX512CD; - if (*ebx & CPUID_INTC_EBX_7_0_AVX512BW) - hwcap_flags_2 |= AV_386_2_AVX512BW; - if (*ebx & CPUID_INTC_EBX_7_0_AVX512VL) - hwcap_flags_2 |= AV_386_2_AVX512VL; - - if (*ecx_7 & CPUID_INTC_ECX_7_0_AVX512VBMI) - hwcap_flags_2 |= AV_386_2_AVX512VBMI; - if (*ecx_7 & CPUID_INTC_ECX_7_0_AVX512VNNI) - hwcap_flags_2 |= AV_386_2_AVX512_VNNI; - if (*ecx_7 & CPUID_INTC_ECX_7_0_AVX512VPOPCDQ) - hwcap_flags_2 |= AV_386_2_AVX512VPOPCDQ; - if (*ecx_7 & CPUID_INTC_ECX_7_0_VAES) - hwcap_flags_2 |= AV_386_2_VAES; - if (*ecx_7 & CPUID_INTC_ECX_7_0_VPCLMULQDQ) - hwcap_flags_2 |= AV_386_2_VPCLMULQDQ; - - if (*edx_7 & CPUID_INTC_EDX_7_0_AVX5124NNIW) - hwcap_flags_2 |= AV_386_2_AVX512_4NNIW; - if (*edx_7 & CPUID_INTC_EDX_7_0_AVX5124FMAPS) - hwcap_flags_2 |= AV_386_2_AVX512_4FMAPS; - } - } - if (*ecx & CPUID_INTC_ECX_VMX) - hwcap_flags |= AV_386_VMX; + if (*ecx & CPUID_INTC_ECX_POPCNT) hwcap_flags |= AV_386_POPCNT; if (*edx & CPUID_INTC_EDX_FPU) hwcap_flags |= AV_386_FPU; if (*edx & CPUID_INTC_EDX_MMX) hwcap_flags |= AV_386_MMX; - if (*edx & CPUID_INTC_EDX_TSC) hwcap_flags |= AV_386_TSC; - if (*edx & CPUID_INTC_EDX_CX8) - hwcap_flags |= AV_386_CX8; - if (*edx & CPUID_INTC_EDX_CMOV) - hwcap_flags |= AV_386_CMOV; - if (*ecx & CPUID_INTC_ECX_CX16) - hwcap_flags |= AV_386_CX16; - - if (*ecx & CPUID_INTC_ECX_RDRAND) - hwcap_flags_2 |= AV_386_2_RDRAND; - if (*ebx & CPUID_INTC_EBX_7_0_ADX) - hwcap_flags_2 |= AV_386_2_ADX; - if (*ebx & CPUID_INTC_EBX_7_0_RDSEED) - hwcap_flags_2 |= AV_386_2_RDSEED; - if (*ebx & CPUID_INTC_EBX_7_0_SHA) - hwcap_flags_2 |= AV_386_2_SHA; - if (*ebx & CPUID_INTC_EBX_7_0_FSGSBASE) - hwcap_flags_2 |= AV_386_2_FSGSBASE; - if (*ebx & CPUID_INTC_EBX_7_0_CLWB) - hwcap_flags_2 |= AV_386_2_CLWB; - if (*ebx & CPUID_INTC_EBX_7_0_CLFLUSHOPT) - hwcap_flags_2 |= AV_386_2_CLFLUSHOPT; - } /* Detect systems with a potential CPUID limit */ @@ -5620,14 +5594,10 @@ cpuid_pass_resolve(cpu_t *cpu, void *arg) /* * Check a few miscellaneous features. */ - if (is_x86_feature(x86_featureset, X86FSET_CLZERO)) - hwcap_flags_2 |= AV_386_2_CLZERO; - if (cpi->cpi_xmaxeax < 0x80000001) goto resolve_done; switch (cpi->cpi_vendor) { - struct cpuid_regs cp; uint32_t *edx, *ecx; case X86_VENDOR_Intel: @@ -5648,27 +5618,6 @@ cpuid_pass_resolve(cpu_t *cpu, void *arg) *ecx = CPI_FEATURES_XTD_ECX(cpi); /* - * [these features require explicit kernel support] - */ - switch (cpi->cpi_vendor) { - case X86_VENDOR_Intel: - if (!is_x86_feature(x86_featureset, X86FSET_TSCP)) - *edx &= ~CPUID_AMD_EDX_TSCP; - break; - - case X86_VENDOR_AMD: - case X86_VENDOR_HYGON: - if (!is_x86_feature(x86_featureset, X86FSET_TSCP)) - *edx &= ~CPUID_AMD_EDX_TSCP; - if (!is_x86_feature(x86_featureset, X86FSET_SSE4A)) - *ecx &= ~CPUID_AMD_ECX_SSE4A; - break; - - default: - break; - } - - /* * [no explicit support required beyond * x87 fp context and exception handlers] */ @@ -5676,41 +5625,27 @@ cpuid_pass_resolve(cpu_t *cpu, void *arg) *edx &= ~(CPUID_AMD_EDX_MMXamd | CPUID_AMD_EDX_3DNow | CPUID_AMD_EDX_3DNowx); - if (!is_x86_feature(x86_featureset, X86FSET_NX)) - *edx &= ~CPUID_AMD_EDX_NX; /* * Now map the supported feature vector to * things that we think userland will care about. */ - if (*edx & CPUID_AMD_EDX_SYSC) - hwcap_flags |= AV_386_AMD_SYSC; if (*edx & CPUID_AMD_EDX_MMXamd) hwcap_flags |= AV_386_AMD_MMX; if (*edx & CPUID_AMD_EDX_3DNow) hwcap_flags |= AV_386_AMD_3DNow; if (*edx & CPUID_AMD_EDX_3DNowx) hwcap_flags |= AV_386_AMD_3DNowx; - if (*ecx & CPUID_AMD_ECX_SVM) - hwcap_flags |= AV_386_AMD_SVM; switch (cpi->cpi_vendor) { case X86_VENDOR_AMD: case X86_VENDOR_HYGON: - if (*edx & CPUID_AMD_EDX_TSCP) - hwcap_flags |= AV_386_TSCP; if (*ecx & CPUID_AMD_ECX_AHF64) hwcap_flags |= AV_386_AHF; - if (*ecx & CPUID_AMD_ECX_SSE4A) - hwcap_flags |= AV_386_AMD_SSE4A; if (*ecx & CPUID_AMD_ECX_LZCNT) hwcap_flags |= AV_386_AMD_LZCNT; - if (*ecx & CPUID_AMD_ECX_MONITORX) - hwcap_flags_2 |= AV_386_2_MONITORX; break; case X86_VENDOR_Intel: - if (*edx & CPUID_AMD_EDX_TSCP) - hwcap_flags |= AV_386_TSCP; if (*ecx & CPUID_AMD_ECX_LZCNT) hwcap_flags |= AV_386_AMD_LZCNT; /* @@ -5720,18 +5655,11 @@ cpuid_pass_resolve(cpu_t *cpu, void *arg) if (*ecx & CPUID_INTC_ECX_AHF64) hwcap_flags |= AV_386_AHF; break; - default: break; } break; - case X86_VENDOR_TM: - cp.cp_eax = 0x80860001; - (void) __cpuid_insn(&cp); - cpi->cpi_support[TM_EDX_FEATURES] = cp.cp_edx; - break; - default: break; } @@ -5740,6 +5668,7 @@ resolve_done: if (hwcap_out != NULL) { hwcap_out[0] = hwcap_flags; hwcap_out[1] = hwcap_flags_2; + hwcap_out[2] = hwcap_flags_3; } } |
