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