|
| 1 | +//=== feature_bits.c - Update RISC-V Feature Bits Structure -*- C -*-=========// |
| 2 | +// |
| 3 | +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | +// See https://llvm.org/LICENSE.txt for license information. |
| 5 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | +// |
| 7 | +//===----------------------------------------------------------------------===// |
| 8 | + |
| 9 | +#define RISCV_FEATURE_BITS_LENGTH 1 |
| 10 | +struct { |
| 11 | + unsigned length; |
| 12 | + unsigned long long features[RISCV_FEATURE_BITS_LENGTH]; |
| 13 | +} __riscv_feature_bits __attribute__((visibility("hidden"), nocommon)); |
| 14 | + |
| 15 | +#define RISCV_VENDOR_FEATURE_BITS_LENGTH 1 |
| 16 | +struct { |
| 17 | + unsigned vendorID; |
| 18 | + unsigned length; |
| 19 | + unsigned long long features[RISCV_VENDOR_FEATURE_BITS_LENGTH]; |
| 20 | +} __riscv_vendor_feature_bits __attribute__((visibility("hidden"), nocommon)); |
| 21 | + |
| 22 | +// NOTE: Should sync-up with RISCVFeatures.td |
| 23 | +// TODO: Maybe generate a header from tablegen then include it. |
| 24 | +#define A_GROUPID 0 |
| 25 | +#define A_BITMASK (1ULL << 0) |
| 26 | +#define C_GROUPID 0 |
| 27 | +#define C_BITMASK (1ULL << 2) |
| 28 | +#define D_GROUPID 0 |
| 29 | +#define D_BITMASK (1ULL << 3) |
| 30 | +#define F_GROUPID 0 |
| 31 | +#define F_BITMASK (1ULL << 5) |
| 32 | +#define I_GROUPID 0 |
| 33 | +#define I_BITMASK (1ULL << 8) |
| 34 | +#define M_GROUPID 0 |
| 35 | +#define M_BITMASK (1ULL << 12) |
| 36 | +#define V_GROUPID 0 |
| 37 | +#define V_BITMASK (1ULL << 21) |
| 38 | +#define ZACAS_GROUPID 0 |
| 39 | +#define ZACAS_BITMASK (1ULL << 26) |
| 40 | +#define ZBA_GROUPID 0 |
| 41 | +#define ZBA_BITMASK (1ULL << 27) |
| 42 | +#define ZBB_GROUPID 0 |
| 43 | +#define ZBB_BITMASK (1ULL << 28) |
| 44 | +#define ZBC_GROUPID 0 |
| 45 | +#define ZBC_BITMASK (1ULL << 29) |
| 46 | +#define ZBKB_GROUPID 0 |
| 47 | +#define ZBKB_BITMASK (1ULL << 30) |
| 48 | +#define ZBKC_GROUPID 0 |
| 49 | +#define ZBKC_BITMASK (1ULL << 31) |
| 50 | +#define ZBKX_GROUPID 0 |
| 51 | +#define ZBKX_BITMASK (1ULL << 32) |
| 52 | +#define ZBS_GROUPID 0 |
| 53 | +#define ZBS_BITMASK (1ULL << 33) |
| 54 | +#define ZFA_GROUPID 0 |
| 55 | +#define ZFA_BITMASK (1ULL << 34) |
| 56 | +#define ZFH_GROUPID 0 |
| 57 | +#define ZFH_BITMASK (1ULL << 35) |
| 58 | +#define ZFHMIN_GROUPID 0 |
| 59 | +#define ZFHMIN_BITMASK (1ULL << 36) |
| 60 | +#define ZICBOZ_GROUPID 0 |
| 61 | +#define ZICBOZ_BITMASK (1ULL << 37) |
| 62 | +#define ZICOND_GROUPID 0 |
| 63 | +#define ZICOND_BITMASK (1ULL << 38) |
| 64 | +#define ZIHINTNTL_GROUPID 0 |
| 65 | +#define ZIHINTNTL_BITMASK (1ULL << 39) |
| 66 | +#define ZIHINTPAUSE_GROUPID 0 |
| 67 | +#define ZIHINTPAUSE_BITMASK (1ULL << 40) |
| 68 | +#define ZKND_GROUPID 0 |
| 69 | +#define ZKND_BITMASK (1ULL << 41) |
| 70 | +#define ZKNE_GROUPID 0 |
| 71 | +#define ZKNE_BITMASK (1ULL << 42) |
| 72 | +#define ZKNH_GROUPID 0 |
| 73 | +#define ZKNH_BITMASK (1ULL << 43) |
| 74 | +#define ZKSED_GROUPID 0 |
| 75 | +#define ZKSED_BITMASK (1ULL << 44) |
| 76 | +#define ZKSH_GROUPID 0 |
| 77 | +#define ZKSH_BITMASK (1ULL << 45) |
| 78 | +#define ZKT_GROUPID 0 |
| 79 | +#define ZKT_BITMASK (1ULL << 46) |
| 80 | +#define ZTSO_GROUPID 0 |
| 81 | +#define ZTSO_BITMASK (1ULL << 47) |
| 82 | +#define ZVBB_GROUPID 0 |
| 83 | +#define ZVBB_BITMASK (1ULL << 48) |
| 84 | +#define ZVBC_GROUPID 0 |
| 85 | +#define ZVBC_BITMASK (1ULL << 49) |
| 86 | +#define ZVFH_GROUPID 0 |
| 87 | +#define ZVFH_BITMASK (1ULL << 50) |
| 88 | +#define ZVFHMIN_GROUPID 0 |
| 89 | +#define ZVFHMIN_BITMASK (1ULL << 51) |
| 90 | +#define ZVKB_GROUPID 0 |
| 91 | +#define ZVKB_BITMASK (1ULL << 52) |
| 92 | +#define ZVKG_GROUPID 0 |
| 93 | +#define ZVKG_BITMASK (1ULL << 53) |
| 94 | +#define ZVKNED_GROUPID 0 |
| 95 | +#define ZVKNED_BITMASK (1ULL << 54) |
| 96 | +#define ZVKNHA_GROUPID 0 |
| 97 | +#define ZVKNHA_BITMASK (1ULL << 55) |
| 98 | +#define ZVKNHB_GROUPID 0 |
| 99 | +#define ZVKNHB_BITMASK (1ULL << 56) |
| 100 | +#define ZVKSED_GROUPID 0 |
| 101 | +#define ZVKSED_BITMASK (1ULL << 57) |
| 102 | +#define ZVKSH_GROUPID 0 |
| 103 | +#define ZVKSH_BITMASK (1ULL << 58) |
| 104 | +#define ZVKT_GROUPID 0 |
| 105 | +#define ZVKT_BITMASK (1ULL << 59) |
| 106 | + |
| 107 | +#if defined(__linux__) |
| 108 | + |
| 109 | +static long syscall_impl_5_args(long number, long arg1, long arg2, long arg3, |
| 110 | + long arg4, long arg5) { |
| 111 | + register long a7 __asm__("a7") = number; |
| 112 | + register long a0 __asm__("a0") = arg1; |
| 113 | + register long a1 __asm__("a1") = arg2; |
| 114 | + register long a2 __asm__("a2") = arg3; |
| 115 | + register long a3 __asm__("a3") = arg4; |
| 116 | + register long a4 __asm__("a4") = arg5; |
| 117 | + __asm__ __volatile__("ecall\n\t" |
| 118 | + : "=r"(a0) |
| 119 | + : "r"(a7), "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4) |
| 120 | + : "memory"); |
| 121 | + return a0; |
| 122 | +} |
| 123 | + |
| 124 | +#define RISCV_HWPROBE_KEY_MVENDORID 0 |
| 125 | +#define RISCV_HWPROBE_KEY_MARCHID 1 |
| 126 | +#define RISCV_HWPROBE_KEY_MIMPID 2 |
| 127 | +#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3 |
| 128 | +#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1ULL << 0) |
| 129 | +#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 |
| 130 | +#define RISCV_HWPROBE_IMA_FD (1ULL << 0) |
| 131 | +#define RISCV_HWPROBE_IMA_C (1ULL << 1) |
| 132 | +#define RISCV_HWPROBE_IMA_V (1ULL << 2) |
| 133 | +#define RISCV_HWPROBE_EXT_ZBA (1ULL << 3) |
| 134 | +#define RISCV_HWPROBE_EXT_ZBB (1ULL << 4) |
| 135 | +#define RISCV_HWPROBE_EXT_ZBS (1ULL << 5) |
| 136 | +#define RISCV_HWPROBE_EXT_ZICBOZ (1ULL << 6) |
| 137 | +#define RISCV_HWPROBE_EXT_ZBC (1ULL << 7) |
| 138 | +#define RISCV_HWPROBE_EXT_ZBKB (1ULL << 8) |
| 139 | +#define RISCV_HWPROBE_EXT_ZBKC (1ULL << 9) |
| 140 | +#define RISCV_HWPROBE_EXT_ZBKX (1ULL << 10) |
| 141 | +#define RISCV_HWPROBE_EXT_ZKND (1ULL << 11) |
| 142 | +#define RISCV_HWPROBE_EXT_ZKNE (1ULL << 12) |
| 143 | +#define RISCV_HWPROBE_EXT_ZKNH (1ULL << 13) |
| 144 | +#define RISCV_HWPROBE_EXT_ZKSED (1ULL << 14) |
| 145 | +#define RISCV_HWPROBE_EXT_ZKSH (1ULL << 15) |
| 146 | +#define RISCV_HWPROBE_EXT_ZKT (1ULL << 16) |
| 147 | +#define RISCV_HWPROBE_EXT_ZVBB (1ULL << 17) |
| 148 | +#define RISCV_HWPROBE_EXT_ZVBC (1ULL << 18) |
| 149 | +#define RISCV_HWPROBE_EXT_ZVKB (1ULL << 19) |
| 150 | +#define RISCV_HWPROBE_EXT_ZVKG (1ULL << 20) |
| 151 | +#define RISCV_HWPROBE_EXT_ZVKNED (1ULL << 21) |
| 152 | +#define RISCV_HWPROBE_EXT_ZVKNHA (1ULL << 22) |
| 153 | +#define RISCV_HWPROBE_EXT_ZVKNHB (1ULL << 23) |
| 154 | +#define RISCV_HWPROBE_EXT_ZVKSED (1ULL << 24) |
| 155 | +#define RISCV_HWPROBE_EXT_ZVKSH (1ULL << 25) |
| 156 | +#define RISCV_HWPROBE_EXT_ZVKT (1ULL << 26) |
| 157 | +#define RISCV_HWPROBE_EXT_ZFH (1ULL << 27) |
| 158 | +#define RISCV_HWPROBE_EXT_ZFHMIN (1ULL << 28) |
| 159 | +#define RISCV_HWPROBE_EXT_ZIHINTNTL (1ULL << 29) |
| 160 | +#define RISCV_HWPROBE_EXT_ZVFH (1ULL << 30) |
| 161 | +#define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31) |
| 162 | +#define RISCV_HWPROBE_EXT_ZFA (1ULL << 32) |
| 163 | +#define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33) |
| 164 | +#define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34) |
| 165 | +#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35) |
| 166 | +#define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36) |
| 167 | +#define RISCV_HWPROBE_KEY_CPUPERF_0 5 |
| 168 | +#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) |
| 169 | +#define RISCV_HWPROBE_MISALIGNED_EMULATED (1ULL << 0) |
| 170 | +#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0) |
| 171 | +#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0) |
| 172 | +#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0) |
| 173 | +#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0) |
| 174 | +#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6 |
| 175 | +/* Increase RISCV_HWPROBE_MAX_KEY when adding items. */ |
| 176 | + |
| 177 | +struct riscv_hwprobe { |
| 178 | + long long key; |
| 179 | + unsigned long long value; |
| 180 | +}; |
| 181 | + |
| 182 | +#define __NR_riscv_hwprobe 258 |
| 183 | +static long initHwProbe(struct riscv_hwprobe *Hwprobes, int len) { |
| 184 | + return syscall_impl_5_args(__NR_riscv_hwprobe, (long)Hwprobes, len, 0, 0, 0); |
| 185 | +} |
| 186 | + |
| 187 | +#define SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(EXTNAME) \ |
| 188 | + SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_EXT_##EXTNAME, EXTNAME) |
| 189 | + |
| 190 | +#define SET_SINGLE_IMAEXT_RISCV_FEATURE(HWPROBE_BITMASK, EXT) \ |
| 191 | + SET_SINGLE_RISCV_FEATURE(IMAEXT0Value &HWPROBE_BITMASK, EXT) |
| 192 | + |
| 193 | +#define SET_SINGLE_RISCV_FEATURE(COND, EXT) \ |
| 194 | + if (COND) { \ |
| 195 | + SET_RISCV_FEATURE(EXT); \ |
| 196 | + } |
| 197 | + |
| 198 | +#define SET_RISCV_FEATURE(EXT) features[EXT##_GROUPID] |= EXT##_BITMASK |
| 199 | + |
| 200 | +static void initRISCVFeature(struct riscv_hwprobe Hwprobes[]) { |
| 201 | + |
| 202 | + // Note: If a hwprobe key is unknown to the kernel, its key field |
| 203 | + // will be cleared to -1, and its value set to 0. |
| 204 | + // This unsets all extension bitmask bits. |
| 205 | + |
| 206 | + // Init vendor extension |
| 207 | + __riscv_vendor_feature_bits.length = 0; |
| 208 | + __riscv_vendor_feature_bits.vendorID = Hwprobes[2].value; |
| 209 | + |
| 210 | + // Init standard extension |
| 211 | + // TODO: Maybe Extension implied generate from tablegen? |
| 212 | + __riscv_feature_bits.length = RISCV_FEATURE_BITS_LENGTH; |
| 213 | + |
| 214 | + unsigned long long features[RISCV_FEATURE_BITS_LENGTH]; |
| 215 | + int i; |
| 216 | + |
| 217 | + for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++) |
| 218 | + features[i] = 0; |
| 219 | + |
| 220 | + // Check RISCV_HWPROBE_KEY_BASE_BEHAVIOR |
| 221 | + unsigned long long BaseValue = Hwprobes[0].value; |
| 222 | + if (BaseValue & RISCV_HWPROBE_BASE_BEHAVIOR_IMA) { |
| 223 | + SET_RISCV_FEATURE(I); |
| 224 | + SET_RISCV_FEATURE(M); |
| 225 | + SET_RISCV_FEATURE(A); |
| 226 | + } |
| 227 | + |
| 228 | + // Check RISCV_HWPROBE_KEY_IMA_EXT_0 |
| 229 | + unsigned long long IMAEXT0Value = Hwprobes[1].value; |
| 230 | + if (IMAEXT0Value & RISCV_HWPROBE_IMA_FD) { |
| 231 | + SET_RISCV_FEATURE(F); |
| 232 | + SET_RISCV_FEATURE(D); |
| 233 | + } |
| 234 | + |
| 235 | + SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_IMA_C, C); |
| 236 | + SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_IMA_V, V); |
| 237 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBA); |
| 238 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBB); |
| 239 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBS); |
| 240 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZICBOZ); |
| 241 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBC); |
| 242 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKB); |
| 243 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKC); |
| 244 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKX); |
| 245 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKND); |
| 246 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKNE); |
| 247 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKNH); |
| 248 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKSED); |
| 249 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKSH); |
| 250 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKT); |
| 251 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVBB); |
| 252 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVBC); |
| 253 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKB); |
| 254 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKG); |
| 255 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNED); |
| 256 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNHA); |
| 257 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNHB); |
| 258 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKSED); |
| 259 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKSH); |
| 260 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKT); |
| 261 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFH); |
| 262 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFHMIN); |
| 263 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIHINTNTL); |
| 264 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIHINTPAUSE); |
| 265 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVFH); |
| 266 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVFHMIN); |
| 267 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFA); |
| 268 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZTSO); |
| 269 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZACAS); |
| 270 | + SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZICOND); |
| 271 | + |
| 272 | + for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++) |
| 273 | + __riscv_feature_bits.features[i] = features[i]; |
| 274 | +} |
| 275 | + |
| 276 | +#endif // defined(__linux__) |
| 277 | + |
| 278 | +static int FeaturesBitCached = 0; |
| 279 | + |
| 280 | +void __init_riscv_feature_bits() { |
| 281 | + |
| 282 | + if (FeaturesBitCached) |
| 283 | + return; |
| 284 | + |
| 285 | +#if defined(__linux__) |
| 286 | + struct riscv_hwprobe Hwprobes[] = { |
| 287 | + {RISCV_HWPROBE_KEY_BASE_BEHAVIOR, 0}, |
| 288 | + {RISCV_HWPROBE_KEY_IMA_EXT_0, 0}, |
| 289 | + {RISCV_HWPROBE_KEY_MVENDORID, 0}, |
| 290 | + }; |
| 291 | + if (initHwProbe(Hwprobes, sizeof(Hwprobes) / sizeof(Hwprobes[0]))) |
| 292 | + return; |
| 293 | + |
| 294 | + initRISCVFeature(Hwprobes); |
| 295 | +#endif // defined(__linux__) |
| 296 | + |
| 297 | + FeaturesBitCached = 1; |
| 298 | +} |
0 commit comments