Skip to content

Commit 4e5be9e

Browse files
Add limited support for RISC-V initialization (#190)
* Adds header definitions for RISCV32 and RISCV64, and support in Bazel files for RISCV64. Adds ISA information for RISC-V and hwcap support. * Adds support to construct the processor, core, cluster and package information reported by the system. * Remaining support required for: - Inferring uarch of each processor (reports unknown for now). - Reading cache information (left empty for now). Test: Build and ran cpu_info and isa_info on RISC-V QEMU instance and RISC-V Android emulator. Confirmed that it properly reports the ISA information as well as processor and cluster counts.
1 parent d6860c4 commit 4e5be9e

16 files changed

+1196
-25
lines changed

BUILD.bazel

+20-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ ARM_SRCS = [
4343
"src/arm/uarch.c",
4444
]
4545

46+
RISCV_SRCS = [
47+
"src/riscv/uarch.c",
48+
]
49+
4650
# Platform-specific sources and headers
4751
LINUX_SRCS = [
4852
"src/linux/cpulist.c",
@@ -81,6 +85,12 @@ LINUX_ARM32_SRCS = LINUX_ARM_SRCS + ["src/arm/linux/aarch32-isa.c"]
8185

8286
LINUX_ARM64_SRCS = LINUX_ARM_SRCS + ["src/arm/linux/aarch64-isa.c"]
8387

88+
LINUX_RISCV_SRCS = [
89+
"src/riscv/linux/init.c",
90+
"src/riscv/linux/riscv-isa.c",
91+
"src/riscv/linux/riscv-hw.c",
92+
]
93+
8494
ANDROID_ARM_SRCS = [
8595
"src/arm/android/properties.c",
8696
]
@@ -111,7 +121,8 @@ cc_library(
111121
":linux_armeabi": COMMON_SRCS + ARM_SRCS + LINUX_SRCS + LINUX_ARM32_SRCS,
112122
":linux_aarch64": COMMON_SRCS + ARM_SRCS + LINUX_SRCS + LINUX_ARM64_SRCS,
113123
":linux_mips64": COMMON_SRCS + LINUX_SRCS,
114-
":linux_riscv64": COMMON_SRCS + LINUX_SRCS,
124+
":linux_riscv32": COMMON_SRCS + RISCV_SRCS + LINUX_SRCS + LINUX_RISCV_SRCS,
125+
":linux_riscv64": COMMON_SRCS + RISCV_SRCS + LINUX_SRCS + LINUX_RISCV_SRCS,
115126
":linux_s390x": COMMON_SRCS + LINUX_SRCS,
116127
":macos_x86_64": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
117128
":macos_x86_64_legacy": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
@@ -121,6 +132,7 @@ cc_library(
121132
":android_arm64": COMMON_SRCS + ARM_SRCS + LINUX_SRCS + LINUX_ARM64_SRCS + ANDROID_ARM_SRCS,
122133
":android_x86": COMMON_SRCS + X86_SRCS + LINUX_SRCS + LINUX_X86_SRCS,
123134
":android_x86_64": COMMON_SRCS + X86_SRCS + LINUX_SRCS + LINUX_X86_SRCS,
135+
":android_riscv64": COMMON_SRCS + RISCV_SRCS + LINUX_SRCS + LINUX_RISCV_SRCS,
124136
":ios_x86_64": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
125137
":ios_x86": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
126138
":ios_armv7": COMMON_SRCS + MACH_SRCS + MACH_ARM_SRCS,
@@ -170,6 +182,8 @@ cc_library(
170182
"src/arm/linux/cp.h",
171183
"src/arm/api.h",
172184
"src/arm/midr.h",
185+
"src/riscv/api.h",
186+
"src/riscv/linux/api.h",
173187
],
174188
)
175189

@@ -231,6 +245,11 @@ config_setting(
231245
values = {"cpu": "mips64"},
232246
)
233247

248+
config_setting(
249+
name = "linux_riscv32",
250+
values = {"cpu": "riscv32"},
251+
)
252+
234253
config_setting(
235254
name = "linux_riscv64",
236255
values = {"cpu": "riscv64"},

CMakeLists.txt

+10-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ IF(NOT CMAKE_SYSTEM_PROCESSOR)
9292
"cpuinfo will compile, but cpuinfo_initialize() will always fail.")
9393
SET(CPUINFO_SUPPORTED_PLATFORM FALSE)
9494
ENDIF()
95-
ELSEIF(NOT CPUINFO_TARGET_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?|armv[5-8].*|aarch64|arm64.*|ARM64.*)$")
95+
ELSEIF(NOT CPUINFO_TARGET_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?|armv[5-8].*|aarch64|arm64.*|ARM64.*|riscv(32|64))$")
9696
MESSAGE(WARNING
9797
"Target processor architecture \"${CPUINFO_TARGET_PROCESSOR}\" is not supported in cpuinfo. "
9898
"cpuinfo will compile, but cpuinfo_initialize() will always fail.")
@@ -210,6 +210,15 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
210210
LIST(APPEND CPUINFO_SRCS
211211
src/arm/android/properties.c)
212212
ENDIF()
213+
ELSEIF(CPUINFO_TARGET_PROCESSOR MATCHES "^(riscv(32|64))$")
214+
LIST(APPEND CPUINFO_SRCS
215+
src/riscv/uarch.c)
216+
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
217+
LIST(APPEND CPUINFO_SRCS
218+
src/riscv/linux/init.c
219+
src/riscv/linux/riscv-hw.c
220+
src/riscv/linux/riscv-isa.c)
221+
ENDIF()
213222
ENDIF()
214223

215224
IF(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")

configure.py

+6
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ def main(args):
5656
sources += [
5757
"arm/android/properties.c",
5858
]
59+
if build.target.is_riscv:
60+
if build.target.is_linux:
61+
sources += [
62+
"riscv/linux/init.c",
63+
"riscv/linux/riscv-isa.c",
64+
]
5965

6066
if build.target.is_macos:
6167
sources += ["mach/topology.c"]

include/cpuinfo.h

+121
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@
4646
#endif
4747
#endif
4848

49+
#if defined(__riscv)
50+
#if (__riscv_xlen == 32)
51+
#define CPUINFO_ARCH_RISCV32 1
52+
#elif (__riscv_xlen == 64)
53+
#define CPUINFO_ARCH_RISCV64 1
54+
#endif
55+
#endif
56+
4957
/* Define other architecture-specific macros as 0 */
5058

5159
#ifndef CPUINFO_ARCH_X86
@@ -80,6 +88,14 @@
8088
#define CPUINFO_ARCH_WASMSIMD 0
8189
#endif
8290

91+
#ifndef CPUINFO_ARCH_RISCV32
92+
#define CPUINFO_ARCH_RISCV32 0
93+
#endif
94+
95+
#ifndef CPUINFO_ARCH_RISCV64
96+
#define CPUINFO_ARCH_RISCV64 0
97+
#endif
98+
8399
#if CPUINFO_ARCH_X86 && defined(_MSC_VER)
84100
#define CPUINFO_ABI __cdecl
85101
#elif CPUINFO_ARCH_X86 && defined(__GNUC__)
@@ -188,6 +204,8 @@ enum cpuinfo_vendor {
188204
* Processors are variants of AMD cores.
189205
*/
190206
cpuinfo_vendor_hygon = 16,
207+
/** SiFive, Inc. Vendor of RISC-V processor microarchitectures. */
208+
cpuinfo_vendor_sifive = 17,
191209

192210
/* Active vendors of embedded CPUs */
193211

@@ -1877,6 +1895,109 @@ static inline bool cpuinfo_has_arm_sve2(void) {
18771895
#endif
18781896
}
18791897

1898+
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
1899+
/* This structure is not a part of stable API. Use cpuinfo_has_riscv_* functions instead. */
1900+
struct cpuinfo_riscv_isa {
1901+
/**
1902+
* Keep fields in line with the canonical order as defined by
1903+
* Section 27.11 Subset Naming Convention.
1904+
*/
1905+
/* RV32I/64I/128I Base ISA. */
1906+
bool i;
1907+
#if CPUINFO_ARCH_RISCV32
1908+
/* RV32E Base ISA. */
1909+
bool e;
1910+
#endif
1911+
/* Integer Multiply/Divide Extension. */
1912+
bool m;
1913+
/* Atomic Extension. */
1914+
bool a;
1915+
/* Single-Precision Floating-Point Extension. */
1916+
bool f;
1917+
/* Double-Precision Floating-Point Extension. */
1918+
bool d;
1919+
/* Compressed Extension. */
1920+
bool c;
1921+
/* Vector Extension. */
1922+
bool v;
1923+
};
1924+
1925+
extern struct cpuinfo_riscv_isa cpuinfo_isa;
1926+
#endif
1927+
1928+
static inline bool cpuinfo_has_riscv_i(void) {
1929+
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
1930+
return cpuinfo_isa.i;
1931+
#else
1932+
return false;
1933+
#endif
1934+
}
1935+
1936+
static inline bool cpuinfo_has_riscv_e(void) {
1937+
#if CPUINFO_ARCH_RISCV32
1938+
return cpuinfo_isa.e;
1939+
#else
1940+
return false;
1941+
#endif
1942+
}
1943+
1944+
static inline bool cpuinfo_has_riscv_m(void) {
1945+
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
1946+
return cpuinfo_isa.m;
1947+
#else
1948+
return false;
1949+
#endif
1950+
}
1951+
1952+
static inline bool cpuinfo_has_riscv_a(void) {
1953+
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
1954+
return cpuinfo_isa.a;
1955+
#else
1956+
return false;
1957+
#endif
1958+
}
1959+
1960+
static inline bool cpuinfo_has_riscv_f(void) {
1961+
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
1962+
return cpuinfo_isa.f;
1963+
#else
1964+
return false;
1965+
#endif
1966+
}
1967+
1968+
static inline bool cpuinfo_has_riscv_d(void) {
1969+
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
1970+
return cpuinfo_isa.d;
1971+
#else
1972+
return false;
1973+
#endif
1974+
}
1975+
1976+
static inline bool cpuinfo_has_riscv_g(void) {
1977+
// The 'G' extension is simply shorthand for 'IMAFD'.
1978+
return cpuinfo_has_riscv_i()
1979+
&& cpuinfo_has_riscv_m()
1980+
&& cpuinfo_has_riscv_a()
1981+
&& cpuinfo_has_riscv_f()
1982+
&& cpuinfo_has_riscv_d();
1983+
}
1984+
1985+
static inline bool cpuinfo_has_riscv_c(void) {
1986+
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
1987+
return cpuinfo_isa.c;
1988+
#else
1989+
return false;
1990+
#endif
1991+
}
1992+
1993+
static inline bool cpuinfo_has_riscv_v(void) {
1994+
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
1995+
return cpuinfo_isa.v;
1996+
#else
1997+
return false;
1998+
#endif
1999+
}
2000+
18802001
const struct cpuinfo_processor* CPUINFO_ABI cpuinfo_get_processors(void);
18812002
const struct cpuinfo_core* CPUINFO_ABI cpuinfo_get_cores(void);
18822003
const struct cpuinfo_cluster* CPUINFO_ABI cpuinfo_get_clusters(void);

src/api.c

+16-9
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ uint32_t cpuinfo_packages_count = 0;
3030
uint32_t cpuinfo_cache_count[cpuinfo_cache_level_max] = { 0 };
3131
uint32_t cpuinfo_max_cache_size = 0;
3232

33-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
33+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
34+
|| CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
3435
struct cpuinfo_uarch_info* cpuinfo_uarchs = NULL;
3536
uint32_t cpuinfo_uarchs_count = 0;
3637
#else
@@ -41,7 +42,8 @@ uint32_t cpuinfo_max_cache_size = 0;
4142
uint32_t cpuinfo_linux_cpu_max = 0;
4243
const struct cpuinfo_processor** cpuinfo_linux_cpu_to_processor_map = NULL;
4344
const struct cpuinfo_core** cpuinfo_linux_cpu_to_core_map = NULL;
44-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
45+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
46+
|| CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
4547
const uint32_t* cpuinfo_linux_cpu_to_uarch_index_map = NULL;
4648
#endif
4749
#endif
@@ -79,7 +81,8 @@ const struct cpuinfo_uarch_info* cpuinfo_get_uarchs() {
7981
if (!cpuinfo_is_initialized) {
8082
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarchs");
8183
}
82-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
84+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
85+
|| CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
8386
return cpuinfo_uarchs;
8487
#else
8588
return &cpuinfo_global_uarch;
@@ -130,7 +133,8 @@ const struct cpuinfo_uarch_info* cpuinfo_get_uarch(uint32_t index) {
130133
if (!cpuinfo_is_initialized) {
131134
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarch");
132135
}
133-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
136+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
137+
|| CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
134138
if CPUINFO_UNLIKELY(index >= cpuinfo_uarchs_count) {
135139
return NULL;
136140
}
@@ -175,7 +179,8 @@ uint32_t cpuinfo_get_uarchs_count(void) {
175179
if (!cpuinfo_is_initialized) {
176180
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarchs_count");
177181
}
178-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
182+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
183+
|| CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
179184
return cpuinfo_uarchs_count;
180185
#else
181186
return 1;
@@ -351,7 +356,8 @@ uint32_t CPUINFO_ABI cpuinfo_get_current_uarch_index(void) {
351356
if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
352357
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "current_uarch_index");
353358
}
354-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
359+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
360+
|| CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
355361
#ifdef __linux__
356362
if (cpuinfo_linux_cpu_to_uarch_index_map == NULL) {
357363
/* Special case: avoid syscall on systems with only a single type of cores */
@@ -373,7 +379,7 @@ uint32_t CPUINFO_ABI cpuinfo_get_current_uarch_index(void) {
373379
return 0;
374380
#endif
375381
#else
376-
/* Only ARM/ARM64 processors may include cores of different types in the same package. */
382+
/* Only ARM/ARM64/RISCV processors may include cores of different types in the same package. */
377383
return 0;
378384
#endif
379385
}
@@ -382,7 +388,8 @@ uint32_t CPUINFO_ABI cpuinfo_get_current_uarch_index_with_default(uint32_t defau
382388
if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
383389
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "current_uarch_index_with_default");
384390
}
385-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
391+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \
392+
|| CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
386393
#ifdef __linux__
387394
if (cpuinfo_linux_cpu_to_uarch_index_map == NULL) {
388395
/* Special case: avoid syscall on systems with only a single type of cores */
@@ -404,7 +411,7 @@ uint32_t CPUINFO_ABI cpuinfo_get_current_uarch_index_with_default(uint32_t defau
404411
return default_uarch_index;
405412
#endif
406413
#else
407-
/* Only ARM/ARM64 processors may include cores of different types in the same package. */
414+
/* Only ARM/ARM64/RISCV processors may include cores of different types in the same package. */
408415
return 0;
409416
#endif
410417
}

src/cpuinfo/internal-api.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ extern CPUINFO_INTERNAL uint32_t cpuinfo_packages_count;
3535
extern CPUINFO_INTERNAL uint32_t cpuinfo_cache_count[cpuinfo_cache_level_max];
3636
extern CPUINFO_INTERNAL uint32_t cpuinfo_max_cache_size;
3737

38-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
38+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
3939
extern CPUINFO_INTERNAL struct cpuinfo_uarch_info* cpuinfo_uarchs;
4040
extern CPUINFO_INTERNAL uint32_t cpuinfo_uarchs_count;
4141
#else
@@ -59,6 +59,7 @@ CPUINFO_PRIVATE void cpuinfo_x86_linux_init(void);
5959
#endif
6060
CPUINFO_PRIVATE void cpuinfo_arm_mach_init(void);
6161
CPUINFO_PRIVATE void cpuinfo_arm_linux_init(void);
62+
CPUINFO_PRIVATE void cpuinfo_riscv_linux_init(void);
6263
CPUINFO_PRIVATE void cpuinfo_emscripten_init(void);
6364

6465
CPUINFO_PRIVATE uint32_t cpuinfo_compute_max_cache_size(const struct cpuinfo_processor* processor);

src/init.c

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ bool CPUINFO_ABI cpuinfo_initialize(void) {
4242
#else
4343
cpuinfo_log_error("operating system is not supported in cpuinfo");
4444
#endif
45+
#elif CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
46+
#if defined(__linux__)
47+
pthread_once(&init_guard, &cpuinfo_riscv_linux_init);
48+
#else
49+
cpuinfo_log_error("operating system is not supported in cpuinfo");
50+
#endif
4551
#elif CPUINFO_ARCH_ASMJS || CPUINFO_ARCH_WASM || CPUINFO_ARCH_WASMSIMD
4652
#if defined(__EMSCRIPTEN_PTHREADS__)
4753
pthread_once(&init_guard, &cpuinfo_emscripten_init);

0 commit comments

Comments
 (0)