aboutsummaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2024-06-27 04:54:47 +0000
committerRichard Henderson <richard.henderson@linaro.org>2024-07-03 10:24:12 -0700
commitb86c6ba689662256ea32f3e27927524ccb13f81d (patch)
tree1515c9f55843bcd5cbdf78e7fc714c2734caab62 /util
parentab089908b42f22e7edfa0d40db963c136ab35419 (diff)
util/cpuinfo-riscv: Support host/cpuinfo.h for riscv
Move detection code out of tcg, similar to other hosts. Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'util')
-rw-r--r--util/cpuinfo-riscv.c85
-rw-r--r--util/meson.build2
2 files changed, 87 insertions, 0 deletions
diff --git a/util/cpuinfo-riscv.c b/util/cpuinfo-riscv.c
new file mode 100644
index 0000000000..1236ee5fa4
--- /dev/null
+++ b/util/cpuinfo-riscv.c
@@ -0,0 +1,85 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Host specific cpu identification for RISC-V.
+ */
+
+#include "qemu/osdep.h"
+#include "host/cpuinfo.h"
+
+unsigned cpuinfo;
+static volatile sig_atomic_t got_sigill;
+
+static void sigill_handler(int signo, siginfo_t *si, void *data)
+{
+ /* Skip the faulty instruction */
+ ucontext_t *uc = (ucontext_t *)data;
+ uc->uc_mcontext.__gregs[REG_PC] += 4;
+
+ got_sigill = 1;
+}
+
+/* Called both as constructor and (possibly) via other constructors. */
+unsigned __attribute__((constructor)) cpuinfo_init(void)
+{
+ unsigned left = CPUINFO_ZBA | CPUINFO_ZBB | CPUINFO_ZICOND;
+ unsigned info = cpuinfo;
+
+ if (info) {
+ return info;
+ }
+
+ /* Test for compile-time settings. */
+#if defined(__riscv_arch_test) && defined(__riscv_zba)
+ info |= CPUINFO_ZBA;
+#endif
+#if defined(__riscv_arch_test) && defined(__riscv_zbb)
+ info |= CPUINFO_ZBB;
+#endif
+#if defined(__riscv_arch_test) && defined(__riscv_zicond)
+ info |= CPUINFO_ZICOND;
+#endif
+ left &= ~info;
+
+ if (left) {
+ struct sigaction sa_old, sa_new;
+
+ memset(&sa_new, 0, sizeof(sa_new));
+ sa_new.sa_flags = SA_SIGINFO;
+ sa_new.sa_sigaction = sigill_handler;
+ sigaction(SIGILL, &sa_new, &sa_old);
+
+ if (left & CPUINFO_ZBA) {
+ /* Probe for Zba: add.uw zero,zero,zero. */
+ got_sigill = 0;
+ asm volatile(".insn r 0x3b, 0, 0x04, zero, zero, zero"
+ : : : "memory");
+ info |= got_sigill ? 0 : CPUINFO_ZBA;
+ left &= ~CPUINFO_ZBA;
+ }
+
+ if (left & CPUINFO_ZBB) {
+ /* Probe for Zbb: andn zero,zero,zero. */
+ got_sigill = 0;
+ asm volatile(".insn r 0x33, 7, 0x20, zero, zero, zero"
+ : : : "memory");
+ info |= got_sigill ? 0 : CPUINFO_ZBB;
+ left &= ~CPUINFO_ZBB;
+ }
+
+ if (left & CPUINFO_ZICOND) {
+ /* Probe for Zicond: czero.eqz zero,zero,zero. */
+ got_sigill = 0;
+ asm volatile(".insn r 0x33, 5, 0x07, zero, zero, zero"
+ : : : "memory");
+ info |= got_sigill ? 0 : CPUINFO_ZICOND;
+ left &= ~CPUINFO_ZICOND;
+ }
+
+ sigaction(SIGILL, &sa_old, NULL);
+ assert(left == 0);
+ }
+
+ info |= CPUINFO_ALWAYS;
+ cpuinfo = info;
+ return info;
+}
diff --git a/util/meson.build b/util/meson.build
index 72b505df11..5d8bef9891 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -127,4 +127,6 @@ elif cpu == 'loongarch64'
util_ss.add(files('cpuinfo-loongarch.c'))
elif cpu in ['ppc', 'ppc64']
util_ss.add(files('cpuinfo-ppc.c'))
+elif cpu in ['riscv32', 'riscv64']
+ util_ss.add(files('cpuinfo-riscv.c'))
endif