1b86c6ba6SRichard Henderson /* 2b86c6ba6SRichard Henderson * SPDX-License-Identifier: GPL-2.0-or-later 3b86c6ba6SRichard Henderson * Host specific cpu identification for RISC-V. 4b86c6ba6SRichard Henderson */ 5b86c6ba6SRichard Henderson 6b86c6ba6SRichard Henderson #include "qemu/osdep.h" 7b86c6ba6SRichard Henderson #include "host/cpuinfo.h" 8b86c6ba6SRichard Henderson 9b86c6ba6SRichard Henderson unsigned cpuinfo; 10b86c6ba6SRichard Henderson static volatile sig_atomic_t got_sigill; 11b86c6ba6SRichard Henderson 12b86c6ba6SRichard Henderson static void sigill_handler(int signo, siginfo_t *si, void *data) 13b86c6ba6SRichard Henderson { 14b86c6ba6SRichard Henderson /* Skip the faulty instruction */ 15b86c6ba6SRichard Henderson ucontext_t *uc = (ucontext_t *)data; 16*adc02842SRichard Henderson 17*adc02842SRichard Henderson #ifdef __linux__ 18b86c6ba6SRichard Henderson uc->uc_mcontext.__gregs[REG_PC] += 4; 19*adc02842SRichard Henderson #elif defined(__OpenBSD__) 20*adc02842SRichard Henderson uc->sc_sepc += 4; 21*adc02842SRichard Henderson #else 22*adc02842SRichard Henderson # error Unsupported OS 23*adc02842SRichard Henderson #endif 24b86c6ba6SRichard Henderson 25b86c6ba6SRichard Henderson got_sigill = 1; 26b86c6ba6SRichard Henderson } 27b86c6ba6SRichard Henderson 28b86c6ba6SRichard Henderson /* Called both as constructor and (possibly) via other constructors. */ 29b86c6ba6SRichard Henderson unsigned __attribute__((constructor)) cpuinfo_init(void) 30b86c6ba6SRichard Henderson { 31b86c6ba6SRichard Henderson unsigned left = CPUINFO_ZBA | CPUINFO_ZBB | CPUINFO_ZICOND; 32b86c6ba6SRichard Henderson unsigned info = cpuinfo; 33b86c6ba6SRichard Henderson 34b86c6ba6SRichard Henderson if (info) { 35b86c6ba6SRichard Henderson return info; 36b86c6ba6SRichard Henderson } 37b86c6ba6SRichard Henderson 38b86c6ba6SRichard Henderson /* Test for compile-time settings. */ 39b86c6ba6SRichard Henderson #if defined(__riscv_arch_test) && defined(__riscv_zba) 40b86c6ba6SRichard Henderson info |= CPUINFO_ZBA; 41b86c6ba6SRichard Henderson #endif 42b86c6ba6SRichard Henderson #if defined(__riscv_arch_test) && defined(__riscv_zbb) 43b86c6ba6SRichard Henderson info |= CPUINFO_ZBB; 44b86c6ba6SRichard Henderson #endif 45b86c6ba6SRichard Henderson #if defined(__riscv_arch_test) && defined(__riscv_zicond) 46b86c6ba6SRichard Henderson info |= CPUINFO_ZICOND; 47b86c6ba6SRichard Henderson #endif 48b86c6ba6SRichard Henderson left &= ~info; 49b86c6ba6SRichard Henderson 50b86c6ba6SRichard Henderson if (left) { 51b86c6ba6SRichard Henderson struct sigaction sa_old, sa_new; 52b86c6ba6SRichard Henderson 53b86c6ba6SRichard Henderson memset(&sa_new, 0, sizeof(sa_new)); 54b86c6ba6SRichard Henderson sa_new.sa_flags = SA_SIGINFO; 55b86c6ba6SRichard Henderson sa_new.sa_sigaction = sigill_handler; 56b86c6ba6SRichard Henderson sigaction(SIGILL, &sa_new, &sa_old); 57b86c6ba6SRichard Henderson 58b86c6ba6SRichard Henderson if (left & CPUINFO_ZBA) { 59b86c6ba6SRichard Henderson /* Probe for Zba: add.uw zero,zero,zero. */ 60b86c6ba6SRichard Henderson got_sigill = 0; 61b86c6ba6SRichard Henderson asm volatile(".insn r 0x3b, 0, 0x04, zero, zero, zero" 62b86c6ba6SRichard Henderson : : : "memory"); 63b86c6ba6SRichard Henderson info |= got_sigill ? 0 : CPUINFO_ZBA; 64b86c6ba6SRichard Henderson left &= ~CPUINFO_ZBA; 65b86c6ba6SRichard Henderson } 66b86c6ba6SRichard Henderson 67b86c6ba6SRichard Henderson if (left & CPUINFO_ZBB) { 68b86c6ba6SRichard Henderson /* Probe for Zbb: andn zero,zero,zero. */ 69b86c6ba6SRichard Henderson got_sigill = 0; 70b86c6ba6SRichard Henderson asm volatile(".insn r 0x33, 7, 0x20, zero, zero, zero" 71b86c6ba6SRichard Henderson : : : "memory"); 72b86c6ba6SRichard Henderson info |= got_sigill ? 0 : CPUINFO_ZBB; 73b86c6ba6SRichard Henderson left &= ~CPUINFO_ZBB; 74b86c6ba6SRichard Henderson } 75b86c6ba6SRichard Henderson 76b86c6ba6SRichard Henderson if (left & CPUINFO_ZICOND) { 77b86c6ba6SRichard Henderson /* Probe for Zicond: czero.eqz zero,zero,zero. */ 78b86c6ba6SRichard Henderson got_sigill = 0; 79b86c6ba6SRichard Henderson asm volatile(".insn r 0x33, 5, 0x07, zero, zero, zero" 80b86c6ba6SRichard Henderson : : : "memory"); 81b86c6ba6SRichard Henderson info |= got_sigill ? 0 : CPUINFO_ZICOND; 82b86c6ba6SRichard Henderson left &= ~CPUINFO_ZICOND; 83b86c6ba6SRichard Henderson } 84b86c6ba6SRichard Henderson 85b86c6ba6SRichard Henderson sigaction(SIGILL, &sa_old, NULL); 86b86c6ba6SRichard Henderson assert(left == 0); 87b86c6ba6SRichard Henderson } 88b86c6ba6SRichard Henderson 89b86c6ba6SRichard Henderson info |= CPUINFO_ALWAYS; 90b86c6ba6SRichard Henderson cpuinfo = info; 91b86c6ba6SRichard Henderson return info; 92b86c6ba6SRichard Henderson } 93