Skip to content

Commit 876be35

Browse files
Added support for RISC-V architecture on Linux
1 parent 20bd32c commit 876be35

File tree

17 files changed

+660
-120
lines changed

17 files changed

+660
-120
lines changed

BUILD.bazel

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ ARM_SRCS = [
4545

4646
RISCV_SRCS = [
4747
"src/riscv/uarch.c",
48+
"src/riscv/cache.c",
4849
]
4950

5051
# Platform-specific sources and headers
@@ -86,9 +87,11 @@ LINUX_ARM32_SRCS = LINUX_ARM_SRCS + ["src/arm/linux/aarch32-isa.c"]
8687
LINUX_ARM64_SRCS = LINUX_ARM_SRCS + ["src/arm/linux/aarch64-isa.c"]
8788

8889
LINUX_RISCV_SRCS = [
90+
"src/riscv/linux/cpuinfo.c",
91+
"src/riscv/linux/hwcap.c",
8992
"src/riscv/linux/init.c",
90-
"src/riscv/linux/riscv-isa.c",
9193
"src/riscv/linux/riscv-hw.c",
94+
"src/riscv/linux/riscv-isa.c",
9295
]
9396

9497
ANDROID_ARM_SRCS = [

CMakeLists.txt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,15 +210,18 @@ 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))$")
213+
ELSEIF (CPUINFO_TARGET_PROCESSOR MATCHES "^(riscv(32|64)?)$")
214214
LIST(APPEND CPUINFO_SRCS
215+
src/riscv/cache.c
215216
src/riscv/uarch.c)
216217
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
217218
LIST(APPEND CPUINFO_SRCS
219+
src/riscv/linux/cpuinfo.c
220+
src/riscv/linux/hwcap.c
218221
src/riscv/linux/init.c
219-
src/riscv/linux/riscv-hw.c
220-
src/riscv/linux/riscv-isa.c)
221-
ENDIF()
222+
src/riscv/linux/riscv-hw.c
223+
src/riscv/linux/riscv-isa.c)
224+
ENDIF ()
222225
ENDIF()
223226

224227
IF(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")

configure.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,13 @@ def main(args):
5757
"arm/android/properties.c",
5858
]
5959
if build.target.is_riscv:
60+
sources += [
61+
"riscv/cache.c",
62+
]
6063
if build.target.is_linux:
6164
sources += [
65+
"riscv/linux/cpuinfo.c",
66+
"riscv/linux/hwcap.c",
6267
"riscv/linux/init.c",
6368
"riscv/linux/riscv-isa.c",
6469
]

include/cpuinfo-mock.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ struct cpuinfo_mock_property {
6464
#if CPUINFO_ARCH_ARM
6565
void CPUINFO_ABI cpuinfo_set_hwcap2(uint32_t hwcap2);
6666
#endif
67+
68+
#if CPUINFO_ARCH_RISCV32 || 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: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
#define CPUINFO_ARCH_RISCV32 1
5252
#elif (__riscv_xlen == 64)
5353
#define CPUINFO_ARCH_RISCV64 1
54+
#else
55+
#error "Unexpected __riscv_xlen"
5456
#endif
5557
#endif
5658

@@ -76,6 +78,14 @@
7678
#define CPUINFO_ARCH_PPC64 0
7779
#endif
7880

81+
#ifndef CPUINFO_ARCH_RISCV32
82+
#define CPUINFO_ARCH_RISCV32 0
83+
#endif
84+
85+
#ifndef CPUINFO_ARCH_RISCV64
86+
#define CPUINFO_ARCH_RISCV64 0
87+
#endif
88+
7989
#ifndef CPUINFO_ARCH_ASMJS
8090
#define CPUINFO_ARCH_ASMJS 0
8191
#endif
@@ -556,6 +566,9 @@ enum cpuinfo_uarch {
556566

557567
/** HiSilicon TaiShan v110 (Huawei Kunpeng 920 series processors). */
558568
cpuinfo_uarch_taishan_v110 = 0x00C00100,
569+
570+
/** SiFive U74-MC Standard Core. */
571+
cpuinfo_uarch_u74_mc = 0x00D00100,
559572
};
560573

561574
struct cpuinfo_processor {
@@ -1904,10 +1917,6 @@ static inline bool cpuinfo_has_arm_sve2(void) {
19041917
*/
19051918
/* RV32I/64I/128I Base ISA. */
19061919
bool i;
1907-
#if CPUINFO_ARCH_RISCV32
1908-
/* RV32E Base ISA. */
1909-
bool e;
1910-
#endif
19111920
/* Integer Multiply/Divide Extension. */
19121921
bool m;
19131922
/* Atomic Extension. */
@@ -1933,14 +1942,6 @@ static inline bool cpuinfo_has_riscv_i(void) {
19331942
#endif
19341943
}
19351944

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-
19441945
static inline bool cpuinfo_has_riscv_m(void) {
19451946
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
19461947
return cpuinfo_isa.m;

src/linux/api.h

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

2727
typedef bool (*cpuinfo_cpulist_callback)(uint32_t, uint32_t, void*);
2828
CPUINFO_INTERNAL bool cpuinfo_linux_parse_cpulist(const char* filename, cpuinfo_cpulist_callback callback, void* context);
29-
typedef bool (*cpuinfo_smallfile_callback)(const char*, const char*, void*);
29+
typedef bool (*cpuinfo_smallfile_callback)(const char*, const char*, const char*, void*);
3030
CPUINFO_INTERNAL bool cpuinfo_linux_parse_small_file(const char* filename, size_t buffer_size, cpuinfo_smallfile_callback, void* context);
3131
typedef bool (*cpuinfo_line_callback)(const char*, const char*, void*, uint64_t);
3232
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
@@ -88,7 +88,7 @@ inline static bool is_whitespace(char c) {
8888
static const uint32_t default_max_processors_count = CPU_SETSIZE;
8989
#endif
9090

91-
static bool uint32_parser(const char* text_start, const char* text_end, void* context) {
91+
static bool uint32_parser(const char* filename, const char* text_start, const char* text_end, void* context) {
9292
if (text_start == text_end) {
9393
cpuinfo_log_error("failed to parse file %s: file is empty", KERNEL_MAX_FILENAME);
9494
return false;
@@ -98,13 +98,13 @@ static bool uint32_parser(const char* text_start, const char* text_end, void* co
9898
const char* parsed_end = parse_number(text_start, text_end, &kernel_max);
9999
if (parsed_end == text_start) {
100100
cpuinfo_log_error("failed to parse file %s: \"%.*s\" is not an unsigned number",
101-
KERNEL_MAX_FILENAME, (int) (text_end - text_start), text_start);
101+
filename, (int) (text_end - text_start), text_start);
102102
return false;
103103
} else {
104104
for (const char* char_ptr = parsed_end; char_ptr != text_end; char_ptr++) {
105105
if (!is_whitespace(*char_ptr)) {
106106
cpuinfo_log_warning("non-whitespace characters \"%.*s\" following number in file %s are ignored",
107-
(int) (text_end - char_ptr), char_ptr, KERNEL_MAX_FILENAME);
107+
(int) (text_end - char_ptr), char_ptr, filename);
108108
break;
109109
}
110110
}
@@ -255,7 +255,7 @@ static bool max_processor_number_parser(uint32_t processor_list_start, uint32_t
255255
uint32_t cpuinfo_linux_get_max_possible_processor(uint32_t max_processors_count) {
256256
uint32_t max_possible_processor = 0;
257257
if (!cpuinfo_linux_parse_cpulist(POSSIBLE_CPULIST_FILENAME, max_processor_number_parser, &max_possible_processor)) {
258-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
258+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
259259
cpuinfo_log_error("failed to parse the list of possible processors in %s", POSSIBLE_CPULIST_FILENAME);
260260
#else
261261
cpuinfo_log_warning("failed to parse the list of possible processors in %s", POSSIBLE_CPULIST_FILENAME);
@@ -274,7 +274,7 @@ uint32_t cpuinfo_linux_get_max_possible_processor(uint32_t max_processors_count)
274274
uint32_t cpuinfo_linux_get_max_present_processor(uint32_t max_processors_count) {
275275
uint32_t max_present_processor = 0;
276276
if (!cpuinfo_linux_parse_cpulist(PRESENT_CPULIST_FILENAME, max_processor_number_parser, &max_present_processor)) {
277-
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
277+
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
278278
cpuinfo_log_error("failed to parse the list of present processors in %s", PRESENT_CPULIST_FILENAME);
279279
#else
280280
cpuinfo_log_warning("failed to parse the list of present processors in %s", PRESENT_CPULIST_FILENAME);

src/linux/smallfile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ bool cpuinfo_linux_parse_small_file(const char* filename, size_t buffer_size, cp
5555
}
5656
} while (bytes_read != 0);
5757

58-
status = callback(buffer, &buffer[buffer_position], context);
58+
status = callback(filename, buffer, &buffer[buffer_position], context);
5959

6060
cleanup:
6161
if (file != -1) {

src/riscv/api.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <cpuinfo.h>
66
#include <cpuinfo/common.h>
7+
#include <cpuinfo/internal-api.h>
78

89
/* RISC-V Vendor IDs. */
910
enum cpuinfo_riscv_chipset_vendor {
@@ -40,3 +41,12 @@ CPUINFO_INTERNAL void cpuinfo_riscv_decode_vendor_uarch(
4041
uint32_t imp_id,
4142
enum cpuinfo_vendor vendor[restrict static 1],
4243
enum cpuinfo_uarch uarch[restrict static 1]);
44+
45+
CPUINFO_INTERNAL void cpuinfo_riscv_decode_cache(
46+
enum cpuinfo_uarch uarch,
47+
struct cpuinfo_cache l1i[restrict static 1],
48+
struct cpuinfo_cache l1d[restrict static 1],
49+
struct cpuinfo_cache l2[restrict static 1]);
50+
51+
CPUINFO_INTERNAL uint32_t cpuinfo_riscv_compute_max_cache_size(
52+
const struct cpuinfo_processor processor[restrict static 1]);

src/riscv/cache.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <inttypes.h>
2+
3+
#include <cpuinfo.h>
4+
#include <cpuinfo/internal-api.h>
5+
#include <cpuinfo/log.h>
6+
7+
void cpuinfo_riscv_decode_cache(
8+
enum cpuinfo_uarch uarch,
9+
struct cpuinfo_cache l1i[restrict static 1],
10+
struct cpuinfo_cache l1d[restrict static 1],
11+
struct cpuinfo_cache l2[restrict static 1])
12+
{
13+
switch(uarch) {
14+
case cpuinfo_uarch_u74_mc:
15+
*l1i = (struct cpuinfo_cache) {
16+
.size = 32 * 1024,
17+
.associativity = 2,
18+
.line_size = 64
19+
};
20+
*l1d = (struct cpuinfo_cache) {
21+
.size = 32 * 1024,
22+
.associativity = 4,
23+
.line_size = 64
24+
};
25+
*l2 = (struct cpuinfo_cache) {
26+
.size = 2 * 1024 * 1024,
27+
.associativity = 16,
28+
.line_size = 64
29+
};
30+
break;
31+
default:
32+
cpuinfo_log_warning("target uarch not recognized; cache data is not populated");
33+
}
34+
l1i->sets = l1i->size / (l1i->associativity * l1i->line_size);
35+
l1i->partitions = 1;
36+
l1d->sets = l1d->size / (l1d->associativity * l1d->line_size);
37+
l1d->partitions = 1;
38+
if (l2->size != 0) {
39+
l2->sets = l2->size / (l2->associativity * l2->line_size);
40+
l2->partitions = 1;
41+
}
42+
}
43+
44+
uint32_t cpuinfo_riscv_compute_max_cache_size(const struct cpuinfo_processor* processor) {
45+
switch(processor->core->uarch) {
46+
case cpuinfo_uarch_u74_mc:
47+
return 2 * 1024 * 1024;
48+
default:
49+
cpuinfo_log_warning("target uarch not recognized; mas cache size is not populated");
50+
return 0;
51+
}
52+
}

src/riscv/linux/api.h

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,26 @@
11
#pragma once
22

3+
#include <inttypes.h>
4+
35
#include <cpuinfo.h>
46
#include <cpuinfo/common.h>
57

8+
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
9+
/* arch/riscv/include/uapi/asm/hwcap.h */
10+
#define CPUINFO_RISCV_LINUX_FEATURE_A UINT32_C(0x00000001)
11+
#define CPUINFO_RISCV_LINUX_FEATURE_C UINT32_C(0x00000004)
12+
#define CPUINFO_RISCV_LINUX_FEATURE_D UINT32_C(0x00000008)
13+
#define CPUINFO_RISCV_LINUX_FEATURE_F UINT32_C(0x00000020)
14+
#define CPUINFO_RISCV_LINUX_FEATURE_I UINT32_C(0x00000100)
15+
#define CPUINFO_RISCV_LINUX_FEATURE_M UINT32_C(0x00001000)
16+
#define CPUINFO_RISCV_LINUX_FEATURE_V UINT32_C(0x00200000)
17+
#endif
18+
19+
#define CPUINFO_RISCV_LINUX_VALID_ARCHITECTURE UINT32_C(0x10000000)
20+
#define CPUINFO_RISCV_LINUX_VALID_IMPLEMENTER UINT32_C(0x20000000)
21+
#define CPUINFO_RISCV_LINUX_VALID_PROCESSOR UINT32_C(0x40000000)
22+
#define CPUINFO_RISCV_LINUX_VALID_FEATURES UINT32_C(0x80000000)
23+
624
/**
725
* Definition of a RISC-V Linux processor. It is composed of the base processor
826
* definition in "include/cpuinfo.h" and flags specific to RISC-V Linux
@@ -41,6 +59,9 @@ struct cpuinfo_riscv_linux_processor {
4159
* is the same for all logical processors on the same package.
4260
*/
4361
uint32_t package_leader_id;
62+
63+
/* RISC-V ISA extensions supported by this processor */
64+
uint32_t features;
4465
};
4566

4667
/**
@@ -65,5 +86,16 @@ CPUINFO_INTERNAL void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
6586
enum cpuinfo_vendor vendor[restrict static 1],
6687
enum cpuinfo_uarch uarch[restrict static 1]);
6788

89+
CPUINFO_INTERNAL void cpuinfo_riscv_linux_count_cluster_processors(
90+
uint32_t max_processors,
91+
struct cpuinfo_riscv_linux_processor processors[restrict static max_processors]);
92+
93+
CPUINFO_INTERNAL void cpuinfo_riscv_linux_hwcap_from_getauxval(
94+
uint32_t hwcap[restrict static 1]);
95+
96+
CPUINFO_INTERNAL bool cpuinfo_riscv_linux_parse_proc_cpuinfo(
97+
uint32_t max_processors_count,
98+
struct cpuinfo_riscv_linux_processor processors[restrict static max_processors_count]);
99+
68100
/* Used to determine which uarch is associated with the current thread. */
69-
extern CPUINFO_INTERNAL const uint32_t* cpuinfo_linux_cpu_to_uarch_index_map;
101+
extern CPUINFO_INTERNAL const uint32_t* cpuinfo_linux_cpu_to_uarch_index_map;

0 commit comments

Comments
 (0)