diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2024-06-27 04:54:47 +0000 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2024-07-03 10:24:12 -0700 |
commit | b86c6ba689662256ea32f3e27927524ccb13f81d (patch) | |
tree | 1515c9f55843bcd5cbdf78e7fc714c2734caab62 /util | |
parent | ab089908b42f22e7edfa0d40db963c136ab35419 (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.c | 85 | ||||
-rw-r--r-- | util/meson.build | 2 |
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 |