diff options
| -rw-r--r-- | CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/core.c | 174 | ||||
| -rw-r--r-- | src/dynarec/la64/la64_lock.h | 2 | ||||
| -rw-r--r-- | src/include/core_arch.h | 50 | ||||
| -rw-r--r-- | src/include/debug.h | 2 | ||||
| -rw-r--r-- | src/include/hostext.h | 52 | ||||
| -rw-r--r-- | src/os/hostext_common.c | 64 | ||||
| -rw-r--r-- | src/os/hostext_linux.c | 227 | ||||
| -rw-r--r-- | src/os/hostext_wine.c | 20 | ||||
| -rw-r--r-- | src/rv64detect.c | 126 | ||||
| -rw-r--r-- | wine/common/wrt.c | 5 | ||||
| -rw-r--r-- | wine/include/wine/compiler.h | 1 | ||||
| -rw-r--r-- | wine/wow64/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | wine/wow64/wowbox64.c | 11 |
14 files changed, 391 insertions, 348 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 4036a282..32b59734 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -364,6 +364,8 @@ set_source_files_properties( set(OS_LINUX_SRC "${BOX64_ROOT}/src/os/backtrace.c" "${BOX64_ROOT}/src/os/emit_signals_linux.c" + "${BOX64_ROOT}/src/os/hostext_common.c" + "${BOX64_ROOT}/src/os/hostext_linux.c" "${BOX64_ROOT}/src/os/freq_linux.c" "${BOX64_ROOT}/src/os/os_linux.c" "${BOX64_ROOT}/src/os/perfmap.c" @@ -1003,7 +1005,6 @@ if(RV64_DYNAREC) "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_arch.c" "${BOX64_ROOT}/src/dynarec/rv64/rv64_printer.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_jmpnext.c" - "${BOX64_ROOT}/src/rv64detect.c" ) set(DYNAREC_ASM ${DYNAREC_ASM} diff --git a/src/core.c b/src/core.c index 059003b3..dae932a6 100644 --- a/src/core.c +++ b/src/core.c @@ -16,10 +16,6 @@ #include <stdarg.h> #include <ctype.h> #ifdef DYNAREC -#ifdef ARM64 -#include <linux/auxvec.h> -#include <asm/hwcap.h> -#endif #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -49,7 +45,7 @@ #include "env.h" #include "cleanup.h" #include "freq.h" -#include "core_arch.h" +#include "hostext.h" box64context_t *my_context = NULL; extern box64env_t box64env; @@ -186,166 +182,6 @@ void my_child_fork() const char* getCpuName(); int getNCpuUnmasked(); -#ifdef DYNAREC -void GatherDynarecExtensions() -{ -#ifdef ARM64 - unsigned long hwcap = real_getauxval(AT_HWCAP); - if(!hwcap) - hwcap = HWCAP_ASIMD; - // first, check all needed extensions, lif half, edsp and fastmult - if((hwcap&HWCAP_ASIMD) == 0) { - printf_log(LOG_INFO, "Missing ASMID cpu support, disabling Dynarec\n"); - SET_BOX64ENV(dynarec, 0); - return; - } - if(hwcap&HWCAP_CRC32) - cpuext.crc32 = 1; - if(hwcap&HWCAP_PMULL) - cpuext.pmull = 1; - if(hwcap&HWCAP_AES) - cpuext.aes = 1; - if(hwcap&HWCAP_ATOMICS) - cpuext.atomics = 1; - #ifdef HWCAP_SHA1 - if(hwcap&HWCAP_SHA1) - cpuext.sha1 = 1; - #endif - #ifdef HWCAP_SHA2 - if(hwcap&HWCAP_SHA2) - cpuext.sha2 = 1; - #endif - #ifdef HWCAP_USCAT - if(hwcap&HWCAP_USCAT) - cpuext.uscat = 1; - #endif - #ifdef HWCAP_FLAGM - if(hwcap&HWCAP_FLAGM) - cpuext.flagm = 1; - #endif - unsigned long hwcap2 = real_getauxval(AT_HWCAP2); - #ifdef HWCAP2_FLAGM2 - if(hwcap2&HWCAP2_FLAGM2) - cpuext.flagm2 = 1; - #endif - #ifdef HWCAP2_FRINT - if(hwcap2&HWCAP2_FRINT) - cpuext.frintts = 1; - #endif - #ifdef HWCAP2_AFP - if(hwcap2&HWCAP2_AFP) - cpuext.afp = 1; - #endif - #ifdef HWCAP2_RNG - if(hwcap2&HWCAP2_RNG) - cpuext.rndr = 1; - #endif - printf_log(LOG_INFO, "Dynarec for ARM64, with extension: ASIMD"); - if(cpuext.aes) - printf_log_prefix(0, LOG_INFO, " AES"); - if(cpuext.crc32) - printf_log_prefix(0, LOG_INFO, " CRC32"); - if(cpuext.pmull) - printf_log_prefix(0, LOG_INFO, " PMULL"); - if(cpuext.atomics) - printf_log_prefix(0, LOG_INFO, " ATOMICS"); - if(cpuext.sha1) - printf_log_prefix(0, LOG_INFO, " SHA1"); - if(cpuext.sha2) - printf_log_prefix(0, LOG_INFO, " SHA2"); - if(cpuext.uscat) - printf_log_prefix(0, LOG_INFO, " USCAT"); - if(cpuext.flagm) - printf_log_prefix(0, LOG_INFO, " FLAGM"); - if(cpuext.flagm2) - printf_log_prefix(0, LOG_INFO, " FLAGM2"); - if(cpuext.frintts) - printf_log_prefix(0, LOG_INFO, " FRINT"); - if(cpuext.afp) - printf_log_prefix(0, LOG_INFO, " AFP"); - if(cpuext.rndr) - printf_log_prefix(0, LOG_INFO, " RNDR"); - printf_log_prefix(0, LOG_INFO, "\n"); -#elif defined(LA64) - printf_log(LOG_INFO, "Dynarec for LoongArch "); - char* p = getenv("BOX64_DYNAREC_LA64NOEXT"); - if(p == NULL || p[0] == '0') { - uint32_t cpucfg2 = 0, idx = 2; - asm volatile("cpucfg %0, %1" : "=r"(cpucfg2) : "r"(idx)); - if (((cpucfg2 >> 6) & 0b11) == 3) { - printf_log_prefix(0, LOG_INFO, "with extension LSX LASX"); - } else { - printf_log(LOG_INFO, "\nMissing LSX and/or LASX extension support, disabling Dynarec\n"); - SET_BOX64ENV(dynarec, 0); - return; - } - - if (cpuext.lbt = ((cpucfg2 >> 18) & 0b1)) - printf_log_prefix(0, LOG_INFO, " LBT_X86"); - if ((cpuext.lam_bh = (cpucfg2 >> 27) & 0b1)) - printf_log_prefix(0, LOG_INFO, " LAM_BH"); - if ((cpuext.lamcas = (cpucfg2 >> 28) & 0b1)) - printf_log_prefix(0, LOG_INFO, " LAMCAS"); - if ((cpuext.scq = (cpucfg2 >> 30) & 0b1)) - printf_log_prefix(0, LOG_INFO, " SCQ"); - } - printf_log_prefix(0, LOG_INFO, "\n"); -#elif defined(RV64) - void RV64_Detect_Function(); - // private env. variable for the developer ;) - char *p = getenv("BOX64_DYNAREC_RV64NOEXT"); - if(p == NULL || strcasecmp(p, "1")) { - RV64_Detect_Function(); - if (p) { - p = strtok(p, ","); - while (p) { - if (!strcasecmp(p, "zba")) cpuext.zba = 0; - if (!strcasecmp(p, "zbb")) cpuext.zbb = 0; - if (!strcasecmp(p, "zbc")) cpuext.zbc = 0; - if (!strcasecmp(p, "zbs")) cpuext.zbs = 0; - if (!strcasecmp(p, "vector")) { - cpuext.vector = 0; - cpuext.xtheadvector = 0; - } - if (!strcasecmp(p, "xtheadba")) cpuext.xtheadba = 0; - if (!strcasecmp(p, "xtheadbb")) cpuext.xtheadbb = 0; - if (!strcasecmp(p, "xtheadbs")) cpuext.xtheadbs = 0; - if (!strcasecmp(p, "xtheadmemidx")) cpuext.xtheadmemidx = 0; - // if (!strcasecmp(p, "xtheadfmemidx")) cpuext.xtheadfmemidx = 0; - // if (!strcasecmp(p, "xtheadmac")) cpuext.xtheadmac = 0; - // if (!strcasecmp(p, "xtheadfmv")) cpuext.xtheadfmv = 0; - if (!strcasecmp(p, "xtheadmempair")) cpuext.xtheadmempair = 0; - if (!strcasecmp(p, "xtheadcondmov")) cpuext.xtheadcondmov = 0; - p = strtok(NULL, ","); - } - } - } - - printf_log(LOG_INFO, "Dynarec for rv64g"); - if (cpuext.vector && !cpuext.xtheadvector) printf_log_prefix(0, LOG_INFO, "v"); - if (cpuext.zba) printf_log_prefix(0, LOG_INFO, "_zba"); - if (cpuext.zbb) printf_log_prefix(0, LOG_INFO, "_zbb"); - if (cpuext.zbc) printf_log_prefix(0, LOG_INFO, "_zbc"); - if (cpuext.zbs) printf_log_prefix(0, LOG_INFO, "_zbs"); - if (cpuext.vector && !cpuext.xtheadvector) printf_log_prefix(0, LOG_INFO, "_zvl%d", cpuext.vlen*8); - if (cpuext.xtheadba) printf_log_prefix(0, LOG_INFO, "_xtheadba"); - if (cpuext.xtheadbb) printf_log_prefix(0, LOG_INFO, "_xtheadbb"); - if (cpuext.xtheadbs) printf_log_prefix(0, LOG_INFO, "_xtheadbs"); - if (cpuext.xtheadmempair) printf_log_prefix(0, LOG_INFO, "_xtheadmempair"); - if (cpuext.xtheadcondmov) printf_log_prefix(0, LOG_INFO, "_xtheadcondmov"); - if (cpuext.xtheadmemidx) printf_log_prefix(0, LOG_INFO, "_xtheadmemidx"); - // Disable the display since these are only detected but never used. - // if(cpuext.xtheadfmemidx) printf_log_prefix(0, LOG_INFO, " xtheadfmemidx"); - // if(cpuext.xtheadmac) printf_log_prefix(0, LOG_INFO, " xtheadmac"); - // if(cpuext.xtheadfmv) printf_log_prefix(0, LOG_INFO, " xtheadfmv"); - if (cpuext.xtheadvector) printf_log_prefix(0, LOG_INFO, "_xthvector"); - printf_log_prefix(0, LOG_INFO, "\n"); -#else -#error Unsupported architecture -#endif -} -#endif - void computeRDTSC() { int hardware = 0; @@ -405,8 +241,12 @@ static void displayMiscInfo() box64_pagesize = 4096; #ifdef DYNAREC - // grab cpu extensions for dynarec usage - GatherDynarecExtensions(); + if (DetectHostCpuFeatures()) + PrintHostCpuFeatures(); + else { + printf_log(LOG_INFO, "Minimum CPU requirements not met, disabling DynaRec\n"); + SET_BOX64ENV(dynarec, 0); + } #endif // grab ncpu and cpu name diff --git a/src/dynarec/la64/la64_lock.h b/src/dynarec/la64/la64_lock.h index c5175c2e..e51267fe 100644 --- a/src/dynarec/la64/la64_lock.h +++ b/src/dynarec/la64/la64_lock.h @@ -1,7 +1,7 @@ #ifndef __LA64_LOCK__H__ #define __LA64_LOCK__H__ #include <stdint.h> -#include "core_arch.h" +#include "hostext.h" extern cpu_ext_t cpuext; diff --git a/src/include/core_arch.h b/src/include/core_arch.h deleted file mode 100644 index f297bcb8..00000000 --- a/src/include/core_arch.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __CORE_ARCH_H__ -#define __CORE_ARCH_H__ -#include <stdint.h> - -#ifdef DYNAREC -typedef union cpu_ext_s { - struct { -#ifdef ARM64 - uint64_t atomics:1; // it's important this is the 1st bit - uint64_t asimd:1; - uint64_t aes:1; - uint64_t pmull:1; - uint64_t crc32:1; - uint64_t sha1:1; - uint64_t sha2:1; - uint64_t uscat:1; - uint64_t flagm:1; - uint64_t flagm2:1; - uint64_t frintts:1; - uint64_t afp:1; - uint64_t rndr:1; -#elif defined(RV64) -uint64_t vlen:8; // Not *8, 8bits should be enugh? that's 2048 vector - uint64_t zba:1; - uint64_t zbb:1; - uint64_t zbc:1; - uint64_t zbs:1; - uint64_t vector:1; // rvv 1.0 or xtheadvector - uint64_t xtheadvector:1; - uint64_t xtheadba:1; - uint64_t xtheadbb:1; - uint64_t xtheadbs:1; - uint64_t xtheadcondmov:1; - uint64_t xtheadmemidx:1; - uint64_t xtheadmempair:1; - uint64_t xtheadfmemidx:1; - uint64_t xtheadmac:1; - uint64_t xtheadfmv:1; -#elif defined(LA64) - uint64_t lbt:1; // it's important it's stay the 1st bit - uint64_t lam_bh:1; - uint64_t lamcas:1; - uint64_t scq:1; -#endif - }; - uint64_t x; -} cpu_ext_t; -#endif - -#endif //__CORE_ARCH_H__ \ No newline at end of file diff --git a/src/include/debug.h b/src/include/debug.h index 57520cbd..a4b2ee53 100644 --- a/src/include/debug.h +++ b/src/include/debug.h @@ -4,7 +4,7 @@ #include <env.h> #include "os.h" -#include "core_arch.h" +#include "hostext.h" typedef struct box64context_s box64context_t; extern box64env_t box64env; diff --git a/src/include/hostext.h b/src/include/hostext.h new file mode 100644 index 00000000..579e76ac --- /dev/null +++ b/src/include/hostext.h @@ -0,0 +1,52 @@ +#ifndef __HOSTEXT_H__ +#define __HOSTEXT_H__ + +#include <stdint.h> + +typedef union cpu_ext_s { + struct { +#ifdef ARM64 + uint64_t atomics : 1; // it's important this is the 1st bit + uint64_t asimd : 1; + uint64_t aes : 1; + uint64_t pmull : 1; + uint64_t crc32 : 1; + uint64_t sha1 : 1; + uint64_t sha2 : 1; + uint64_t uscat : 1; + uint64_t flagm : 1; + uint64_t flagm2 : 1; + uint64_t frintts : 1; + uint64_t afp : 1; + uint64_t rndr : 1; +#elif defined(RV64) + uint64_t vlen : 8; // Not *8, 8bits should be enugh? that's 2048 vector + uint64_t zba : 1; + uint64_t zbb : 1; + uint64_t zbc : 1; + uint64_t zbs : 1; + uint64_t vector : 1; // rvv 1.0 or xtheadvector + uint64_t xtheadvector : 1; + uint64_t xtheadba : 1; + uint64_t xtheadbb : 1; + uint64_t xtheadbs : 1; + uint64_t xtheadcondmov : 1; + uint64_t xtheadmemidx : 1; + uint64_t xtheadmempair : 1; + uint64_t xtheadfmemidx : 1; + uint64_t xtheadmac : 1; + uint64_t xtheadfmv : 1; +#elif defined(LA64) + uint64_t lbt : 1; // it's important it's stay the 1st bit + uint64_t lam_bh : 1; + uint64_t lamcas : 1; + uint64_t scq : 1; +#endif + }; + uint64_t x; +} cpu_ext_t; + +int DetectHostCpuFeatures(void); +void PrintHostCpuFeatures(void); + +#endif //__HOSTEXT_H__ \ No newline at end of file diff --git a/src/os/hostext_common.c b/src/os/hostext_common.c new file mode 100644 index 00000000..258e1af4 --- /dev/null +++ b/src/os/hostext_common.c @@ -0,0 +1,64 @@ +#include "debug.h" + +void PrintHostCpuFeatures(void) +{ +#ifdef ARM64 + printf_log(LOG_INFO, "Dynarec for ARM64, with extension: ASIMD"); + if(cpuext.aes) + printf_log_prefix(0, LOG_INFO, " AES"); + if(cpuext.crc32) + printf_log_prefix(0, LOG_INFO, " CRC32"); + if(cpuext.pmull) + printf_log_prefix(0, LOG_INFO, " PMULL"); + if(cpuext.atomics) + printf_log_prefix(0, LOG_INFO, " ATOMICS"); + if(cpuext.sha1) + printf_log_prefix(0, LOG_INFO, " SHA1"); + if(cpuext.sha2) + printf_log_prefix(0, LOG_INFO, " SHA2"); + if(cpuext.uscat) + printf_log_prefix(0, LOG_INFO, " USCAT"); + if(cpuext.flagm) + printf_log_prefix(0, LOG_INFO, " FLAGM"); + if(cpuext.flagm2) + printf_log_prefix(0, LOG_INFO, " FLAGM2"); + if(cpuext.frintts) + printf_log_prefix(0, LOG_INFO, " FRINT"); + if(cpuext.afp) + printf_log_prefix(0, LOG_INFO, " AFP"); + if(cpuext.rndr) + printf_log_prefix(0, LOG_INFO, " RNDR"); + printf_log_prefix(0, LOG_INFO, "\n"); +#elif defined(LA64) + printf_log(LOG_INFO, "Dynarec for LoongArch with extension LSX LASX"); + if (cpuext.lbt) + printf_log_prefix(0, LOG_INFO, " LBT_X86"); + if (cpuext.lam_bh) + printf_log_prefix(0, LOG_INFO, " LAM_BH"); + if (cpuext.lamcas) + printf_log_prefix(0, LOG_INFO, " LAMCAS"); + if (cpuext.scq) + printf_log_prefix(0, LOG_INFO, " SCQ"); + printf_log_prefix(0, LOG_INFO, "\n"); +#elif defined(RV64) + printf_log(LOG_INFO, "Dynarec for rv64g"); + if (cpuext.vector && !cpuext.xtheadvector) printf_log_prefix(0, LOG_INFO, "v"); + if (cpuext.zba) printf_log_prefix(0, LOG_INFO, "_zba"); + if (cpuext.zbb) printf_log_prefix(0, LOG_INFO, "_zbb"); + if (cpuext.zbc) printf_log_prefix(0, LOG_INFO, "_zbc"); + if (cpuext.zbs) printf_log_prefix(0, LOG_INFO, "_zbs"); + if (cpuext.vector && !cpuext.xtheadvector) printf_log_prefix(0, LOG_INFO, "_zvl%d", cpuext.vlen * 8); + if (cpuext.xtheadba) printf_log_prefix(0, LOG_INFO, "_xtheadba"); + if (cpuext.xtheadbb) printf_log_prefix(0, LOG_INFO, "_xtheadbb"); + if (cpuext.xtheadbs) printf_log_prefix(0, LOG_INFO, "_xtheadbs"); + if (cpuext.xtheadmempair) printf_log_prefix(0, LOG_INFO, "_xtheadmempair"); + if (cpuext.xtheadcondmov) printf_log_prefix(0, LOG_INFO, "_xtheadcondmov"); + if (cpuext.xtheadmemidx) printf_log_prefix(0, LOG_INFO, "_xtheadmemidx"); + // Disable the display since these are only detected but never used. + // if(cpuext.xtheadfmemidx) printf_log_prefix(0, LOG_INFO, " xtheadfmemidx"); + // if(cpuext.xtheadmac) printf_log_prefix(0, LOG_INFO, " xtheadmac"); + // if(cpuext.xtheadfmv) printf_log_prefix(0, LOG_INFO, " xtheadfmv"); + if (cpuext.xtheadvector) printf_log_prefix(0, LOG_INFO, "_xthvector"); + printf_log_prefix(0, LOG_INFO, "\n"); +#endif +} \ No newline at end of file diff --git a/src/os/hostext_linux.c b/src/os/hostext_linux.c new file mode 100644 index 00000000..60c6a21f --- /dev/null +++ b/src/os/hostext_linux.c @@ -0,0 +1,227 @@ +#include "auxval.h" +#include "debug.h" + + +#ifdef ARM64 +#include <linux/auxvec.h> +#include <asm/hwcap.h> +#endif + +#ifdef RV64 +#include <setjmp.h> +#include <signal.h> +#include <sys/mman.h> +#include "dynarec/rv64/rv64_emitter.h" + + +// Detect RV64 extensions, by executing on of the opcode with a SIGILL signal handler + +static sigjmp_buf sigbuf = {0}; +typedef int (*iFiip_t)(int, int, void*); +static void detect_sigill(int sig) +{ + siglongjmp(sigbuf, 1); +} + +static int Check(void* block) +{ + static uint64_t buf[2] = {0}; + // Clear instruction cache + __clear_cache(block, block+box64_pagesize); + // Setup SIGILL signal handler + __sighandler_t old = signal(SIGILL, detect_sigill); + if(sigsetjmp(sigbuf, 1)) { + // didn't work, extension not present + signal(SIGILL, old); + return 0; + } + int result = ((iFiip_t)block)(0, 1, buf); + if (result != 42) { + // wrong result, extension not present + signal(SIGILL, old); + return 0; + } + // done... + signal(SIGILL, old); + return 1; +} + +void rv64Detect(void) +{ + // Alloc memory to execute stuffs + void* my_block = mmap(NULL, box64_pagesize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if(my_block==(void*)-1) { + return; + } + uint32_t* block; + #define EMIT(A) *block = (A); ++block + + + // THead vendor extensions + block = (uint32_t*)my_block; + ADDI(A0, xZR, 40); + ADDI(A1, xZR, 1); + TH_ADDSL(A0, A0, A1, 1); + BR(xRA); + cpuext.xtheadba + = cpuext.xtheadbb + = cpuext.xtheadbs + = cpuext.xtheadcondmov + = cpuext.xtheadmemidx + = cpuext.xtheadmempair + = cpuext.xtheadfmemidx + = cpuext.xtheadmac + = cpuext.xtheadfmv = Check(my_block); + + // Official extensions + + if (!cpuext.xtheadba) { + // Test Zba with ADDUW + block = (uint32_t*)my_block; + ADDUW(A0, A0, A1); + ADDI(A0, xZR, 42); + BR(xRA); + cpuext.zba = Check(my_block); + // Test Zbb with ANDN + block = (uint32_t*)my_block; + ANDN(A0, A0, A1); + ADDI(A0, xZR, 42); + BR(xRA); + cpuext.zbb = Check(my_block); + // Test Zbc with CLMUL + block = (uint32_t*)my_block; + CLMUL(A0, A0, A1); + ADDI(A0, xZR, 42); + BR(xRA); + cpuext.zbc = Check(my_block); + // Test Zbs with BCLR + block = (uint32_t*)my_block; + BCLR(A0, A0, A1); + ADDI(A0, xZR, 42); + BR(xRA); + cpuext.zbs = Check(my_block); + } + + block = (uint32_t*)my_block; + CSRRS(xZR, xZR, 0xc22 /* vlenb */); + ADDI(A0, xZR, 42); + BR(xRA); + cpuext.vector = Check(my_block); + + if (cpuext.vector) { + block = (uint32_t*)my_block; + CSRRS(xZR, xZR, 0x00f /* vcsr */); // vcsr does not exists in xtheadvector + ADDI(A0, xZR, 42); + BR(xRA); + cpuext.xtheadvector = !Check(my_block); + } + + if (cpuext.vector) { + int vlenb = 0; + asm volatile("csrr %0, 0xc22" : "=r"(vlenb)); + cpuext.vlen = vlenb; + if (vlenb < 16) { + // we need vlen >= 128 + cpuext.vector = 0; + } + } + + // Finish + // Free the memory my_block + munmap(my_block, box64_pagesize); +} +#endif + +int DetectHostCpuFeatures(void) +{ +#ifdef ARM64 + unsigned long hwcap = real_getauxval(AT_HWCAP); + if(!hwcap) + hwcap = HWCAP_ASIMD; + // first, check all needed extensions, lif half, edsp and fastmult + if ((hwcap & HWCAP_ASIMD) == 0) return 0; + if(hwcap&HWCAP_CRC32) + cpuext.crc32 = 1; + if(hwcap&HWCAP_PMULL) + cpuext.pmull = 1; + if(hwcap&HWCAP_AES) + cpuext.aes = 1; + if(hwcap&HWCAP_ATOMICS) + cpuext.atomics = 1; + #ifdef HWCAP_SHA1 + if(hwcap&HWCAP_SHA1) + cpuext.sha1 = 1; + #endif + #ifdef HWCAP_SHA2 + if(hwcap&HWCAP_SHA2) + cpuext.sha2 = 1; + #endif + #ifdef HWCAP_USCAT + if(hwcap&HWCAP_USCAT) + cpuext.uscat = 1; + #endif + #ifdef HWCAP_FLAGM + if(hwcap&HWCAP_FLAGM) + cpuext.flagm = 1; + #endif + unsigned long hwcap2 = real_getauxval(AT_HWCAP2); + #ifdef HWCAP2_FLAGM2 + if(hwcap2&HWCAP2_FLAGM2) + cpuext.flagm2 = 1; + #endif + #ifdef HWCAP2_FRINT + if(hwcap2&HWCAP2_FRINT) + cpuext.frintts = 1; + #endif + #ifdef HWCAP2_AFP + if(hwcap2&HWCAP2_AFP) + cpuext.afp = 1; + #endif + #ifdef HWCAP2_RNG + if(hwcap2&HWCAP2_RNG) + cpuext.rndr = 1; + #endif +#elif defined(LA64) + char* p = getenv("BOX64_DYNAREC_LA64NOEXT"); + if(p == NULL || p[0] == '0') { + uint32_t cpucfg2 = 0, idx = 2; + asm volatile("cpucfg %0, %1" : "=r"(cpucfg2) : "r"(idx)); + if (((cpucfg2 >> 6) & 0b11) != 3) return 0; // LSX/LASX must present + + cpuext.lbt = (cpucfg2 >> 18) & 0b1; + cpuext.lam_bh = (cpucfg2 >> 27) & 0b1; + cpuext.lamcas = (cpucfg2 >> 28) & 0b1; + cpuext.scq = (cpucfg2 >> 30) & 0b1; + } +#elif defined(RV64) + // private env. variable for the developer ;) + char *p = getenv("BOX64_DYNAREC_RV64NOEXT"); + if(p == NULL || strcasecmp(p, "1")) { + rv64Detect(); + if (p) { + p = strtok(p, ","); + while (p) { + if (!strcasecmp(p, "zba")) cpuext.zba = 0; + if (!strcasecmp(p, "zbb")) cpuext.zbb = 0; + if (!strcasecmp(p, "zbc")) cpuext.zbc = 0; + if (!strcasecmp(p, "zbs")) cpuext.zbs = 0; + if (!strcasecmp(p, "vector")) { + cpuext.vector = 0; + cpuext.xtheadvector = 0; + } + if (!strcasecmp(p, "xtheadba")) cpuext.xtheadba = 0; + if (!strcasecmp(p, "xtheadbb")) cpuext.xtheadbb = 0; + if (!strcasecmp(p, "xtheadbs")) cpuext.xtheadbs = 0; + if (!strcasecmp(p, "xtheadmemidx")) cpuext.xtheadmemidx = 0; + // if (!strcasecmp(p, "xtheadfmemidx")) cpuext.xtheadfmemidx = 0; + // if (!strcasecmp(p, "xtheadmac")) cpuext.xtheadmac = 0; + // if (!strcasecmp(p, "xtheadfmv")) cpuext.xtheadfmv = 0; + if (!strcasecmp(p, "xtheadmempair")) cpuext.xtheadmempair = 0; + if (!strcasecmp(p, "xtheadcondmov")) cpuext.xtheadcondmov = 0; + p = strtok(NULL, ","); + } + } + } +#endif + return 1; +} \ No newline at end of file diff --git a/src/os/hostext_wine.c b/src/os/hostext_wine.c new file mode 100644 index 00000000..3b6d5663 --- /dev/null +++ b/src/os/hostext_wine.c @@ -0,0 +1,20 @@ +#include <winternl.h> + +#include "debug.h" +#include "wine/compiler.h" +#include "wine/debug.h" + +int DetectHostCpuFeatures(void) +{ + cpuext.asimd = 1; + if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) + cpuext.aes = cpuext.sha1 = cpuext.sha2 = cpuext.pmull = 1; + if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)) + cpuext.crc32 = 1; + if (IsProcessorFeaturePresent(PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE)) + cpuext.atomics = 1; + + // TODO + cpuext.uscat = cpuext.flagm = cpuext.flagm2 = cpuext.frintts = cpuext.afp = cpuext.rndr = 0; + return 1; +} diff --git a/src/rv64detect.c b/src/rv64detect.c deleted file mode 100644 index 3cce199e..00000000 --- a/src/rv64detect.c +++ /dev/null @@ -1,126 +0,0 @@ -#include <string.h> -#include <stdio.h> -#include <stdint.h> -#include <signal.h> -#include <sys/mman.h> -#include <setjmp.h> - -#include "debug.h" -#include "dynarec/rv64/rv64_emitter.h" - -// Detect RV64 extensions, by executing on of the opcode with a SIGILL signal handler - -static sigjmp_buf sigbuf = {0}; -typedef int (*iFiip_t)(int, int, void*); -static void detect_sigill(int sig) -{ - siglongjmp(sigbuf, 1); -} - -static int Check(void* block) -{ - static uint64_t buf[2] = {0}; - // Clear instruction cache - __clear_cache(block, block+box64_pagesize); - // Setup SIGILL signal handler - __sighandler_t old = signal(SIGILL, detect_sigill); - if(sigsetjmp(sigbuf, 1)) { - // didn't work, extension not present - signal(SIGILL, old); - return 0; - } - int result = ((iFiip_t)block)(0, 1, buf); - if (result != 42) { - // wrong result, extension not present - signal(SIGILL, old); - return 0; - } - // done... - signal(SIGILL, old); - return 1; -} - -void RV64_Detect_Function() -{ - // Alloc memory to execute stuffs - void* my_block = mmap(NULL, box64_pagesize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); - if(my_block==(void*)-1) { - return; - } - uint32_t* block; - #define EMIT(A) *block = (A); ++block - - - // THead vendor extensions - block = (uint32_t*)my_block; - ADDI(A0, xZR, 40); - ADDI(A1, xZR, 1); - TH_ADDSL(A0, A0, A1, 1); - BR(xRA); - cpuext.xtheadba - = cpuext.xtheadbb - = cpuext.xtheadbs - = cpuext.xtheadcondmov - = cpuext.xtheadmemidx - = cpuext.xtheadmempair - = cpuext.xtheadfmemidx - = cpuext.xtheadmac - = cpuext.xtheadfmv = Check(my_block); - - // Official extensions - - if (!cpuext.xtheadba) { - // Test Zba with ADDUW - block = (uint32_t*)my_block; - ADDUW(A0, A0, A1); - ADDI(A0, xZR, 42); - BR(xRA); - cpuext.zba = Check(my_block); - // Test Zbb with ANDN - block = (uint32_t*)my_block; - ANDN(A0, A0, A1); - ADDI(A0, xZR, 42); - BR(xRA); - cpuext.zbb = Check(my_block); - // Test Zbc with CLMUL - block = (uint32_t*)my_block; - CLMUL(A0, A0, A1); - ADDI(A0, xZR, 42); - BR(xRA); - cpuext.zbc = Check(my_block); - // Test Zbs with BCLR - block = (uint32_t*)my_block; - BCLR(A0, A0, A1); - ADDI(A0, xZR, 42); - BR(xRA); - cpuext.zbs = Check(my_block); - } - - block = (uint32_t*)my_block; - CSRRS(xZR, xZR, 0xc22 /* vlenb */); - ADDI(A0, xZR, 42); - BR(xRA); - cpuext.vector = Check(my_block); - - if (cpuext.vector) { - block = (uint32_t*)my_block; - CSRRS(xZR, xZR, 0x00f /* vcsr */); // vcsr does not exists in xtheadvector - ADDI(A0, xZR, 42); - BR(xRA); - cpuext.xtheadvector = !Check(my_block); - } - - if (cpuext.vector) { - int vlenb = 0; - asm volatile("csrr %0, 0xc22" : "=r"(vlenb)); - cpuext.vlen = vlenb; - if (vlenb < 16) { - // we need vlen >= 128 - cpuext.vector = 0; - } - } - - // Finish - // Free the memory my_block - munmap(my_block, box64_pagesize); -} diff --git a/wine/common/wrt.c b/wine/common/wrt.c index d9725e4b..82477c1f 100644 --- a/wine/common/wrt.c +++ b/wine/common/wrt.c @@ -234,3 +234,8 @@ void WINAPI GetSystemInfo(SYSTEM_INFO* si) fillSystemInfo(si, &basic_info, &cpu_info); } + +BOOL WINAPI IsProcessorFeaturePresent(DWORD feature) +{ + return RtlIsProcessorFeaturePresent(feature); +} diff --git a/wine/include/wine/compiler.h b/wine/include/wine/compiler.h index a38f624b..ca7aedf4 100644 --- a/wine/include/wine/compiler.h +++ b/wine/include/wine/compiler.h @@ -92,6 +92,7 @@ NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE, PVOID*, SIZE_T*, ULONG, ULONG*); NTSTATUS WINAPI NtAllocateVirtualMemory(HANDLE, PVOID*, ULONG_PTR, SIZE_T*, ULONG, ULONG); PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T); NTSTATUS WINAPI NtFreeVirtualMemory(HANDLE, PVOID*, SIZE_T*, ULONG); +BOOLEAN WINAPI RtlIsProcessorFeaturePresent(UINT feature); static inline uintptr_t calculate_fs(void) { diff --git a/wine/wow64/CMakeLists.txt b/wine/wow64/CMakeLists.txt index a8d996f9..47b28da7 100644 --- a/wine/wow64/CMakeLists.txt +++ b/wine/wow64/CMakeLists.txt @@ -87,6 +87,8 @@ set(WOW64_BOX64CPU_SRC "${BOX64_ROOT}/src/emu/x87emu_private.c" "${BOX64_ROOT}/src/os/backtrace.c" "${BOX64_ROOT}/src/os/os_wine.c" + "${BOX64_ROOT}/src/os/hostext_common.c" + "${BOX64_ROOT}/src/os/hostext_wine.c" "${BOX64_ROOT}/src/os/freq_wine.c" "${BOX64_ROOT}/src/os/symbolfuncs_wine.c" "${BOX64_ROOT}/src/os/emit_signal_wine.c" diff --git a/wine/wow64/wowbox64.c b/wine/wow64/wowbox64.c index 02b25c05..770af6bf 100644 --- a/wine/wow64/wowbox64.c +++ b/wine/wow64/wowbox64.c @@ -24,7 +24,7 @@ #include "rbtree.h" #include "wine/compiler.h" #include "wine/debug.h" -#include "core_arch.h" +#include "hostext.h" uintptr_t box64_pagesize = 4096; @@ -226,6 +226,14 @@ NTSTATUS WINAPI BTCpuProcessInit(void) LoadEnvVariables(); InitializeEnvFiles(); + if (!BOX64ENV(nobanner)) PrintBox64Version(1); + if (DetectHostCpuFeatures()) + PrintHostCpuFeatures(); + else { + printf_log(LOG_INFO, "Minimum CPU requirements not met, disabling DynaRec\n"); + SET_BOX64ENV(dynarec, 0); + } + TCHAR filename[MAX_PATH]; if (GetModuleFileNameA(NULL, filename, MAX_PATH)) { char* shortname = strrchr(filename, '\\'); @@ -235,7 +243,6 @@ NTSTATUS WINAPI BTCpuProcessInit(void) } } - if (!BOX64ENV(nobanner)) PrintBox64Version(1); PrintEnvVariables(&box64env, LOG_INFO); memset(bopcode, 0xc3, sizeof(bopcode)); |