eal/riscv: support RISC-V architecture
[dpdk.git] / lib / eal / riscv / rte_cpuflags.c
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
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
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 (feature >= RTE_CPUFLAG_NUMFLAGS)
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 *
111 rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
112 {
113         if (feature >= RTE_CPUFLAG_NUMFLAGS)
114                 return NULL;
115         return rte_cpu_feature_table[feature].name;
116 }
117
118 void
119 rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
120 {
121         memset(intrinsics, 0, sizeof(*intrinsics));
122 }