Browse Source
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>pull/286/head
5 changed files with 139 additions and 101 deletions
@ -0,0 +1,23 @@ |
|||
/*
|
|||
* SPDX-License-Identifier: GPL-2.0-or-later |
|||
* Host specific cpu identification for RISC-V. |
|||
*/ |
|||
|
|||
#ifndef HOST_CPUINFO_H |
|||
#define HOST_CPUINFO_H |
|||
|
|||
#define CPUINFO_ALWAYS (1u << 0) /* so cpuinfo is nonzero */ |
|||
#define CPUINFO_ZBA (1u << 1) |
|||
#define CPUINFO_ZBB (1u << 2) |
|||
#define CPUINFO_ZICOND (1u << 3) |
|||
|
|||
/* Initialized with a constructor. */ |
|||
extern unsigned cpuinfo; |
|||
|
|||
/*
|
|||
* We cannot rely on constructor ordering, so other constructors must |
|||
* use the function interface rather than the variable above. |
|||
*/ |
|||
unsigned cpuinfo_init(void); |
|||
|
|||
#endif /* HOST_CPUINFO_H */ |
|||
@ -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; |
|||
} |
|||
Loading…
Reference in new issue