xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/cpu_model/riscv.c (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //=== cpu_model/riscv.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 #include "cpu_model.h"
10 
11 #define RISCV_FEATURE_BITS_LENGTH 2
12 struct {
13   unsigned length;
14   unsigned long long features[RISCV_FEATURE_BITS_LENGTH];
15 } __riscv_feature_bits __attribute__((visibility("hidden"), nocommon));
16 
17 struct {
18   unsigned mvendorid;
19   unsigned long long marchid;
20   unsigned long long mimpid;
21 } __riscv_cpu_model __attribute__((visibility("hidden"), nocommon));
22 
23 // NOTE: Should sync-up with RISCVFeatures.td
24 // TODO: Maybe generate a header from tablegen then include it.
25 #define A_GROUPID 0
26 #define A_BITMASK (1ULL << 0)
27 #define B_GROUPID 0
28 #define B_BITMASK (1ULL << 1)
29 #define C_GROUPID 0
30 #define C_BITMASK (1ULL << 2)
31 #define D_GROUPID 0
32 #define D_BITMASK (1ULL << 3)
33 #define E_GROUPID 0
34 #define E_BITMASK (1ULL << 4)
35 #define F_GROUPID 0
36 #define F_BITMASK (1ULL << 5)
37 #define H_GROUPID 0
38 #define H_BITMASK (1ULL << 7)
39 #define I_GROUPID 0
40 #define I_BITMASK (1ULL << 8)
41 #define M_GROUPID 0
42 #define M_BITMASK (1ULL << 12)
43 #define Q_GROUPID 0
44 #define Q_BITMASK (1ULL << 16)
45 #define V_GROUPID 0
46 #define V_BITMASK (1ULL << 21)
47 #define ZACAS_GROUPID 0
48 #define ZACAS_BITMASK (1ULL << 26)
49 #define ZBA_GROUPID 0
50 #define ZBA_BITMASK (1ULL << 27)
51 #define ZBB_GROUPID 0
52 #define ZBB_BITMASK (1ULL << 28)
53 #define ZBC_GROUPID 0
54 #define ZBC_BITMASK (1ULL << 29)
55 #define ZBKB_GROUPID 0
56 #define ZBKB_BITMASK (1ULL << 30)
57 #define ZBKC_GROUPID 0
58 #define ZBKC_BITMASK (1ULL << 31)
59 #define ZBKX_GROUPID 0
60 #define ZBKX_BITMASK (1ULL << 32)
61 #define ZBS_GROUPID 0
62 #define ZBS_BITMASK (1ULL << 33)
63 #define ZFA_GROUPID 0
64 #define ZFA_BITMASK (1ULL << 34)
65 #define ZFH_GROUPID 0
66 #define ZFH_BITMASK (1ULL << 35)
67 #define ZFHMIN_GROUPID 0
68 #define ZFHMIN_BITMASK (1ULL << 36)
69 #define ZICBOZ_GROUPID 0
70 #define ZICBOZ_BITMASK (1ULL << 37)
71 #define ZICOND_GROUPID 0
72 #define ZICOND_BITMASK (1ULL << 38)
73 #define ZIHINTNTL_GROUPID 0
74 #define ZIHINTNTL_BITMASK (1ULL << 39)
75 #define ZIHINTPAUSE_GROUPID 0
76 #define ZIHINTPAUSE_BITMASK (1ULL << 40)
77 #define ZKND_GROUPID 0
78 #define ZKND_BITMASK (1ULL << 41)
79 #define ZKNE_GROUPID 0
80 #define ZKNE_BITMASK (1ULL << 42)
81 #define ZKNH_GROUPID 0
82 #define ZKNH_BITMASK (1ULL << 43)
83 #define ZKSED_GROUPID 0
84 #define ZKSED_BITMASK (1ULL << 44)
85 #define ZKSH_GROUPID 0
86 #define ZKSH_BITMASK (1ULL << 45)
87 #define ZKT_GROUPID 0
88 #define ZKT_BITMASK (1ULL << 46)
89 #define ZTSO_GROUPID 0
90 #define ZTSO_BITMASK (1ULL << 47)
91 #define ZVBB_GROUPID 0
92 #define ZVBB_BITMASK (1ULL << 48)
93 #define ZVBC_GROUPID 0
94 #define ZVBC_BITMASK (1ULL << 49)
95 #define ZVFH_GROUPID 0
96 #define ZVFH_BITMASK (1ULL << 50)
97 #define ZVFHMIN_GROUPID 0
98 #define ZVFHMIN_BITMASK (1ULL << 51)
99 #define ZVKB_GROUPID 0
100 #define ZVKB_BITMASK (1ULL << 52)
101 #define ZVKG_GROUPID 0
102 #define ZVKG_BITMASK (1ULL << 53)
103 #define ZVKNED_GROUPID 0
104 #define ZVKNED_BITMASK (1ULL << 54)
105 #define ZVKNHA_GROUPID 0
106 #define ZVKNHA_BITMASK (1ULL << 55)
107 #define ZVKNHB_GROUPID 0
108 #define ZVKNHB_BITMASK (1ULL << 56)
109 #define ZVKSED_GROUPID 0
110 #define ZVKSED_BITMASK (1ULL << 57)
111 #define ZVKSH_GROUPID 0
112 #define ZVKSH_BITMASK (1ULL << 58)
113 #define ZVKT_GROUPID 0
114 #define ZVKT_BITMASK (1ULL << 59)
115 #define ZVE32X_GROUPID 0
116 #define ZVE32X_BITMASK (1ULL << 60)
117 #define ZVE32F_GROUPID 0
118 #define ZVE32F_BITMASK (1ULL << 61)
119 #define ZVE64X_GROUPID 0
120 #define ZVE64X_BITMASK (1ULL << 62)
121 #define ZVE64F_GROUPID 0
122 #define ZVE64F_BITMASK (1ULL << 63)
123 #define ZVE64D_GROUPID 1
124 #define ZVE64D_BITMASK (1ULL << 0)
125 #define ZIMOP_GROUPID 1
126 #define ZIMOP_BITMASK (1ULL << 1)
127 #define ZCA_GROUPID 1
128 #define ZCA_BITMASK (1ULL << 2)
129 #define ZCB_GROUPID 1
130 #define ZCB_BITMASK (1ULL << 3)
131 #define ZCD_GROUPID 1
132 #define ZCD_BITMASK (1ULL << 4)
133 #define ZCF_GROUPID 1
134 #define ZCF_BITMASK (1ULL << 5)
135 #define ZCMOP_GROUPID 1
136 #define ZCMOP_BITMASK (1ULL << 6)
137 #define ZAWRS_GROUPID 1
138 #define ZAWRS_BITMASK (1ULL << 7)
139 #define ZILSD_GROUPID 1
140 #define ZILSD_BITMASK (1ULL << 8)
141 #define ZCLSD_GROUPID 1
142 #define ZCLSD_BITMASK (1ULL << 9)
143 #define ZCMP_GROUPID 1
144 #define ZCMP_BITMASK (1ULL << 10)
145 
146 #if defined(__linux__)
147 
148 // The RISC-V hwprobe interface is documented here:
149 // <https://docs.kernel.org/arch/riscv/hwprobe.html>.
150 
syscall_impl_5_args(long number,long arg1,long arg2,long arg3,long arg4,long arg5)151 static long syscall_impl_5_args(long number, long arg1, long arg2, long arg3,
152                                 long arg4, long arg5) {
153   register long a7 __asm__("a7") = number;
154   register long a0 __asm__("a0") = arg1;
155   register long a1 __asm__("a1") = arg2;
156   register long a2 __asm__("a2") = arg3;
157   register long a3 __asm__("a3") = arg4;
158   register long a4 __asm__("a4") = arg5;
159   __asm__ __volatile__("ecall\n\t"
160                        : "=r"(a0)
161                        : "r"(a7), "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4)
162                        : "memory");
163   return a0;
164 }
165 
166 #define RISCV_HWPROBE_KEY_MVENDORID 0
167 #define RISCV_HWPROBE_KEY_MARCHID 1
168 #define RISCV_HWPROBE_KEY_MIMPID 2
169 #define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3
170 #define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1ULL << 0)
171 #define RISCV_HWPROBE_KEY_IMA_EXT_0 4
172 #define RISCV_HWPROBE_IMA_FD (1ULL << 0)
173 #define RISCV_HWPROBE_IMA_C (1ULL << 1)
174 #define RISCV_HWPROBE_IMA_V (1ULL << 2)
175 #define RISCV_HWPROBE_EXT_ZBA (1ULL << 3)
176 #define RISCV_HWPROBE_EXT_ZBB (1ULL << 4)
177 #define RISCV_HWPROBE_EXT_ZBS (1ULL << 5)
178 #define RISCV_HWPROBE_EXT_ZICBOZ (1ULL << 6)
179 #define RISCV_HWPROBE_EXT_ZBC (1ULL << 7)
180 #define RISCV_HWPROBE_EXT_ZBKB (1ULL << 8)
181 #define RISCV_HWPROBE_EXT_ZBKC (1ULL << 9)
182 #define RISCV_HWPROBE_EXT_ZBKX (1ULL << 10)
183 #define RISCV_HWPROBE_EXT_ZKND (1ULL << 11)
184 #define RISCV_HWPROBE_EXT_ZKNE (1ULL << 12)
185 #define RISCV_HWPROBE_EXT_ZKNH (1ULL << 13)
186 #define RISCV_HWPROBE_EXT_ZKSED (1ULL << 14)
187 #define RISCV_HWPROBE_EXT_ZKSH (1ULL << 15)
188 #define RISCV_HWPROBE_EXT_ZKT (1ULL << 16)
189 #define RISCV_HWPROBE_EXT_ZVBB (1ULL << 17)
190 #define RISCV_HWPROBE_EXT_ZVBC (1ULL << 18)
191 #define RISCV_HWPROBE_EXT_ZVKB (1ULL << 19)
192 #define RISCV_HWPROBE_EXT_ZVKG (1ULL << 20)
193 #define RISCV_HWPROBE_EXT_ZVKNED (1ULL << 21)
194 #define RISCV_HWPROBE_EXT_ZVKNHA (1ULL << 22)
195 #define RISCV_HWPROBE_EXT_ZVKNHB (1ULL << 23)
196 #define RISCV_HWPROBE_EXT_ZVKSED (1ULL << 24)
197 #define RISCV_HWPROBE_EXT_ZVKSH (1ULL << 25)
198 #define RISCV_HWPROBE_EXT_ZVKT (1ULL << 26)
199 #define RISCV_HWPROBE_EXT_ZFH (1ULL << 27)
200 #define RISCV_HWPROBE_EXT_ZFHMIN (1ULL << 28)
201 #define RISCV_HWPROBE_EXT_ZIHINTNTL (1ULL << 29)
202 #define RISCV_HWPROBE_EXT_ZVFH (1ULL << 30)
203 #define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31)
204 #define RISCV_HWPROBE_EXT_ZFA (1ULL << 32)
205 #define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33)
206 #define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34)
207 #define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35)
208 #define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36)
209 #define RISCV_HWPROBE_EXT_ZVE32X (1ULL << 37)
210 #define RISCV_HWPROBE_EXT_ZVE32F (1ULL << 38)
211 #define RISCV_HWPROBE_EXT_ZVE64X (1ULL << 39)
212 #define RISCV_HWPROBE_EXT_ZVE64F (1ULL << 40)
213 #define RISCV_HWPROBE_EXT_ZVE64D (1ULL << 41)
214 #define RISCV_HWPROBE_EXT_ZIMOP (1ULL << 42)
215 #define RISCV_HWPROBE_EXT_ZCA (1ULL << 43)
216 #define RISCV_HWPROBE_EXT_ZCB (1ULL << 44)
217 #define RISCV_HWPROBE_EXT_ZCD (1ULL << 45)
218 #define RISCV_HWPROBE_EXT_ZCF (1ULL << 46)
219 #define RISCV_HWPROBE_EXT_ZCMOP (1ULL << 47)
220 #define RISCV_HWPROBE_EXT_ZAWRS (1ULL << 48)
221 #define RISCV_HWPROBE_KEY_CPUPERF_0 5
222 #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
223 #define RISCV_HWPROBE_MISALIGNED_EMULATED (1ULL << 0)
224 #define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0)
225 #define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)
226 #define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
227 #define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
228 #define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6
229 /* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
230 
231 struct riscv_hwprobe {
232   long long key;
233   unsigned long long value;
234 };
235 
236 #define __NR_riscv_hwprobe 258
initHwProbe(struct riscv_hwprobe * Hwprobes,int len)237 static long initHwProbe(struct riscv_hwprobe *Hwprobes, int len) {
238   return syscall_impl_5_args(__NR_riscv_hwprobe, (long)Hwprobes, len, 0, 0, 0);
239 }
240 
241 #define SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(EXTNAME)                    \
242   SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_EXT_##EXTNAME, EXTNAME)
243 
244 #define SET_SINGLE_IMAEXT_RISCV_FEATURE(HWPROBE_BITMASK, EXT)                  \
245   SET_SINGLE_RISCV_FEATURE(IMAEXT0Value &HWPROBE_BITMASK, EXT)
246 
247 #define SET_SINGLE_RISCV_FEATURE(COND, EXT)                                    \
248   if (COND) {                                                                  \
249     SET_RISCV_FEATURE(EXT);                                                    \
250   }
251 
252 #define SET_RISCV_FEATURE(EXT) features[EXT##_GROUPID] |= EXT##_BITMASK
253 
initRISCVFeature(struct riscv_hwprobe Hwprobes[])254 static void initRISCVFeature(struct riscv_hwprobe Hwprobes[]) {
255 
256   // Note: If a hwprobe key is unknown to the kernel, its key field
257   // will be cleared to -1, and its value set to 0.
258   // This unsets all extension bitmask bits.
259 
260   // Init VendorID, ArchID, ImplID
261   __riscv_cpu_model.mvendorid = Hwprobes[2].value;
262   __riscv_cpu_model.marchid = Hwprobes[3].value;
263   __riscv_cpu_model.mimpid = Hwprobes[4].value;
264 
265   // Init standard extension
266   // TODO: Maybe Extension implied generate from tablegen?
267 
268   unsigned long long features[RISCV_FEATURE_BITS_LENGTH];
269   int i;
270 
271   for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++)
272     features[i] = 0;
273 
274   // Check RISCV_HWPROBE_KEY_BASE_BEHAVIOR
275   unsigned long long BaseValue = Hwprobes[0].value;
276   if (BaseValue & RISCV_HWPROBE_BASE_BEHAVIOR_IMA) {
277     SET_RISCV_FEATURE(I);
278     SET_RISCV_FEATURE(M);
279     SET_RISCV_FEATURE(A);
280   }
281 
282   // Check RISCV_HWPROBE_KEY_IMA_EXT_0
283   unsigned long long IMAEXT0Value = Hwprobes[1].value;
284   if (IMAEXT0Value & RISCV_HWPROBE_IMA_FD) {
285     SET_RISCV_FEATURE(F);
286     SET_RISCV_FEATURE(D);
287   }
288 
289   SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_IMA_C, C);
290   SET_SINGLE_IMAEXT_RISCV_FEATURE(RISCV_HWPROBE_IMA_V, V);
291   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBA);
292   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBB);
293   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBS);
294   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZICBOZ);
295   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBC);
296   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKB);
297   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKC);
298   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZBKX);
299   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKND);
300   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKNE);
301   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKNH);
302   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKSED);
303   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKSH);
304   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZKT);
305   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVBB);
306   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVBC);
307   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKB);
308   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKG);
309   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNED);
310   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNHA);
311   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKNHB);
312   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKSED);
313   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKSH);
314   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVKT);
315   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFH);
316   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFHMIN);
317   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIHINTNTL);
318   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIHINTPAUSE);
319   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVFH);
320   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVFHMIN);
321   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZFA);
322   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZTSO);
323   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZACAS);
324   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZICOND);
325   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE32X);
326   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE32F);
327   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64X);
328   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64F);
329   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64D);
330   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIMOP);
331   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCA);
332   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCB);
333   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCD);
334   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCF);
335   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCMOP);
336   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZAWRS);
337 
338   for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++)
339     __riscv_feature_bits.features[i] = features[i];
340 }
341 
342 #endif // defined(__linux__)
343 
344 static int FeaturesBitCached = 0;
345 
346 void __init_riscv_feature_bits(void *);
347 static void __init_riscv_feature_bits_ctor(void) CONSTRUCTOR_ATTRIBUTE;
348 
349 // A constructor function that sets __riscv_feature_bits
350 // to the right values.  This needs to run only once.  This constructor is given
351 // the highest priority and it should run before constructors without the
352 // priority set.  However, it still runs after ifunc initializers and needs to
353 // be called explicitly there.
354 
__init_riscv_feature_bits_ctor(void)355 static void CONSTRUCTOR_ATTRIBUTE __init_riscv_feature_bits_ctor(void) {
356   __init_riscv_feature_bits(0);
357 }
358 
359 // PlatformArgs allows the platform to provide pre-computed data and access it
360 // without extra effort. For example, Linux could pass the vDSO object to avoid
361 // an extra system call.
__init_riscv_feature_bits(void * PlatformArgs)362 void __init_riscv_feature_bits(void *PlatformArgs) {
363 
364   if (FeaturesBitCached)
365     return;
366 
367   __riscv_feature_bits.length = RISCV_FEATURE_BITS_LENGTH;
368 
369 #if defined(__linux__)
370   struct riscv_hwprobe Hwprobes[] = {
371       {RISCV_HWPROBE_KEY_BASE_BEHAVIOR, 0}, {RISCV_HWPROBE_KEY_IMA_EXT_0, 0},
372       {RISCV_HWPROBE_KEY_MVENDORID, 0},     {RISCV_HWPROBE_KEY_MARCHID, 0},
373       {RISCV_HWPROBE_KEY_MIMPID, 0},
374   };
375   if (initHwProbe(Hwprobes, sizeof(Hwprobes) / sizeof(Hwprobes[0])))
376     return;
377 
378   initRISCVFeature(Hwprobes);
379 #endif // defined(__linux__)
380 
381   FeaturesBitCached = 1;
382 }
383