1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2015 Intel Corporation 3 */ 4 5 #include "rte_cpuflags.h" 6 7 #include <stdio.h> 8 #include <errno.h> 9 #include <stdint.h> 10 #include <string.h> 11 #include <stdbool.h> 12 13 #include "rte_cpuid.h" 14 #include "rte_atomic.h" 15 16 /** 17 * Struct to hold a processor feature entry 18 */ 19 struct feature_entry { 20 uint32_t leaf; /**< cpuid leaf */ 21 uint32_t subleaf; /**< cpuid subleaf */ 22 uint32_t reg; /**< cpuid register */ 23 uint32_t bit; /**< cpuid register bit */ 24 #define CPU_FLAG_NAME_MAX_LEN 64 25 char name[CPU_FLAG_NAME_MAX_LEN]; /**< String for printing */ 26 bool has_value; 27 bool value; 28 }; 29 30 #define FEAT_DEF(name, leaf, subleaf, reg, bit) \ 31 [RTE_CPUFLAG_##name] = {leaf, subleaf, reg, bit, #name }, 32 33 struct feature_entry rte_cpu_feature_table[] = { 34 FEAT_DEF(SSE3, 0x00000001, 0, RTE_REG_ECX, 0) 35 FEAT_DEF(PCLMULQDQ, 0x00000001, 0, RTE_REG_ECX, 1) 36 FEAT_DEF(DTES64, 0x00000001, 0, RTE_REG_ECX, 2) 37 FEAT_DEF(MONITOR, 0x00000001, 0, RTE_REG_ECX, 3) 38 FEAT_DEF(DS_CPL, 0x00000001, 0, RTE_REG_ECX, 4) 39 FEAT_DEF(VMX, 0x00000001, 0, RTE_REG_ECX, 5) 40 FEAT_DEF(SMX, 0x00000001, 0, RTE_REG_ECX, 6) 41 FEAT_DEF(EIST, 0x00000001, 0, RTE_REG_ECX, 7) 42 FEAT_DEF(TM2, 0x00000001, 0, RTE_REG_ECX, 8) 43 FEAT_DEF(SSSE3, 0x00000001, 0, RTE_REG_ECX, 9) 44 FEAT_DEF(CNXT_ID, 0x00000001, 0, RTE_REG_ECX, 10) 45 FEAT_DEF(FMA, 0x00000001, 0, RTE_REG_ECX, 12) 46 FEAT_DEF(CMPXCHG16B, 0x00000001, 0, RTE_REG_ECX, 13) 47 FEAT_DEF(XTPR, 0x00000001, 0, RTE_REG_ECX, 14) 48 FEAT_DEF(PDCM, 0x00000001, 0, RTE_REG_ECX, 15) 49 FEAT_DEF(PCID, 0x00000001, 0, RTE_REG_ECX, 17) 50 FEAT_DEF(DCA, 0x00000001, 0, RTE_REG_ECX, 18) 51 FEAT_DEF(SSE4_1, 0x00000001, 0, RTE_REG_ECX, 19) 52 FEAT_DEF(SSE4_2, 0x00000001, 0, RTE_REG_ECX, 20) 53 FEAT_DEF(X2APIC, 0x00000001, 0, RTE_REG_ECX, 21) 54 FEAT_DEF(MOVBE, 0x00000001, 0, RTE_REG_ECX, 22) 55 FEAT_DEF(POPCNT, 0x00000001, 0, RTE_REG_ECX, 23) 56 FEAT_DEF(TSC_DEADLINE, 0x00000001, 0, RTE_REG_ECX, 24) 57 FEAT_DEF(AES, 0x00000001, 0, RTE_REG_ECX, 25) 58 FEAT_DEF(XSAVE, 0x00000001, 0, RTE_REG_ECX, 26) 59 FEAT_DEF(OSXSAVE, 0x00000001, 0, RTE_REG_ECX, 27) 60 FEAT_DEF(AVX, 0x00000001, 0, RTE_REG_ECX, 28) 61 FEAT_DEF(F16C, 0x00000001, 0, RTE_REG_ECX, 29) 62 FEAT_DEF(RDRAND, 0x00000001, 0, RTE_REG_ECX, 30) 63 FEAT_DEF(HYPERVISOR, 0x00000001, 0, RTE_REG_ECX, 31) 64 65 FEAT_DEF(FPU, 0x00000001, 0, RTE_REG_EDX, 0) 66 FEAT_DEF(VME, 0x00000001, 0, RTE_REG_EDX, 1) 67 FEAT_DEF(DE, 0x00000001, 0, RTE_REG_EDX, 2) 68 FEAT_DEF(PSE, 0x00000001, 0, RTE_REG_EDX, 3) 69 FEAT_DEF(TSC, 0x00000001, 0, RTE_REG_EDX, 4) 70 FEAT_DEF(MSR, 0x00000001, 0, RTE_REG_EDX, 5) 71 FEAT_DEF(PAE, 0x00000001, 0, RTE_REG_EDX, 6) 72 FEAT_DEF(MCE, 0x00000001, 0, RTE_REG_EDX, 7) 73 FEAT_DEF(CX8, 0x00000001, 0, RTE_REG_EDX, 8) 74 FEAT_DEF(APIC, 0x00000001, 0, RTE_REG_EDX, 9) 75 FEAT_DEF(SEP, 0x00000001, 0, RTE_REG_EDX, 11) 76 FEAT_DEF(MTRR, 0x00000001, 0, RTE_REG_EDX, 12) 77 FEAT_DEF(PGE, 0x00000001, 0, RTE_REG_EDX, 13) 78 FEAT_DEF(MCA, 0x00000001, 0, RTE_REG_EDX, 14) 79 FEAT_DEF(CMOV, 0x00000001, 0, RTE_REG_EDX, 15) 80 FEAT_DEF(PAT, 0x00000001, 0, RTE_REG_EDX, 16) 81 FEAT_DEF(PSE36, 0x00000001, 0, RTE_REG_EDX, 17) 82 FEAT_DEF(PSN, 0x00000001, 0, RTE_REG_EDX, 18) 83 FEAT_DEF(CLFSH, 0x00000001, 0, RTE_REG_EDX, 19) 84 FEAT_DEF(DS, 0x00000001, 0, RTE_REG_EDX, 21) 85 FEAT_DEF(ACPI, 0x00000001, 0, RTE_REG_EDX, 22) 86 FEAT_DEF(MMX, 0x00000001, 0, RTE_REG_EDX, 23) 87 FEAT_DEF(FXSR, 0x00000001, 0, RTE_REG_EDX, 24) 88 FEAT_DEF(SSE, 0x00000001, 0, RTE_REG_EDX, 25) 89 FEAT_DEF(SSE2, 0x00000001, 0, RTE_REG_EDX, 26) 90 FEAT_DEF(SS, 0x00000001, 0, RTE_REG_EDX, 27) 91 FEAT_DEF(HTT, 0x00000001, 0, RTE_REG_EDX, 28) 92 FEAT_DEF(TM, 0x00000001, 0, RTE_REG_EDX, 29) 93 FEAT_DEF(PBE, 0x00000001, 0, RTE_REG_EDX, 31) 94 95 FEAT_DEF(DIGTEMP, 0x00000006, 0, RTE_REG_EAX, 0) 96 FEAT_DEF(TRBOBST, 0x00000006, 0, RTE_REG_EAX, 1) 97 FEAT_DEF(ARAT, 0x00000006, 0, RTE_REG_EAX, 2) 98 FEAT_DEF(PLN, 0x00000006, 0, RTE_REG_EAX, 4) 99 FEAT_DEF(ECMD, 0x00000006, 0, RTE_REG_EAX, 5) 100 FEAT_DEF(PTM, 0x00000006, 0, RTE_REG_EAX, 6) 101 102 FEAT_DEF(MPERF_APERF_MSR, 0x00000006, 0, RTE_REG_ECX, 0) 103 FEAT_DEF(ACNT2, 0x00000006, 0, RTE_REG_ECX, 1) 104 FEAT_DEF(ENERGY_EFF, 0x00000006, 0, RTE_REG_ECX, 3) 105 106 FEAT_DEF(FSGSBASE, 0x00000007, 0, RTE_REG_EBX, 0) 107 FEAT_DEF(BMI1, 0x00000007, 0, RTE_REG_EBX, 3) 108 FEAT_DEF(HLE, 0x00000007, 0, RTE_REG_EBX, 4) 109 FEAT_DEF(AVX2, 0x00000007, 0, RTE_REG_EBX, 5) 110 FEAT_DEF(SMEP, 0x00000007, 0, RTE_REG_EBX, 7) 111 FEAT_DEF(BMI2, 0x00000007, 0, RTE_REG_EBX, 8) 112 FEAT_DEF(ERMS, 0x00000007, 0, RTE_REG_EBX, 9) 113 FEAT_DEF(INVPCID, 0x00000007, 0, RTE_REG_EBX, 10) 114 FEAT_DEF(RTM, 0x00000007, 0, RTE_REG_EBX, 11) 115 FEAT_DEF(AVX512F, 0x00000007, 0, RTE_REG_EBX, 16) 116 FEAT_DEF(AVX512DQ, 0x00000007, 0, RTE_REG_EBX, 17) 117 FEAT_DEF(RDSEED, 0x00000007, 0, RTE_REG_EBX, 18) 118 FEAT_DEF(AVX512IFMA, 0x00000007, 0, RTE_REG_EBX, 21) 119 FEAT_DEF(AVX512CD, 0x00000007, 0, RTE_REG_EBX, 28) 120 FEAT_DEF(AVX512BW, 0x00000007, 0, RTE_REG_EBX, 30) 121 FEAT_DEF(AVX512VL, 0x00000007, 0, RTE_REG_EBX, 31) 122 123 FEAT_DEF(AVX512VBMI, 0x00000007, 0, RTE_REG_ECX, 1) 124 FEAT_DEF(WAITPKG, 0x00000007, 0, RTE_REG_ECX, 5) 125 FEAT_DEF(AVX512VBMI2, 0x00000007, 0, RTE_REG_ECX, 6) 126 FEAT_DEF(GFNI, 0x00000007, 0, RTE_REG_ECX, 8) 127 FEAT_DEF(VAES, 0x00000007, 0, RTE_REG_ECX, 9) 128 FEAT_DEF(VPCLMULQDQ, 0x00000007, 0, RTE_REG_ECX, 10) 129 FEAT_DEF(AVX512VNNI, 0x00000007, 0, RTE_REG_ECX, 11) 130 FEAT_DEF(AVX512BITALG, 0x00000007, 0, RTE_REG_ECX, 12) 131 FEAT_DEF(AVX512VPOPCNTDQ, 0x00000007, 0, RTE_REG_ECX, 14) 132 FEAT_DEF(CLDEMOTE, 0x00000007, 0, RTE_REG_ECX, 25) 133 FEAT_DEF(MOVDIRI, 0x00000007, 0, RTE_REG_ECX, 27) 134 FEAT_DEF(MOVDIR64B, 0x00000007, 0, RTE_REG_ECX, 28) 135 136 FEAT_DEF(AVX512VP2INTERSECT, 0x00000007, 0, RTE_REG_EDX, 8) 137 138 FEAT_DEF(LAHF_SAHF, 0x80000001, 0, RTE_REG_ECX, 0) 139 FEAT_DEF(LZCNT, 0x80000001, 0, RTE_REG_ECX, 4) 140 FEAT_DEF(MONITORX, 0x80000001, 0, RTE_REG_ECX, 29) 141 142 FEAT_DEF(SYSCALL, 0x80000001, 0, RTE_REG_EDX, 11) 143 FEAT_DEF(XD, 0x80000001, 0, RTE_REG_EDX, 20) 144 FEAT_DEF(1GB_PG, 0x80000001, 0, RTE_REG_EDX, 26) 145 FEAT_DEF(RDTSCP, 0x80000001, 0, RTE_REG_EDX, 27) 146 FEAT_DEF(EM64T, 0x80000001, 0, RTE_REG_EDX, 29) 147 148 FEAT_DEF(INVTSC, 0x80000007, 0, RTE_REG_EDX, 8) 149 }; 150 151 int 152 rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature) 153 { 154 struct feature_entry *feat; 155 cpuid_registers_t regs; 156 unsigned int maxleaf; 157 158 if ((unsigned int)feature >= RTE_DIM(rte_cpu_feature_table)) 159 /* Flag does not match anything in the feature tables */ 160 return -ENOENT; 161 162 feat = &rte_cpu_feature_table[feature]; 163 if (feat->has_value) 164 return feat->value; 165 166 if (!feat->leaf) 167 /* This entry in the table wasn't filled out! */ 168 return -EFAULT; 169 170 maxleaf = __get_cpuid_max(feat->leaf & 0x80000000, NULL); 171 172 if (maxleaf < feat->leaf) { 173 feat->value = 0; 174 goto out; 175 } 176 177 #ifdef RTE_TOOLCHAIN_MSVC 178 __cpuidex(regs, feat->leaf, feat->subleaf); 179 #else 180 __cpuid_count(feat->leaf, feat->subleaf, 181 regs[RTE_REG_EAX], regs[RTE_REG_EBX], 182 regs[RTE_REG_ECX], regs[RTE_REG_EDX]); 183 #endif 184 185 /* check if the feature is enabled */ 186 feat->value = (regs[feat->reg] >> feat->bit) & 1; 187 out: 188 rte_compiler_barrier(); 189 feat->has_value = true; 190 return feat->value; 191 } 192 193 const char * 194 rte_cpu_get_flag_name(enum rte_cpu_flag_t feature) 195 { 196 if ((unsigned int)feature >= RTE_DIM(rte_cpu_feature_table)) 197 return NULL; 198 return rte_cpu_feature_table[feature].name; 199 } 200 201 void 202 rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics) 203 { 204 memset(intrinsics, 0, sizeof(*intrinsics)); 205 206 if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_WAITPKG)) { 207 intrinsics->power_monitor = 1; 208 intrinsics->power_pause = 1; 209 if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_RTM)) 210 intrinsics->power_monitor_multi = 1; 211 } else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_MONITORX)) { 212 intrinsics->power_monitor = 1; 213 } 214 } 215