Skip to content

Commit a41a4ac

Browse files
BeMgkito-cheng
andauthored
[compiler-rt][RISCV] Implement __init_riscv_feature_bits (#85790)
Base on riscv-non-isa/riscv-c-api-doc#74, this patch defines the `__riscv_feature_bits` and `__riscv_vendor_feature_bits` structures to store the enabled feature bits at runtime. It also introduces the `__init_riscv_feature_bits` function to update these structures based on the platform query mechanism. Additionally, the groupid/bitmask definitions from riscv-non-isa/riscv-c-api-doc#74 are declared and used to update the `__riscv_feature_bits` and `__riscv_vendor_feature_bits` structures. --------- Co-authored-by: Kito Cheng <[email protected]>
1 parent 05f986e commit a41a4ac

File tree

2 files changed

+299
-0
lines changed

2 files changed

+299
-0
lines changed

compiler-rt/lib/builtins/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,7 @@ endif()
739739
set(powerpc64le_SOURCES ${powerpc64_SOURCES})
740740

741741
set(riscv_SOURCES
742+
riscv/feature_bits.c
742743
riscv/fp_mode.c
743744
riscv/save.S
744745
riscv/restore.S
Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
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

Comments
 (0)