adc028428a
Reported-by: Brad Smith <brad@comstyle.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Acked-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
93 lines
2.4 KiB
C
93 lines
2.4 KiB
C
/*
|
|
* 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;
|
|
|
|
#ifdef __linux__
|
|
uc->uc_mcontext.__gregs[REG_PC] += 4;
|
|
#elif defined(__OpenBSD__)
|
|
uc->sc_sepc += 4;
|
|
#else
|
|
# error Unsupported OS
|
|
#endif
|
|
|
|
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;
|
|
}
|