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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of compiler-rt/lib/builtins/cpu_model/riscv.c