diff --git a/src/lib_jit.c b/src/lib_jit.c index a18032621..a1f8ce94f 100644 --- a/src/lib_jit.c +++ b/src/lib_jit.c @@ -698,23 +698,26 @@ JIT_PARAMDEF(JIT_PARAMINIT) #endif #if LJ_TARGET_RISCV64 && LJ_TARGET_POSIX -#include -#include -static sigjmp_buf sigbuf = {0}; -static void detect_sigill(int sig) -{ - siglongjmp(sigbuf, 1); -} + +#if LJ_TARGET_LINUX +#include + +struct riscv_hwprobe hwprobe_requests[] = { + {RISCV_HWPROBE_KEY_IMA_EXT_0} +}; + +const uint64_t *hwprobe_ext = &hwprobe_requests[0].value; + +int hwprobe_ret = 0; +#endif static int riscv_compressed() { #if defined(__riscv_c) || defined(__riscv_compressed) /* Don't bother checking for RVC -- would crash before getting here. */ return 1; -#elif defined(__GNUC__) - /* c.nop; c.nop; */ - __asm__(".4byte 0x00010001"); - return 1; +#elif LJ_TARGET_LINUX + return (hwprobe_ret == 0 && ((*hwprobe_ext) & RISCV_HWPROBE_IMA_C)) ? 1 : 0; #else return 0; #endif @@ -725,11 +728,8 @@ static int riscv_zba() #if defined(__riscv_b) || defined(__riscv_zba) /* Don't bother checking for Zba -- would crash before getting here. */ return 1; -#elif defined(__GNUC__) - /* Don't bother verifying the result, just check if the instruction exists. */ - /* add.uw zero, zero, zero */ - __asm__(".4byte 0x0800003b"); - return 1; +#elif LJ_TARGET_LINUX + return (hwprobe_ret == 0 && ((*hwprobe_ext) & RISCV_HWPROBE_EXT_ZBA)) ? 1 : 0; #else return 0; #endif @@ -740,11 +740,8 @@ static int riscv_zbb() #if defined(__riscv_b) || defined(__riscv_zbb) /* Don't bother checking for Zbb -- would crash before getting here. */ return 1; -#elif defined(__GNUC__) - register int t asm ("a0"); - /* addi a0, zero, 255; sext.b a0, a0; */ - __asm__("addi a0, zero, 255\n\t.4byte 0x60451513"); - return t < 0; +#elif LJ_TARGET_LINUX + return (hwprobe_ret == 0 && ((*hwprobe_ext) & RISCV_HWPROBE_EXT_ZBB)) ? 1 : 0; #else return 0; #endif @@ -755,10 +752,8 @@ static int riscv_zicond() #if defined(__riscv_zicond) /* Don't bother checking for Zicond -- would crash before getting here. */ return 1; -#elif defined(__GNUC__) - /* czero.eqz zero, zero, zero; */ - __asm__(".4byte 0x0e005033"); - return 1; +#elif LJ_TARGET_LINUX + return (hwprobe_ret == 0 && ((*hwprobe_ext) & RISCV_HWPROBE_EXT_ZICOND)) ? 1 : 0; #else return 0; #endif @@ -766,23 +761,17 @@ static int riscv_zicond() static int riscv_xthead() { -#if defined(__GNUC__) - register int t asm ("a0"); - /* C906 & C910 & C908 all have "xtheadc", XTheadBb subset "xtheadc". */ - /* Therefore assume XThead* are present if XTheadBb is present. */ - /* addi a0, zero, 255; th.ext a0, a0, 7, 0; */ - __asm__("addi a0, zero, 255\n\t.4byte 0x1c05250b"); - return t == -1; /* In case of collision with other vendor extensions. */ -#else - return 0; -#endif +/* +** Hardcoded as there's no easy way of detection: +** - SIGILL have some trouble with libluajit as we speak +** - Checking mvendorid looks good, but might not be reliable. +*/ + return 0; } static uint32_t riscv_probe(int (*func)(void), uint32_t flag) { - if (sigsetjmp(sigbuf, 1) == 0) { - return func() ? flag : 0; - } else return 0; + return func() ? flag : 0; } #endif @@ -861,16 +850,20 @@ static uint32_t jit_cpudetect(void) #elif LJ_TARGET_RISCV64 #if LJ_HASJIT - /* SIGILL-based detection of RVC, Zba, Zbb and XThead. Welcome to the future. */ - struct sigaction old = {0}, act = {0}; - act.sa_handler = detect_sigill; - sigaction(SIGILL, &act, &old); + +#if LJ_TARGET_LINUX + /* HWPROBE-based detection of RVC, Zba, Zbb and Zicond. */ + hwprobe_ret = syscall(__NR_riscv_hwprobe, &hwprobe_requests, + sizeof(hwprobe_requests) / sizeof(struct riscv_hwprobe), 0, + NULL, 0); + flags |= riscv_probe(riscv_compressed, JIT_F_RVC); flags |= riscv_probe(riscv_zba, JIT_F_RVZba); flags |= riscv_probe(riscv_zbb, JIT_F_RVZbb); flags |= riscv_probe(riscv_zicond, JIT_F_RVZicond); flags |= riscv_probe(riscv_xthead, JIT_F_RVXThead); - sigaction(SIGILL, &old, NULL); + +#endif /* Detect V/P? */ /* V have no hardware available, P not ratified yet. */ diff --git a/src/lj_jit.h b/src/lj_jit.h index 895759565..4c3a5dbdf 100644 --- a/src/lj_jit.h +++ b/src/lj_jit.h @@ -78,6 +78,34 @@ #define JIT_F_CPUSTRING "\003RVC\003Zba\003Zbb\006Zicond\006XThead" +#if LJ_TARGET_LINUX +#include + +#ifndef __NR_riscv_hwprobe +#ifndef __NR_arch_specific_syscall +#define __NR_arch_specific_syscall 244 +#endif +#define __NR_riscv_hwprobe (__NR_arch_specific_syscall + 14) +#endif + +struct riscv_hwprobe { + int64_t key; + uint64_t value; +}; + +#define RISCV_HWPROBE_KEY_MVENDORID 0 +#define RISCV_HWPROBE_KEY_MARCHID 1 +#define RISCV_HWPROBE_KEY_MIMPID 2 +#define RISCV_HWPROBE_KEY_BASE_BEHAVIOR 3 +#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 + +#define RISCV_HWPROBE_IMA_C (1 << 1) +#define RISCV_HWPROBE_EXT_ZBA (1 << 3) +#define RISCV_HWPROBE_EXT_ZBB (1 << 4) +#define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35) + +#endif + #else #define JIT_F_CPUSTRING ""