Skip to content

Commit 313524a

Browse files
authored
Fix RISC-V Linux build (#212)
Cpuinfo was failing to build on RISC-V Linux distributions, e.g., Ubuntu 23.10, as it includes a header file sys/hwprobe.h that is not yet provided by glibc (although it is provided by bionic). We fix the issue by only including sys/hwprobe.h when building for Android, and invoking the hwprobe syscall directly on other Linux distributions. The Android specific check can be removed in the future once sys/hwprobe.h becomes available in glibc.
1 parent 2f4c278 commit 313524a

File tree

1 file changed

+79
-1
lines changed

1 file changed

+79
-1
lines changed

src/riscv/linux/riscv-hw.c

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,74 @@
1-
#include <sys/hwprobe.h>
1+
/*
2+
* Only enable the C standard library hwprobe interface on Android for now.
3+
* Patches to add a compatible hwprobe API to glibc are available but not
4+
* merged at the time of writing and so cannot easily be tested. The
5+
* #ifdef __ANDROID__ check will be removed in the future.
6+
*/
7+
#ifdef __ANDROID__
8+
#ifdef __has_include
9+
#if __has_include (<sys/hwprobe.h>)
10+
#define CPUINFO_RISCV_LINUX_HAVE_C_HWPROBE
11+
#include <sys/hwprobe.h>
12+
#endif
13+
#endif
14+
#endif
15+
216
#include <sched.h>
317

418
#include <cpuinfo/log.h>
519
#include <riscv/api.h>
620
#include <riscv/linux/api.h>
721

22+
#ifndef CPUINFO_RISCV_LINUX_HAVE_C_HWPROBE
23+
24+
#include <unistd.h>
25+
#include <sys/syscall.h>
26+
#include <stdint.h>
27+
28+
struct riscv_hwprobe {
29+
int64_t key;
30+
uint64_t value;
31+
};
32+
33+
/*
34+
* The standard C library our binary was compiled with does not support
35+
* hwprobe but the kernel on which we are running might do. The
36+
* constants below are copied from
37+
* /usr/include/riscv64-linux-gnu/asm/hwprobe.h. They allow us to
38+
* invoke the hwprobe syscall directly. We duplicate the constants
39+
* rather than including the kernel hwprobe.h header, as this header
40+
* will only be present if we're building Linux 6.4 or greater.
41+
*/
42+
43+
#define RISCV_HWPROBE_KEY_MVENDORID 0
44+
#define RISCV_HWPROBE_KEY_MARCHID 1
45+
#define RISCV_HWPROBE_KEY_MIMPID 2
46+
#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3
47+
#define RISCV_HWPROBE_BASE_BEHAVIOR_IMA (1 << 0)
48+
#define RISCV_HWPROBE_KEY_IMA_EXT_0 4
49+
#define RISCV_HWPROBE_IMA_FD (1 << 0)
50+
#define RISCV_HWPROBE_IMA_C (1 << 1)
51+
#define RISCV_HWPROBE_IMA_V (1 << 2)
52+
#define RISCV_HWPROBE_EXT_ZBA (1 << 3)
53+
#define RISCV_HWPROBE_EXT_ZBB (1 << 4)
54+
#define RISCV_HWPROBE_EXT_ZBS (1 << 5)
55+
#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6)
56+
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
57+
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
58+
#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
59+
#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0)
60+
#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)
61+
#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
62+
#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
63+
64+
#ifndef NR_riscv_hwprobe
65+
#ifndef NR_arch_specific_syscall
66+
#define NR_arch_specific_syscall 244
67+
#endif
68+
#define NR_riscv_hwprobe (NR_arch_specific_syscall + 14)
69+
#endif
70+
#endif
71+
872
void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
973
uint32_t processor,
1074
enum cpuinfo_vendor vendor[restrict static 1],
@@ -33,9 +97,23 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
3397
CPU_SET_S(processor, cpu_set_size, cpu_set);
3498

3599
/* Request all available information from hwprobe. */
100+
#ifndef CPUINFO_RISCV_LINUX_HAVE_C_HWPROBE
101+
/*
102+
* No standard library support for hwprobe. We'll need to invoke the
103+
* syscall directly. See
104+
*
105+
* https://docs.kernel.org/arch/riscv/hwprobe.html
106+
*
107+
* for more details.
108+
*/
109+
int ret = syscall(NR_riscv_hwprobe, pairs, pairs_count,
110+
cpu_set_size, (unsigned long*)cpu_set,
111+
0 /* flags */);
112+
#else
36113
int ret = __riscv_hwprobe(pairs, pairs_count,
37114
cpu_set_size, (unsigned long*)cpu_set,
38115
0 /* flags */);
116+
#endif
39117
if (ret < 0) {
40118
cpuinfo_log_warning("failed to get hwprobe information, err: %d", ret);
41119
goto cleanup;

0 commit comments

Comments
 (0)