xref: /dpdk/lib/eal/riscv/rte_cpuflags.c (revision 48c33e8ceeaf323976b0d26ee976f43829acfb43)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2022 StarFive
3  * Copyright(c) 2022 SiFive
4  * Copyright(c) 2022 Semihalf
5  */
6 
7 #include "rte_cpuflags.h"
8 
9 #include <elf.h>
10 #include <fcntl.h>
11 #include <assert.h>
12 #include <unistd.h>
13 #include <string.h>
14 
15 #ifndef AT_HWCAP
16 #define AT_HWCAP 16
17 #endif
18 
19 #ifndef AT_HWCAP2
20 #define AT_HWCAP2 26
21 #endif
22 
23 #ifndef AT_PLATFORM
24 #define AT_PLATFORM 15
25 #endif
26 
27 enum cpu_register_t {
28 	REG_NONE = 0,
29 	REG_HWCAP,
30 	REG_HWCAP2,
31 	REG_PLATFORM,
32 	REG_MAX
33 };
34 
35 typedef uint32_t hwcap_registers_t[REG_MAX];
36 
37 /**
38  * Struct to hold a processor feature entry
39  */
40 struct feature_entry {
41 	uint32_t reg;
42 	uint32_t bit;
43 #define CPU_FLAG_NAME_MAX_LEN 64
44 	char name[CPU_FLAG_NAME_MAX_LEN];
45 };
46 
47 #define FEAT_DEF(name, reg, bit) \
48 	[RTE_CPUFLAG_##name] = {reg, bit, #name},
49 
50 typedef Elf64_auxv_t _Elfx_auxv_t;
51 
52 const struct feature_entry rte_cpu_feature_table[] = {
53 	FEAT_DEF(RISCV_ISA_A, REG_HWCAP,    0)
54 	FEAT_DEF(RISCV_ISA_B, REG_HWCAP,    1)
55 	FEAT_DEF(RISCV_ISA_C, REG_HWCAP,    2)
56 	FEAT_DEF(RISCV_ISA_D, REG_HWCAP,    3)
57 	FEAT_DEF(RISCV_ISA_E, REG_HWCAP,    4)
58 	FEAT_DEF(RISCV_ISA_F, REG_HWCAP,    5)
59 	FEAT_DEF(RISCV_ISA_G, REG_HWCAP,    6)
60 	FEAT_DEF(RISCV_ISA_H, REG_HWCAP,    7)
61 	FEAT_DEF(RISCV_ISA_I, REG_HWCAP,    8)
62 	FEAT_DEF(RISCV_ISA_J, REG_HWCAP,    9)
63 	FEAT_DEF(RISCV_ISA_K, REG_HWCAP,   10)
64 	FEAT_DEF(RISCV_ISA_L, REG_HWCAP,   11)
65 	FEAT_DEF(RISCV_ISA_M, REG_HWCAP,   12)
66 	FEAT_DEF(RISCV_ISA_N, REG_HWCAP,   13)
67 	FEAT_DEF(RISCV_ISA_O, REG_HWCAP,   14)
68 	FEAT_DEF(RISCV_ISA_P, REG_HWCAP,   15)
69 	FEAT_DEF(RISCV_ISA_Q, REG_HWCAP,   16)
70 	FEAT_DEF(RISCV_ISA_R, REG_HWCAP,   17)
71 	FEAT_DEF(RISCV_ISA_S, REG_HWCAP,   18)
72 	FEAT_DEF(RISCV_ISA_T, REG_HWCAP,   19)
73 	FEAT_DEF(RISCV_ISA_U, REG_HWCAP,   20)
74 	FEAT_DEF(RISCV_ISA_V, REG_HWCAP,   21)
75 	FEAT_DEF(RISCV_ISA_W, REG_HWCAP,   22)
76 	FEAT_DEF(RISCV_ISA_X, REG_HWCAP,   23)
77 	FEAT_DEF(RISCV_ISA_Y, REG_HWCAP,   24)
78 	FEAT_DEF(RISCV_ISA_Z, REG_HWCAP,   25)
79 };
80 /*
81  * Read AUXV software register and get cpu features for ARM
82  */
83 static void
rte_cpu_get_features(hwcap_registers_t out)84 rte_cpu_get_features(hwcap_registers_t out)
85 {
86 	out[REG_HWCAP] = rte_cpu_getauxval(AT_HWCAP);
87 	out[REG_HWCAP2] = rte_cpu_getauxval(AT_HWCAP2);
88 }
89 
90 /*
91  * Checks if a particular flag is available on current machine.
92  */
93 int
rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature)94 rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature)
95 {
96 	const struct feature_entry *feat;
97 	hwcap_registers_t regs = {0};
98 
99 	if ((unsigned int)feature >= RTE_DIM(rte_cpu_feature_table))
100 		return -ENOENT;
101 
102 	feat = &rte_cpu_feature_table[feature];
103 	if (feat->reg == REG_NONE)
104 		return -EFAULT;
105 
106 	rte_cpu_get_features(regs);
107 	return (regs[feat->reg] >> feat->bit) & 1;
108 }
109 
110 const char *
rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)111 rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
112 {
113 	if ((unsigned int)feature >= RTE_DIM(rte_cpu_feature_table))
114 		return NULL;
115 	return rte_cpu_feature_table[feature].name;
116 }
117 
118 void
rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics * intrinsics)119 rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
120 {
121 	memset(intrinsics, 0, sizeof(*intrinsics));
122 }
123