1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2022 Loongson Technology Corporation Limited
4 */
5
6 #include "rte_cpuflags.h"
7
8 #include <elf.h>
9 #include <fcntl.h>
10 #include <assert.h>
11 #include <unistd.h>
12 #include <string.h>
13
14 /* Symbolic values for the entries in the auxiliary table */
15 #define AT_HWCAP 16
16
17 /* software based registers */
18 enum cpu_register_t {
19 REG_NONE = 0,
20 REG_HWCAP,
21 REG_MAX
22 };
23
24 typedef uint32_t hwcap_registers_t[REG_MAX];
25
26 struct feature_entry {
27 uint32_t reg;
28 uint32_t bit;
29 #define CPU_FLAG_NAME_MAX_LEN 64
30 char name[CPU_FLAG_NAME_MAX_LEN];
31 };
32
33 #define FEAT_DEF(name, reg, bit) \
34 [RTE_CPUFLAG_##name] = {reg, bit, #name},
35
36 const struct feature_entry rte_cpu_feature_table[] = {
37 FEAT_DEF(CPUCFG, REG_HWCAP, 0)
38 FEAT_DEF(LAM, REG_HWCAP, 1)
39 FEAT_DEF(UAL, REG_HWCAP, 2)
40 FEAT_DEF(FPU, REG_HWCAP, 3)
41 FEAT_DEF(LSX, REG_HWCAP, 4)
42 FEAT_DEF(LASX, REG_HWCAP, 5)
43 FEAT_DEF(CRC32, REG_HWCAP, 6)
44 FEAT_DEF(COMPLEX, REG_HWCAP, 7)
45 FEAT_DEF(CRYPTO, REG_HWCAP, 8)
46 FEAT_DEF(LVZ, REG_HWCAP, 9)
47 FEAT_DEF(LBT_X86, REG_HWCAP, 10)
48 FEAT_DEF(LBT_ARM, REG_HWCAP, 11)
49 FEAT_DEF(LBT_MIPS, REG_HWCAP, 12)
50 };
51
52 /*
53 * Read AUXV software register and get cpu features for LoongArch
54 */
55 static void
rte_cpu_get_features(hwcap_registers_t out)56 rte_cpu_get_features(hwcap_registers_t out)
57 {
58 out[REG_HWCAP] = rte_cpu_getauxval(AT_HWCAP);
59 }
60
61 /*
62 * Checks if a particular flag is available on current machine.
63 */
64 int
rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature)65 rte_cpu_get_flag_enabled(enum rte_cpu_flag_t feature)
66 {
67 const struct feature_entry *feat;
68 hwcap_registers_t regs = {0};
69
70 if ((unsigned int)feature >= RTE_DIM(rte_cpu_feature_table))
71 return -ENOENT;
72
73 feat = &rte_cpu_feature_table[feature];
74 if (feat->reg == REG_NONE)
75 return -EFAULT;
76
77 rte_cpu_get_features(regs);
78 return (regs[feat->reg] >> feat->bit) & 1;
79 }
80
81 const char *
rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)82 rte_cpu_get_flag_name(enum rte_cpu_flag_t feature)
83 {
84 if ((unsigned int)feature >= RTE_DIM(rte_cpu_feature_table))
85 return NULL;
86 return rte_cpu_feature_table[feature].name;
87 }
88
89 void
rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics * intrinsics)90 rte_cpu_get_intrinsics_support(struct rte_cpu_intrinsics *intrinsics)
91 {
92 memset(intrinsics, 0, sizeof(*intrinsics));
93 }
94