Skip to content

Commit 10e154b

Browse files
Added support for RISC-V architecture on Linux
1 parent f44a9da commit 10e154b

File tree

23 files changed

+1167
-20
lines changed

23 files changed

+1167
-20
lines changed

BUILD.bazel

Lines changed: 20 additions & 1 deletion
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/cache.c",
48+
]
49+
4650
# Platform-specific sources and headers
4751
LINUX_SRCS = [
4852
"src/linux/cpulist.c",
@@ -81,6 +85,14 @@ 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/clusters.c",
90+
"src/riscv/linux/cpuinfo.c",
91+
"src/riscv/linux/hwcap.c",
92+
"src/riscv/linux/init.c",
93+
"src/riscv/linux/riscv-isa.c",
94+
]
95+
8496
ANDROID_ARM_SRCS = [
8597
"src/arm/android/properties.c",
8698
]
@@ -111,7 +123,8 @@ cc_library(
111123
":linux_armeabi": COMMON_SRCS + ARM_SRCS + LINUX_SRCS + LINUX_ARM32_SRCS,
112124
":linux_aarch64": COMMON_SRCS + ARM_SRCS + LINUX_SRCS + LINUX_ARM64_SRCS,
113125
":linux_mips64": COMMON_SRCS + LINUX_SRCS,
114-
":linux_riscv64": COMMON_SRCS + LINUX_SRCS,
126+
":linux_riscv": COMMON_SRCS + LINUX_SRCS + RISCV_SRCS + LINUX_RISCV_SRCS,
127+
":linux_riscv64": COMMON_SRCS + LINUX_SRCS + RISCV_SRCS + LINUX_RISCV_SRCS,
115128
":linux_s390x": COMMON_SRCS + LINUX_SRCS,
116129
":macos_x86_64": COMMON_SRCS + X86_SRCS + MACH_SRCS + MACH_X86_SRCS,
117130
":macos_arm64": COMMON_SRCS + MACH_SRCS + MACH_ARM_SRCS,
@@ -168,6 +181,7 @@ cc_library(
168181
"src/arm/linux/cp.h",
169182
"src/arm/api.h",
170183
"src/arm/midr.h",
184+
"src/riscv/linux/api.h",
171185
],
172186
)
173187

@@ -229,6 +243,11 @@ config_setting(
229243
values = {"cpu": "mips64"},
230244
)
231245

246+
config_setting(
247+
name = "linux_riscv",
248+
values = {"cpu": "riscv"},
249+
)
250+
232251
config_setting(
233252
name = "linux_riscv64",
234253
values = {"cpu": "riscv64"},

CMakeLists.txt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ IF(NOT CMAKE_SYSTEM_PROCESSOR)
8989
"cpuinfo will compile, but cpuinfo_initialize() will always fail.")
9090
SET(CPUINFO_SUPPORTED_PLATFORM FALSE)
9191
ENDIF()
92-
ELSEIF(NOT CPUINFO_TARGET_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?|armv[5-8].*|aarch64|arm64.*|ARM64.*)$")
92+
ELSEIF(NOT CPUINFO_TARGET_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?|armv[5-8].*|aarch64|arm64.*|ARM64.*|riscv(64)?)$")
9393
MESSAGE(WARNING
9494
"Target processor architecture \"${CPUINFO_TARGET_PROCESSOR}\" is not supported in cpuinfo. "
9595
"cpuinfo will compile, but cpuinfo_initialize() will always fail.")
@@ -197,6 +197,17 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
197197
LIST(APPEND CPUINFO_SRCS
198198
src/arm/android/properties.c)
199199
ENDIF()
200+
ELSEIF (CPUINFO_TARGET_PROCESSOR MATCHES "^(riscv(64)?)$")
201+
LIST(APPEND CPUINFO_SRCS
202+
src/riscv/cache.c)
203+
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
204+
LIST(APPEND CPUINFO_SRCS
205+
src/riscv/linux/clusters.c
206+
src/riscv/linux/cpuinfo.c
207+
src/riscv/linux/hwcap.c
208+
src/riscv/linux/init.c
209+
src/riscv/linux/riscv-isa.c)
210+
ENDIF ()
200211
ENDIF()
201212

202213
IF(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")

configure.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ def main(args):
5656
sources += [
5757
"arm/android/properties.c",
5858
]
59+
if build.target.is_riscv:
60+
sources += [
61+
"riscv/cache.c",
62+
]
63+
if build.target.is_linux:
64+
sources += [
65+
"riscv/linux/clusters.c",
66+
"riscv/linux/cpuinfo.c",
67+
"riscv/linux/hwcap.c",
68+
"riscv/linux/init.c",
69+
"riscv/linux/riscv-isa.c",
70+
]
5971

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

include/cpuinfo-mock.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,11 @@ struct cpuinfo_mock_property {
6363
#endif
6464
#if CPUINFO_ARCH_ARM
6565
void CPUINFO_ABI cpuinfo_set_hwcap2(uint32_t hwcap2);
66-
#endif
66+
#endif
67+
68+
#if CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
69+
void CPUINFO_ABI cpuinfo_set_hwcap(uint32_t hwcap);
70+
#endif
6771
#endif
6872

6973
#if defined(__ANDROID__)

include/cpuinfo.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@
3434
#define CPUINFO_ARCH_PPC64 1
3535
#endif
3636

37+
#if defined(__riscv)
38+
#if __riscv_xlen == 32
39+
#define CPUINFO_ARCH_RISCV 1
40+
#elif __riscv_xlen == 64
41+
#define CPUINFO_ARCH_RISCV64 1
42+
#else
43+
#error "Unexpected __riscv_xlen"
44+
#endif
45+
#endif
46+
3747
#if defined(__asmjs__)
3848
#define CPUINFO_ARCH_ASMJS 1
3949
#endif
@@ -68,6 +78,14 @@
6878
#define CPUINFO_ARCH_PPC64 0
6979
#endif
7080

81+
#ifndef CPUINFO_ARCH_RISCV
82+
#define CPUINFO_ARCH_RISCV 0
83+
#endif
84+
85+
#ifndef CPUINFO_ARCH_RISCV64
86+
#define CPUINFO_ARCH_RISCV64 0
87+
#endif
88+
7189
#ifndef CPUINFO_ARCH_ASMJS
7290
#define CPUINFO_ARCH_ASMJS 0
7391
#endif
@@ -257,6 +275,10 @@ enum cpuinfo_vendor {
257275
* Sold its ARM designs in 1997. The last processor design was released in 1997.
258276
*/
259277
cpuinfo_vendor_dec = 57,
278+
/**
279+
* SiFive. Vendor of RISC-V processor microarchitecture.
280+
*/
281+
cpuinfo_vendor_sifive = 58,
260282
};
261283

262284
/**
@@ -532,6 +554,9 @@ enum cpuinfo_uarch {
532554

533555
/** HiSilicon TaiShan v110 (Huawei Kunpeng 920 series processors). */
534556
cpuinfo_uarch_taishan_v110 = 0x00C00100,
557+
558+
/** SiFive U74-MC Standard Core. */
559+
cpuinfo_uarch_u74_mc = 0x00D00100,
535560
};
536561

537562
struct cpuinfo_processor {
@@ -1862,6 +1887,72 @@ static inline bool cpuinfo_has_arm_sve2(void) {
18621887
#endif
18631888
}
18641889

1890+
#if CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
1891+
/* This structure is not a part of stable API. Use cpuinfo_has_riscv_* functions instead. */
1892+
struct cpuinfo_riscv_isa {
1893+
bool a;
1894+
bool c;
1895+
bool d;
1896+
bool f;
1897+
#if CPUINFO_ARCH_RISCV
1898+
bool i;
1899+
#endif
1900+
bool m;
1901+
};
1902+
1903+
extern struct cpuinfo_riscv_isa cpuinfo_isa;
1904+
#endif
1905+
1906+
static inline bool cpuinfo_has_riscv_a(void) {
1907+
#if CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
1908+
return cpuinfo_isa.a;
1909+
#else
1910+
return false;
1911+
#endif
1912+
}
1913+
1914+
static inline bool cpuinfo_has_riscv_c(void) {
1915+
#if CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
1916+
return cpuinfo_isa.c;
1917+
#else
1918+
return false;
1919+
#endif
1920+
}
1921+
1922+
static inline bool cpuinfo_has_riscv_d(void) {
1923+
#if CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
1924+
return cpuinfo_isa.d;
1925+
#else
1926+
return false;
1927+
#endif
1928+
}
1929+
1930+
static inline bool cpuinfo_has_riscv_f(void) {
1931+
#if CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
1932+
return cpuinfo_isa.f;
1933+
#else
1934+
return false;
1935+
#endif
1936+
}
1937+
1938+
static inline bool cpuinfo_has_riscv_i(void) {
1939+
#if CPUINFO_ARCH_RISCV
1940+
return cpuinfo_isa.i;
1941+
#elif CPUINFO_ARCH_RISCV64
1942+
return true;
1943+
#else
1944+
return false;
1945+
#endif
1946+
}
1947+
1948+
static inline bool cpuinfo_has_riscv_m(void) {
1949+
#if CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
1950+
return cpuinfo_isa.m;
1951+
#else
1952+
return false;
1953+
#endif
1954+
}
1955+
18651956
const struct cpuinfo_processor* CPUINFO_ABI cpuinfo_get_processors(void);
18661957
const struct cpuinfo_core* CPUINFO_ABI cpuinfo_get_cores(void);
18671958
const struct cpuinfo_cluster* CPUINFO_ABI cpuinfo_get_clusters(void);

src/api.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ 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 || CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
3434
struct cpuinfo_uarch_info* cpuinfo_uarchs = NULL;
3535
uint32_t cpuinfo_uarchs_count = 0;
3636
#else
@@ -41,7 +41,7 @@ uint32_t cpuinfo_max_cache_size = 0;
4141
uint32_t cpuinfo_linux_cpu_max = 0;
4242
const struct cpuinfo_processor** cpuinfo_linux_cpu_to_processor_map = NULL;
4343
const struct cpuinfo_core** cpuinfo_linux_cpu_to_core_map = NULL;
44-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
44+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
4545
const uint32_t* cpuinfo_linux_cpu_to_uarch_index_map = NULL;
4646
#endif
4747
#endif
@@ -79,7 +79,7 @@ const struct cpuinfo_uarch_info* cpuinfo_get_uarchs() {
7979
if (!cpuinfo_is_initialized) {
8080
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarchs");
8181
}
82-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
82+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
8383
return cpuinfo_uarchs;
8484
#else
8585
return &cpuinfo_global_uarch;
@@ -130,7 +130,7 @@ const struct cpuinfo_uarch_info* cpuinfo_get_uarch(uint32_t index) {
130130
if (!cpuinfo_is_initialized) {
131131
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarch");
132132
}
133-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
133+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
134134
if CPUINFO_UNLIKELY(index >= cpuinfo_uarchs_count) {
135135
return NULL;
136136
}
@@ -175,7 +175,7 @@ uint32_t cpuinfo_get_uarchs_count(void) {
175175
if (!cpuinfo_is_initialized) {
176176
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarchs_count");
177177
}
178-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
178+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
179179
return cpuinfo_uarchs_count;
180180
#else
181181
return 1;
@@ -351,7 +351,7 @@ uint32_t CPUINFO_ABI cpuinfo_get_current_uarch_index(void) {
351351
if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
352352
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "current_uarch_index");
353353
}
354-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
354+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
355355
#ifdef __linux__
356356
if (cpuinfo_linux_cpu_to_uarch_index_map == NULL) {
357357
/* Special case: avoid syscall on systems with only a single type of cores */
@@ -382,7 +382,7 @@ uint32_t CPUINFO_ABI cpuinfo_get_current_uarch_index_with_default(uint32_t defau
382382
if CPUINFO_UNLIKELY(!cpuinfo_is_initialized) {
383383
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "current_uarch_index_with_default");
384384
}
385-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
385+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
386386
#ifdef __linux__
387387
if (cpuinfo_linux_cpu_to_uarch_index_map == NULL) {
388388
/* Special case: avoid syscall on systems with only a single type of cores */

src/arm/linux/cpuinfo.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,6 @@ static bool parse_line(
893893
default:
894894
unknown:
895895
cpuinfo_log_debug("unknown /proc/cpuinfo key: %.*s", (int) key_length, line_start);
896-
897896
}
898897
return true;
899898
}

src/cpuinfo/internal-api.h

Lines changed: 2 additions & 1 deletion
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_RISCV || 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

Lines changed: 6 additions & 0 deletions
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_RISCV || 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);

src/linux/api.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
typedef bool (*cpuinfo_cpulist_callback)(uint32_t, uint32_t, void*);
2727
CPUINFO_INTERNAL bool cpuinfo_linux_parse_cpulist(const char* filename, cpuinfo_cpulist_callback callback, void* context);
28-
typedef bool (*cpuinfo_smallfile_callback)(const char*, const char*, void*);
28+
typedef bool (*cpuinfo_smallfile_callback)(const char*, const char*, const char*, void*);
2929
CPUINFO_INTERNAL bool cpuinfo_linux_parse_small_file(const char* filename, size_t buffer_size, cpuinfo_smallfile_callback, void* context);
3030
typedef bool (*cpuinfo_line_callback)(const char*, const char*, void*, uint64_t);
3131
CPUINFO_INTERNAL bool cpuinfo_linux_parse_multiline_file(const char* filename, size_t buffer_size, cpuinfo_line_callback, void* context);

src/linux/processors.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ inline static bool is_whitespace(char c) {
8181
static const uint32_t default_max_processors_count = CPU_SETSIZE;
8282
#endif
8383

84-
static bool uint32_parser(const char* text_start, const char* text_end, void* context) {
84+
static bool uint32_parser(const char* filename, const char* text_start, const char* text_end, void* context) {
8585
if (text_start == text_end) {
8686
cpuinfo_log_error("failed to parse file %s: file is empty", KERNEL_MAX_FILENAME);
8787
return false;
@@ -91,13 +91,13 @@ static bool uint32_parser(const char* text_start, const char* text_end, void* co
9191
const char* parsed_end = parse_number(text_start, text_end, &kernel_max);
9292
if (parsed_end == text_start) {
9393
cpuinfo_log_error("failed to parse file %s: \"%.*s\" is not an unsigned number",
94-
KERNEL_MAX_FILENAME, (int) (text_end - text_start), text_start);
94+
filename, (int) (text_end - text_start), text_start);
9595
return false;
9696
} else {
9797
for (const char* char_ptr = parsed_end; char_ptr != text_end; char_ptr++) {
9898
if (!is_whitespace(*char_ptr)) {
9999
cpuinfo_log_warning("non-whitespace characters \"%.*s\" following number in file %s are ignored",
100-
(int) (text_end - char_ptr), char_ptr, KERNEL_MAX_FILENAME);
100+
(int) (text_end - char_ptr), char_ptr, filename);
101101
break;
102102
}
103103
}
@@ -227,7 +227,7 @@ static bool max_processor_number_parser(uint32_t processor_list_start, uint32_t
227227
uint32_t cpuinfo_linux_get_max_possible_processor(uint32_t max_processors_count) {
228228
uint32_t max_possible_processor = 0;
229229
if (!cpuinfo_linux_parse_cpulist(POSSIBLE_CPULIST_FILENAME, max_processor_number_parser, &max_possible_processor)) {
230-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
230+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
231231
cpuinfo_log_error("failed to parse the list of possible processors in %s", POSSIBLE_CPULIST_FILENAME);
232232
#else
233233
cpuinfo_log_warning("failed to parse the list of possible processors in %s", POSSIBLE_CPULIST_FILENAME);
@@ -246,7 +246,7 @@ uint32_t cpuinfo_linux_get_max_possible_processor(uint32_t max_processors_count)
246246
uint32_t cpuinfo_linux_get_max_present_processor(uint32_t max_processors_count) {
247247
uint32_t max_present_processor = 0;
248248
if (!cpuinfo_linux_parse_cpulist(PRESENT_CPULIST_FILENAME, max_processor_number_parser, &max_present_processor)) {
249-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
249+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV || CPUINFO_ARCH_RISCV64
250250
cpuinfo_log_error("failed to parse the list of present processors in %s", PRESENT_CPULIST_FILENAME);
251251
#else
252252
cpuinfo_log_warning("failed to parse the list of present processors in %s", PRESENT_CPULIST_FILENAME);

0 commit comments

Comments
 (0)