riscv64: add <sys/hwprobe.h>.
This is source compatible with the current proposal for glibc.
Bug: https://github.com/google/android-riscv64/issues/27
Test: treehugger
Change-Id: I428777e4eac1fe643d442a93a4b3ad1fdf0ffd97
diff --git a/docs/status.md b/docs/status.md
index fc68b80..5514935 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -62,7 +62,8 @@
functions for avoiding $TZ if you need to use multiple timezones in
multi-threaded C).
* `mbsrtowcs_l` and `wcsrtombs_l` aliases for `mbsrtowcs` and `wcsrtombs`.
- * New system call wrapper: `__riscv_flush_icache` (`<sys/cachectl.h>`).
+ * New system call wrappers: `__riscv_flush_icache` (`<sys/cachectl.h>`),
+ `__riscv_hwprobe` (`<sys/hwprobe.h>`).
New libc functions in U (API level 34):
* `close_range` and `copy_file_range` (Linux-specific GNU extensions).
diff --git a/libc/SECCOMP_ALLOWLIST_COMMON.TXT b/libc/SECCOMP_ALLOWLIST_COMMON.TXT
index 4a8d501..67b662e 100644
--- a/libc/SECCOMP_ALLOWLIST_COMMON.TXT
+++ b/libc/SECCOMP_ALLOWLIST_COMMON.TXT
@@ -74,5 +74,3 @@
int rt_sigtimedwait_time64(const sigset64_t*, siginfo_t*, const timespec64*, size_t) lp32
int futex_time64(int*, int, int, const timespec64*, int*, int) lp32
int sched_rr_get_interval_time64(pid_t, timespec64*) lp32
-# Since Linux 6.4, not in glibc (https://www.openwall.com/lists/libc-coord/2023/07/13/1).
-int riscv_hwprobe(riscv_hwprobe*, size_t, size_t, unsigned long*, unsigned) riscv64
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index e8dde7c..079acf9 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -357,6 +357,7 @@
# riscv64-specific
int __riscv_flush_icache:riscv_flush_icache(void*, void*, unsigned long) riscv64
+int __riscv_hwprobe:riscv_hwprobe(riscv_hwprobe*, size_t, size_t, unsigned long*, unsigned) riscv64
# x86-specific
int __set_thread_area:set_thread_area(void*) x86
diff --git a/libc/include/sys/hwprobe.h b/libc/include/sys/hwprobe.h
new file mode 100644
index 0000000..f2fd98d
--- /dev/null
+++ b/libc/include/sys/hwprobe.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if __riscv
+
+/**
+ * @file sys/hwprobe.h
+ * @brief RISC-V hardware probing.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/* Pull in struct riscv_hwprobe and corresponding constants. */
+#include <asm/hwprobe.h>
+
+__BEGIN_DECLS
+
+/**
+ * [__riscv_hwprobe(2)](https://docs.kernel.org/riscv/hwprobe.html)
+ * queries hardware characteristics.
+ *
+ * A `__cpu_count` of 0 and null `__cpus` means "all online cpus".
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ */
+int __riscv_hwprobe(struct riscv_hwprobe* _Nonnull __pairs, size_t __pair_count, size_t __cpu_count, unsigned long* _Nullable __cpus, unsigned __flags);
+
+__END_DECLS
+
+#endif
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 86c8288..e90618d 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1590,6 +1590,7 @@
mbsrtowcs_l;
mktime_z;
__riscv_flush_icache; # riscv64
+ __riscv_hwprobe; # riscv64
timespec_getres;
tzalloc;
tzfree;
diff --git a/tests/Android.bp b/tests/Android.bp
index 8dc8eaf..a4298ab 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -472,6 +472,7 @@
"sys_auxv_test.cpp",
"sys_cachectl_test.cpp",
"sys_epoll_test.cpp",
+ "sys_hwprobe_test.cpp",
"sys_mman_test.cpp",
"sys_msg_test.cpp",
"sys_param_test.cpp",
diff --git a/tests/sys_hwprobe_test.cpp b/tests/sys_hwprobe_test.cpp
new file mode 100644
index 0000000..15028ff
--- /dev/null
+++ b/tests/sys_hwprobe_test.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gtest/gtest.h>
+
+#if __has_include(<sys/hwprobe.h>)
+#include <sys/hwprobe.h>
+#endif
+
+TEST(sys_hwprobe, __riscv_hwprobe) {
+#if defined(__riscv) && __has_include(<sys/cachectl.h>)
+ riscv_hwprobe probes[] = {{.key = RISCV_HWPROBE_KEY_IMA_EXT_0},
+ {.key = RISCV_HWPROBE_KEY_CPUPERF_0}};
+ ASSERT_EQ(0, __riscv_hwprobe(probes, 2, 0, nullptr, 0));
+ EXPECT_EQ(RISCV_HWPROBE_KEY_IMA_EXT_0, probes[0].key);
+ EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_IMA_FD) != 0);
+ EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_IMA_C) != 0);
+ // TODO: remove #define when our uapi headers are new enough.
+#define RISCV_HWPROBE_IMA_V (1 << 2)
+ EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_IMA_V) != 0);
+ // TODO: remove #ifs when our kernel is new enough.
+#if defined(RISCV_HWPROBE_EXT_ZBA)
+ EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_EXT_ZBA) != 0);
+#endif
+#if defined(RISCV_HWPROBE_EXT_ZBB)
+ EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_EXT_ZBB) != 0);
+#endif
+#if defined(RISCV_HWPROBE_EXT_ZBS)
+ EXPECT_TRUE((probes[0].value & RISCV_HWPROBE_EXT_ZBS) != 0);
+#endif
+
+ EXPECT_EQ(RISCV_HWPROBE_KEY_CPUPERF_0, probes[1].key);
+ EXPECT_TRUE((probes[1].value & RISCV_HWPROBE_MISALIGNED_MASK) == RISCV_HWPROBE_MISALIGNED_FAST);
+#else
+ GTEST_SKIP() << "__riscv_hwprobe requires riscv64";
+#endif
+}