xref: /dpdk/lib/eal/x86/rte_cpuflags.c (revision 4225db8dc0fa83c9ba1247ac5aec54ab7f3f8d94)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2010-2015 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #include "rte_cpuflags.h"
699a2dd95SBruce Richardson 
799a2dd95SBruce Richardson #include <stdio.h>
899a2dd95SBruce Richardson #include <errno.h>
999a2dd95SBruce Richardson #include <stdint.h>
1099a2dd95SBruce Richardson #include <string.h>
11*4225db8dSBruce Richardson #include <stdbool.h>
1299a2dd95SBruce Richardson 
1399a2dd95SBruce Richardson #include "rte_cpuid.h"
14*4225db8dSBruce Richardson #include "rte_atomic.h"
1599a2dd95SBruce Richardson 
1699a2dd95SBruce Richardson /**
1799a2dd95SBruce Richardson  * Struct to hold a processor feature entry
1899a2dd95SBruce Richardson  */
1999a2dd95SBruce Richardson struct feature_entry {
2099a2dd95SBruce Richardson 	uint32_t leaf;				/**< cpuid leaf */
2199a2dd95SBruce Richardson 	uint32_t subleaf;			/**< cpuid subleaf */
2299a2dd95SBruce Richardson 	uint32_t reg;				/**< cpuid register */
2399a2dd95SBruce Richardson 	uint32_t bit;				/**< cpuid register bit */
2499a2dd95SBruce Richardson #define CPU_FLAG_NAME_MAX_LEN 64
2599a2dd95SBruce Richardson 	char name[CPU_FLAG_NAME_MAX_LEN];       /**< String for printing */
26*4225db8dSBruce Richardson 	bool has_value;
27*4225db8dSBruce Richardson 	bool value;
2899a2dd95SBruce Richardson };
2999a2dd95SBruce Richardson 
3099a2dd95SBruce Richardson #define FEAT_DEF(name, leaf, subleaf, reg, bit) \
3199a2dd95SBruce Richardson 	[RTE_CPUFLAG_##name] = {leaf, subleaf, reg, bit, #name },
3299a2dd95SBruce Richardson 
33*4225db8dSBruce Richardson struct feature_entry rte_cpu_feature_table[] = {
3499a2dd95SBruce Richardson 	FEAT_DEF(SSE3, 0x00000001, 0, RTE_REG_ECX,  0)
3599a2dd95SBruce Richardson 	FEAT_DEF(PCLMULQDQ, 0x00000001, 0, RTE_REG_ECX,  1)
3699a2dd95SBruce Richardson 	FEAT_DEF(DTES64, 0x00000001, 0, RTE_REG_ECX,  2)
3799a2dd95SBruce Richardson 	FEAT_DEF(MONITOR, 0x00000001, 0, RTE_REG_ECX,  3)
3899a2dd95SBruce Richardson 	FEAT_DEF(DS_CPL, 0x00000001, 0, RTE_REG_ECX,  4)
3999a2dd95SBruce Richardson 	FEAT_DEF(VMX, 0x00000001, 0, RTE_REG_ECX,  5)
4099a2dd95SBruce Richardson 	FEAT_DEF(SMX, 0x00000001, 0, RTE_REG_ECX,  6)
4199a2dd95SBruce Richardson 	FEAT_DEF(EIST, 0x00000001, 0, RTE_REG_ECX,  7)
4299a2dd95SBruce Richardson 	FEAT_DEF(TM2, 0x00000001, 0, RTE_REG_ECX,  8)
4399a2dd95SBruce Richardson 	FEAT_DEF(SSSE3, 0x00000001, 0, RTE_REG_ECX,  9)
4499a2dd95SBruce Richardson 	FEAT_DEF(CNXT_ID, 0x00000001, 0, RTE_REG_ECX, 10)
4599a2dd95SBruce Richardson 	FEAT_DEF(FMA, 0x00000001, 0, RTE_REG_ECX, 12)
4699a2dd95SBruce Richardson 	FEAT_DEF(CMPXCHG16B, 0x00000001, 0, RTE_REG_ECX, 13)
4799a2dd95SBruce Richardson 	FEAT_DEF(XTPR, 0x00000001, 0, RTE_REG_ECX, 14)
4899a2dd95SBruce Richardson 	FEAT_DEF(PDCM, 0x00000001, 0, RTE_REG_ECX, 15)
4999a2dd95SBruce Richardson 	FEAT_DEF(PCID, 0x00000001, 0, RTE_REG_ECX, 17)
5099a2dd95SBruce Richardson 	FEAT_DEF(DCA, 0x00000001, 0, RTE_REG_ECX, 18)
5199a2dd95SBruce Richardson 	FEAT_DEF(SSE4_1, 0x00000001, 0, RTE_REG_ECX, 19)
5299a2dd95SBruce Richardson 	FEAT_DEF(SSE4_2, 0x00000001, 0, RTE_REG_ECX, 20)
5399a2dd95SBruce Richardson 	FEAT_DEF(X2APIC, 0x00000001, 0, RTE_REG_ECX, 21)
5499a2dd95SBruce Richardson 	FEAT_DEF(MOVBE, 0x00000001, 0, RTE_REG_ECX, 22)
5599a2dd95SBruce Richardson 	FEAT_DEF(POPCNT, 0x00000001, 0, RTE_REG_ECX, 23)
5699a2dd95SBruce Richardson 	FEAT_DEF(TSC_DEADLINE, 0x00000001, 0, RTE_REG_ECX, 24)
5799a2dd95SBruce Richardson 	FEAT_DEF(AES, 0x00000001, 0, RTE_REG_ECX, 25)
5899a2dd95SBruce Richardson 	FEAT_DEF(XSAVE, 0x00000001, 0, RTE_REG_ECX, 26)
5999a2dd95SBruce Richardson 	FEAT_DEF(OSXSAVE, 0x00000001, 0, RTE_REG_ECX, 27)
6099a2dd95SBruce Richardson 	FEAT_DEF(AVX, 0x00000001, 0, RTE_REG_ECX, 28)
6199a2dd95SBruce Richardson 	FEAT_DEF(F16C, 0x00000001, 0, RTE_REG_ECX, 29)
6299a2dd95SBruce Richardson 	FEAT_DEF(RDRAND, 0x00000001, 0, RTE_REG_ECX, 30)
6399a2dd95SBruce Richardson 	FEAT_DEF(HYPERVISOR, 0x00000001, 0, RTE_REG_ECX, 31)
6499a2dd95SBruce Richardson 
6599a2dd95SBruce Richardson 	FEAT_DEF(FPU, 0x00000001, 0, RTE_REG_EDX,  0)
6699a2dd95SBruce Richardson 	FEAT_DEF(VME, 0x00000001, 0, RTE_REG_EDX,  1)
6799a2dd95SBruce Richardson 	FEAT_DEF(DE, 0x00000001, 0, RTE_REG_EDX,  2)
6899a2dd95SBruce Richardson 	FEAT_DEF(PSE, 0x00000001, 0, RTE_REG_EDX,  3)
6999a2dd95SBruce Richardson 	FEAT_DEF(TSC, 0x00000001, 0, RTE_REG_EDX,  4)
7099a2dd95SBruce Richardson 	FEAT_DEF(MSR, 0x00000001, 0, RTE_REG_EDX,  5)
7199a2dd95SBruce Richardson 	FEAT_DEF(PAE, 0x00000001, 0, RTE_REG_EDX,  6)
7299a2dd95SBruce Richardson 	FEAT_DEF(MCE, 0x00000001, 0, RTE_REG_EDX,  7)
7399a2dd95SBruce Richardson 	FEAT_DEF(CX8, 0x00000001, 0, RTE_REG_EDX,  8)
7499a2dd95SBruce Richardson 	FEAT_DEF(APIC, 0x00000001, 0, RTE_REG_EDX,  9)
7599a2dd95SBruce Richardson 	FEAT_DEF(SEP, 0x00000001, 0, RTE_REG_EDX, 11)
7699a2dd95SBruce Richardson 	FEAT_DEF(MTRR, 0x00000001, 0, RTE_REG_EDX, 12)
7799a2dd95SBruce Richardson 	FEAT_DEF(PGE, 0x00000001, 0, RTE_REG_EDX, 13)
7899a2dd95SBruce Richardson 	FEAT_DEF(MCA, 0x00000001, 0, RTE_REG_EDX, 14)
7999a2dd95SBruce Richardson 	FEAT_DEF(CMOV, 0x00000001, 0, RTE_REG_EDX, 15)
8099a2dd95SBruce Richardson 	FEAT_DEF(PAT, 0x00000001, 0, RTE_REG_EDX, 16)
8199a2dd95SBruce Richardson 	FEAT_DEF(PSE36, 0x00000001, 0, RTE_REG_EDX, 17)
8299a2dd95SBruce Richardson 	FEAT_DEF(PSN, 0x00000001, 0, RTE_REG_EDX, 18)
8399a2dd95SBruce Richardson 	FEAT_DEF(CLFSH, 0x00000001, 0, RTE_REG_EDX, 19)
8499a2dd95SBruce Richardson 	FEAT_DEF(DS, 0x00000001, 0, RTE_REG_EDX, 21)
8599a2dd95SBruce Richardson 	FEAT_DEF(ACPI, 0x00000001, 0, RTE_REG_EDX, 22)
8699a2dd95SBruce Richardson 	FEAT_DEF(MMX, 0x00000001, 0, RTE_REG_EDX, 23)
8799a2dd95SBruce Richardson 	FEAT_DEF(FXSR, 0x00000001, 0, RTE_REG_EDX, 24)
8899a2dd95SBruce Richardson 	FEAT_DEF(SSE, 0x00000001, 0, RTE_REG_EDX, 25)
8999a2dd95SBruce Richardson 	FEAT_DEF(SSE2, 0x00000001, 0, RTE_REG_EDX, 26)
9099a2dd95SBruce Richardson 	FEAT_DEF(SS, 0x00000001, 0, RTE_REG_EDX, 27)
9199a2dd95SBruce Richardson 	FEAT_DEF(HTT, 0x00000001, 0, RTE_REG_EDX, 28)
9299a2dd95SBruce Richardson 	FEAT_DEF(TM, 0x00000001, 0, RTE_REG_EDX, 29)
9399a2dd95SBruce Richardson 	FEAT_DEF(PBE, 0x00000001, 0, RTE_REG_EDX, 31)
9499a2dd95SBruce Richardson 
9599a2dd95SBruce Richardson 	FEAT_DEF(DIGTEMP, 0x00000006, 0, RTE_REG_EAX,  0)
9699a2dd95SBruce Richardson 	FEAT_DEF(TRBOBST, 0x00000006, 0, RTE_REG_EAX,  1)
9799a2dd95SBruce Richardson 	FEAT_DEF(ARAT, 0x00000006, 0, RTE_REG_EAX,  2)
9899a2dd95SBruce Richardson 	FEAT_DEF(PLN, 0x00000006, 0, RTE_REG_EAX,  4)
9999a2dd95SBruce Richardson 	FEAT_DEF(ECMD, 0x00000006, 0, RTE_REG_EAX,  5)
10099a2dd95SBruce Richardson 	FEAT_DEF(PTM, 0x00000006, 0, RTE_REG_EAX,  6)
10199a2dd95SBruce Richardson 
10299a2dd95SBruce Richardson 	FEAT_DEF(MPERF_APERF_MSR, 0x00000006, 0, RTE_REG_ECX,  0)
10399a2dd95SBruce Richardson 	FEAT_DEF(ACNT2, 0x00000006, 0, RTE_REG_ECX,  1)
10499a2dd95SBruce Richardson 	FEAT_DEF(ENERGY_EFF, 0x00000006, 0, RTE_REG_ECX,  3)
10599a2dd95SBruce Richardson 
10699a2dd95SBruce Richardson 	FEAT_DEF(FSGSBASE, 0x00000007, 0, RTE_REG_EBX,  0)
107aae3037aSDavid Marchand 	FEAT_DEF(BMI1, 0x00000007, 0, RTE_REG_EBX,  3)
10899a2dd95SBruce Richardson 	FEAT_DEF(HLE, 0x00000007, 0, RTE_REG_EBX,  4)
10999a2dd95SBruce Richardson 	FEAT_DEF(AVX2, 0x00000007, 0, RTE_REG_EBX,  5)
110aae3037aSDavid Marchand 	FEAT_DEF(SMEP, 0x00000007, 0, RTE_REG_EBX,  7)
111aae3037aSDavid Marchand 	FEAT_DEF(BMI2, 0x00000007, 0, RTE_REG_EBX,  8)
112aae3037aSDavid Marchand 	FEAT_DEF(ERMS, 0x00000007, 0, RTE_REG_EBX,  9)
11399a2dd95SBruce Richardson 	FEAT_DEF(INVPCID, 0x00000007, 0, RTE_REG_EBX, 10)
11499a2dd95SBruce Richardson 	FEAT_DEF(RTM, 0x00000007, 0, RTE_REG_EBX, 11)
11599a2dd95SBruce Richardson 	FEAT_DEF(AVX512F, 0x00000007, 0, RTE_REG_EBX, 16)
1162f375875SDavid Marchand 	FEAT_DEF(AVX512DQ, 0x00000007, 0, RTE_REG_EBX, 17)
11799a2dd95SBruce Richardson 	FEAT_DEF(RDSEED, 0x00000007, 0, RTE_REG_EBX, 18)
1182f375875SDavid Marchand 	FEAT_DEF(AVX512IFMA, 0x00000007, 0, RTE_REG_EBX, 21)
1192f375875SDavid Marchand 	FEAT_DEF(AVX512CD, 0x00000007, 0, RTE_REG_EBX, 28)
1202f375875SDavid Marchand 	FEAT_DEF(AVX512BW, 0x00000007, 0, RTE_REG_EBX, 30)
1212f375875SDavid Marchand 	FEAT_DEF(AVX512VL, 0x00000007, 0, RTE_REG_EBX, 31)
12299a2dd95SBruce Richardson 
1232f375875SDavid Marchand 	FEAT_DEF(AVX512VBMI, 0x00000007, 0, RTE_REG_ECX,  1)
12499a2dd95SBruce Richardson 	FEAT_DEF(WAITPKG, 0x00000007, 0, RTE_REG_ECX,  5)
1252f375875SDavid Marchand 	FEAT_DEF(AVX512VBMI2, 0x00000007, 0, RTE_REG_ECX,  6)
1262f375875SDavid Marchand 	FEAT_DEF(GFNI, 0x00000007, 0, RTE_REG_ECX,  8)
1272f375875SDavid Marchand 	FEAT_DEF(VAES, 0x00000007, 0, RTE_REG_ECX,  9)
1282f375875SDavid Marchand 	FEAT_DEF(VPCLMULQDQ, 0x00000007, 0, RTE_REG_ECX, 10)
1292f375875SDavid Marchand 	FEAT_DEF(AVX512VNNI, 0x00000007, 0, RTE_REG_ECX, 11)
1302f375875SDavid Marchand 	FEAT_DEF(AVX512BITALG, 0x00000007, 0, RTE_REG_ECX, 12)
1312f375875SDavid Marchand 	FEAT_DEF(AVX512VPOPCNTDQ, 0x00000007, 0, RTE_REG_ECX, 14)
1322f375875SDavid Marchand 	FEAT_DEF(CLDEMOTE, 0x00000007, 0, RTE_REG_ECX, 25)
1332f375875SDavid Marchand 	FEAT_DEF(MOVDIRI, 0x00000007, 0, RTE_REG_ECX, 27)
1342f375875SDavid Marchand 	FEAT_DEF(MOVDIR64B, 0x00000007, 0, RTE_REG_ECX, 28)
1352f375875SDavid Marchand 
1362f375875SDavid Marchand 	FEAT_DEF(AVX512VP2INTERSECT, 0x00000007, 0, RTE_REG_EDX,  8)
13799a2dd95SBruce Richardson 
13899a2dd95SBruce Richardson 	FEAT_DEF(LAHF_SAHF, 0x80000001, 0, RTE_REG_ECX,  0)
13999a2dd95SBruce Richardson 	FEAT_DEF(LZCNT, 0x80000001, 0, RTE_REG_ECX,  4)
140c359a72fSSivaprasad Tummala 	FEAT_DEF(MONITORX, 0x80000001, 0, RTE_REG_ECX,  29)
14199a2dd95SBruce Richardson 
14299a2dd95SBruce Richardson 	FEAT_DEF(SYSCALL, 0x80000001, 0, RTE_REG_EDX, 11)
14399a2dd95SBruce Richardson 	FEAT_DEF(XD, 0x80000001, 0, RTE_REG_EDX, 20)
14499a2dd95SBruce Richardson 	FEAT_DEF(1GB_PG, 0x80000001, 0, RTE_REG_EDX, 26)
14599a2dd95SBruce Richardson 	FEAT_DEF(RDTSCP, 0x80000001, 0, RTE_REG_EDX, 27)
14699a2dd95SBruce Richardson 	FEAT_DEF(EM64T, 0x80000001, 0, RTE_REG_EDX, 29)
14799a2dd95SBruce Richardson 
14899a2dd95SBruce Richardson 	FEAT_DEF(INVTSC, 0x80000007, 0, RTE_REG_EDX,  8)
14999a2dd95SBruce Richardson };
15099a2dd95SBruce Richardson 
15199a2dd95SBruce Richardson int
15299a2dd95SBruce Richardson rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature)
15399a2dd95SBruce Richardson {
154*4225db8dSBruce Richardson 	struct feature_entry *feat;
15599a2dd95SBruce Richardson 	cpuid_registers_t regs;
15699a2dd95SBruce Richardson 	unsigned int maxleaf;
15799a2dd95SBruce Richardson 
15848c33e8cSSivaprasad Tummala 	if ((unsigned int)feature >= RTE_DIM(rte_cpu_feature_table))
15999a2dd95SBruce Richardson 		/* Flag does not match anything in the feature tables */
16099a2dd95SBruce Richardson 		return -ENOENT;
16199a2dd95SBruce Richardson 
16299a2dd95SBruce Richardson 	feat = &rte_cpu_feature_table[feature];
163*4225db8dSBruce Richardson 	if (feat->has_value)
164*4225db8dSBruce Richardson 		return feat->value;
16599a2dd95SBruce Richardson 
16699a2dd95SBruce Richardson 	if (!feat->leaf)
16799a2dd95SBruce Richardson 		/* This entry in the table wasn't filled out! */
16899a2dd95SBruce Richardson 		return -EFAULT;
16999a2dd95SBruce Richardson 
17099a2dd95SBruce Richardson 	maxleaf = __get_cpuid_max(feat->leaf & 0x80000000, NULL);
17199a2dd95SBruce Richardson 
172*4225db8dSBruce Richardson 	if (maxleaf < feat->leaf) {
173*4225db8dSBruce Richardson 		feat->value = 0;
174*4225db8dSBruce Richardson 		goto out;
175*4225db8dSBruce Richardson 	}
17699a2dd95SBruce Richardson 
1772454b37bSTyler Retzlaff #ifdef RTE_TOOLCHAIN_MSVC
1782454b37bSTyler Retzlaff 	__cpuidex(regs, feat->leaf, feat->subleaf);
1792454b37bSTyler Retzlaff #else
18099a2dd95SBruce Richardson 	__cpuid_count(feat->leaf, feat->subleaf,
18199a2dd95SBruce Richardson 			 regs[RTE_REG_EAX], regs[RTE_REG_EBX],
18299a2dd95SBruce Richardson 			 regs[RTE_REG_ECX], regs[RTE_REG_EDX]);
1832454b37bSTyler Retzlaff #endif
18499a2dd95SBruce Richardson 
18599a2dd95SBruce Richardson 	/* check if the feature is enabled */
186*4225db8dSBruce Richardson 	feat->value = (regs[feat->reg] >> feat->bit) & 1;
187*4225db8dSBruce Richardson out:
188*4225db8dSBruce Richardson 	rte_compiler_barrier();
189*4225db8dSBruce Richardson 	feat->has_value = true;
190*4225db8dSBruce Richardson 	return feat->value;
19199a2dd95SBruce Richardson }
19299a2dd95SBruce Richardson 
19399a2dd95SBruce Richardson const char *
19499a2dd95SBruce Richardson rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
19599a2dd95SBruce Richardson {
19648c33e8cSSivaprasad Tummala 	if ((unsigned int)feature >= RTE_DIM(rte_cpu_feature_table))
19799a2dd95SBruce Richardson 		return NULL;
19899a2dd95SBruce Richardson 	return rte_cpu_feature_table[feature].name;
19999a2dd95SBruce Richardson }
20099a2dd95SBruce Richardson 
20199a2dd95SBruce Richardson void
20299a2dd95SBruce Richardson rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
20399a2dd95SBruce Richardson {
20499a2dd95SBruce Richardson 	memset(intrinsics, 0, sizeof(*intrinsics));
20599a2dd95SBruce Richardson 
20699a2dd95SBruce Richardson 	if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_WAITPKG)) {
20799a2dd95SBruce Richardson 		intrinsics->power_monitor = 1;
20899a2dd95SBruce Richardson 		intrinsics->power_pause = 1;
20966834f29SAnatoly Burakov 		if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_RTM))
21066834f29SAnatoly Burakov 			intrinsics->power_monitor_multi = 1;
211c359a72fSSivaprasad Tummala 	} else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_MONITORX)) {
212c359a72fSSivaprasad Tummala 		intrinsics->power_monitor = 1;
21399a2dd95SBruce Richardson 	}
21499a2dd95SBruce Richardson }
215