diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2025-04-14 19:34:43 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-04-14 13:34:43 +0200 |
| commit | 6b2373af93e033019dd1ddd5683f2d866e253d8c (patch) | |
| tree | d8716018ee1c02a8b4e09e88456d1e2c425d3e40 /src/os | |
| parent | cf32412f986a5a9c281dda5dc24bf22641a305ed (diff) | |
| download | box64-6b2373af93e033019dd1ddd5683f2d866e253d8c.tar.gz box64-6b2373af93e033019dd1ddd5683f2d866e253d8c.zip | |
[WOW64] Added non-functional PE build (#2532)
Diffstat (limited to 'src/os')
| -rw-r--r-- | src/os/emit_signal_wine.c | 22 | ||||
| -rw-r--r-- | src/os/freq_wine.c | 2 | ||||
| -rw-r--r-- | src/os/my_cpuid_linux.c | 757 | ||||
| -rw-r--r-- | src/os/my_cpuid_wine.c | 29 | ||||
| -rw-r--r-- | src/os/os_linux.c | 70 | ||||
| -rw-r--r-- | src/os/os_wine.c | 42 | ||||
| -rw-r--r-- | src/os/perfmap.c | 27 |
7 files changed, 947 insertions, 2 deletions
diff --git a/src/os/emit_signal_wine.c b/src/os/emit_signal_wine.c new file mode 100644 index 00000000..0539a818 --- /dev/null +++ b/src/os/emit_signal_wine.c @@ -0,0 +1,22 @@ +#include "x64emu.h" +#include "custommem.h" + +void EmitSignal(x64emu_t* emu, int sig, void* addr, int code) +{ + // FIXME +} + +void CheckExec(x64emu_t* emu, uintptr_t addr) +{ + // FIXME +} + +void EmitInterruption(x64emu_t* emu, int num, void* addr) +{ + // FIXME +} + +void EmitDiv0(x64emu_t* emu, void* addr, int code) +{ + // FIXME +} diff --git a/src/os/freq_wine.c b/src/os/freq_wine.c index 6b2a9dc4..9879b609 100644 --- a/src/os/freq_wine.c +++ b/src/os/freq_wine.c @@ -1,4 +1,4 @@ -#incldue "freq.h" +#include "freq.h" // TODO: box64_rdtsc? diff --git a/src/os/my_cpuid_linux.c b/src/os/my_cpuid_linux.c new file mode 100644 index 00000000..df505ac0 --- /dev/null +++ b/src/os/my_cpuid_linux.c @@ -0,0 +1,757 @@ +#define _GNU_SOURCE +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sched.h> + +#include "my_cpuid.h" +#include "../emu/x64emu_private.h" +#include "debug.h" +#include "x64emu.h" +#include "freq.h" + +int get_cpuMhz() +{ + int MHz = 0; + char *p = NULL; + if((p=getenv("BOX64_CPUMHZ"))) { + MHz = atoi(p); + return MHz; + } + char cpumhz[200]; + sprintf(cpumhz, "%d", MHz?:1000); + setenv("BOX64_CPUMHZ", cpumhz, 1); // set temp value incase box64 gets recursively called + + int cpucore = 0; + while(cpucore!=-1) { + char cpufreq[4096]; + sprintf(cpufreq, "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpucore); + FILE *f = fopen(cpufreq, "r"); + if(f) { + int r; + if(1==fscanf(f, "%d", &r)) { + r /= 1000; + if(MHz<r) + MHz = r; + } + fclose(f); + ++cpucore; + } + else + cpucore = -1; + } + #ifndef STATICBUILD + if(!MHz) { + // try with lscpu, grabbing the max frequency + FILE* f = popen("lscpu | grep \"CPU max MHz:\" | sed -r 's/CPU max MHz:\\s{1,}//g'", "r"); + if(f) { + char tmp[200] = ""; + ssize_t s = fread(tmp, 1, 200, f); + pclose(f); + if(s>0) { + // worked! (unless it's saying "lscpu: command not found" or something like that) + if(!strstr(tmp, "lscpu")) { + // trim ending + while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n') + tmp[strlen(tmp)-1] = 0; + // incase multiple cpu type are present, there will be multiple lines + while(strchr(tmp, '\n')) + *strchr(tmp,'\n') = ' '; + // cut the float part (so '.' or ','), it's not needed + if(strchr(tmp, '.')) + *strchr(tmp, '.')= '\0'; + if(strchr(tmp, ',')) + *strchr(tmp, ',')= '\0'; + int mhz; + if(sscanf(tmp, "%d", &mhz)==1) + MHz = mhz; + } + } + } + } + #endif + if(!MHz) + MHz = 1000; // default to 1Ghz... + sprintf(cpumhz, "%d", MHz); + setenv("BOX64_CPUMHZ", cpumhz, 1); // set actual value + return MHz; +} +static int nCPU = 0; +static double bogoMips = 100.; + +void grabNCpu() { + nCPU = 1; // default number of CPU to 1 + FILE *f = fopen("/proc/cpuinfo", "r"); + ssize_t dummy; + if(f) { + nCPU = 0; + int bogo = 0; + size_t len = 500; + char* line = malloc(len); + while ((dummy = getline(&line, &len, f)) != (ssize_t)-1) { + if(!strncmp(line, "processor\t", strlen("processor\t"))) + ++nCPU; + if(!bogo && !strncmp(line, "BogoMIPS\t", strlen("BogoMIPS\t"))) { + // grab 1st BogoMIPS + float tmp; + if(sscanf(line, "BogoMIPS\t: %g", &tmp)==1) { + bogoMips = tmp; + bogo = 1; + } + } + } + free(line); + fclose(f); + if(!nCPU) nCPU=1; + } +} +int getNCpu() +{ + if(!nCPU) + grabNCpu(); + if(BOX64ENV(maxcpu) && nCPU>BOX64ENV(maxcpu)) + return BOX64ENV(maxcpu); + return nCPU; +} + +double getBogoMips() +{ + if(!nCPU) + grabNCpu(); + return bogoMips; +} + +const char* getCpuName() +{ + static char name[200] = "Unknown CPU"; + static int done = 0; + if(done) + return name; + done = 1; + char *p = NULL; + if((p=getenv("BOX64_CPUNAME"))) { + strcpy(name, p); + return name; + } + setenv("BOX64_CPUNAME", name, 1); // temporary set + #ifndef STATICBUILD + FILE* f = popen("LC_ALL=C lscpu | grep -i \"model name:\" | head -n 1 | sed -r 's/(model name:)\\s{1,}//gi'", "r"); + if(f) { + char tmp[200] = ""; + ssize_t s = fread(tmp, 1, 200, f); + pclose(f); + if(s>0) { + // worked! (unless it's saying "lscpu: command not found" or something like that) + if(!strstr(tmp, "lscpu")) { + // trim ending + while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n') + tmp[strlen(tmp)-1] = 0; + strncpy(name, tmp, 199); + } + setenv("BOX64_CPUNAME", name, 1); + return name; + } + } + // failled, try to get architecture at least + f = popen("uname -m", "r"); + if(f) { + char tmp[200] = ""; + ssize_t s = fread(tmp, 1, 200, f); + pclose(f); + if(s>0) { + // worked! + // trim ending + while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n') + tmp[strlen(tmp)-1] = 0; + snprintf(name, 199, "unknown %s cpu", tmp); + setenv("BOX64_CPUNAME", name, 1); + return name; + } + } + #endif + // Nope, bye + return name; +} + +const char* getBoxCpuName() +{ + static char branding[3*4*4+1] = ""; + static int done = 0; + if(!done) { + done = 1; + const char* name = getCpuName(); + if(strstr(name, "MHz") || strstr(name, "GHz")) { + // name already have the speed in it + snprintf(branding, sizeof(branding), "Box64 on %.*s", 39, name); + } else { + unsigned int MHz = get_cpuMhz(); + if(MHz>1500) { // swiches to GHz display... + snprintf(branding, sizeof(branding), "Box64 on %.*s @%1.2f GHz", 28, name, MHz/1000.); + } else { + snprintf(branding, sizeof(branding), "Box64 on %.*s @%04d MHz", 28, name, MHz); + } + } + } + return branding; +} + +void my_cpuid(x64emu_t* emu, uint32_t tmp32u) +{ + emu->regs[_AX].dword[1] = emu->regs[_DX].dword[1] = emu->regs[_CX].dword[1] = emu->regs[_BX].dword[1] = 0; + int ncpu = getNCpu(); + if(!ncpu) ncpu = 1; + int ncluster = 1; + static int warned = 10; + if(BOX64ENV(cputype)) { + while(ncpu>256) { + ncluster++; // do cluster of 256 cpus... + if(ncpu>=256) + ncpu-=256; + else + ncpu=256; + } + } else { + while(ncpu>64) { + ncluster++; // do cluster of 64 cpus... + if(ncpu>=128) + ncpu-=64; + else + ncpu=64; + } + } + static char branding[3*4*4+1] = ""; + if(!branding[0]) { + strcpy(branding, getBoxCpuName()); + while(strlen(branding)<3*4*4) { + memmove(branding+1, branding, strlen(branding)+1); + branding[0] = ' '; + } + } + switch(tmp32u) { + case 0x0: + // emulate a P4. TODO: Emulate a Core2? + R_EAX = BOX64ENV(cputype)?0x0000000f:0x0000000f;//was 0x15 before, but something seems wrong for leaf 0x15, and cpu-z take that as pure cpu speed... + if(BOX64ENV(cputype)) { + // return AuthenticAMD + R_EBX = 0x68747541; + R_ECX = 0x444d4163; + R_EDX = 0x69746E65; + } else { + // return GenuineIntel + R_EBX = 0x756E6547; + R_ECX = 0x6C65746E; + R_EDX = 0x49656E69; + } + break; + case 0x1: + if(BOX64ENV(cputype)) { + R_EAX = (0xc<<0) | // stepping 0-3 + (0x1<<4) | // base model 4-7 + (0xf<<8) | // base familly 8-11 + (0x0<<12)| // reserved 12-15 + (0x7<<16)| // Extented model 16-19 + (0x8<<20)| // extended familly 20-27 + (0x0<<28)| // reserved 28-31 + 0 ; // family and all, simulating a Ryzen 5 type of cpu + } else { + R_EAX = (0x1<<0) | // stepping + (0x6<<4) | // model + (0x6<<8) | // familly + (0x0<<12)| // Processor type + (0x0<<14)| // reserved + (0x4<<16)| // extended model + (0x0<<20)| // extended familly + 0 ; // family and all, simulating Haswell type of cpu + } + R_EBX = 0 | (8<<0x8) | ((BOX64ENV(cputype)?0:ncluster)<<16); // Brand index, CLFlush (8), Max APIC ID (16-23), Local APIC ID (24-31) + /*{ + int cpu = sched_getcpu(); + if(cpu<0) cpu=0; + R_EAX |= cpu<<24; + }*/ + R_EDX = 1 // fpu + | 1<<1 // vme + | 1<<2 // debugging extension + | 1<<3 // pse + | 1<<4 // rdtsc + | 1<<5 // msr + | 1<<6 // pae + | 1<<7 // mcheck extension + | 1<<8 // cmpxchg8 + | 1<<11 // sep (sysenter & sysexit) + | 1<<12 // mtrr + | 1<<13 // pgb + | 1<<14 // mcheck arch + | 1<<15 // cmov + | 1<<16 // pat + | 1<<17 // pse36 + | 1<<19 // clflush (seems to be with SSE2) + | 1<<21 // DS, used with VMX, is that usefull? + | 1<<23 // mmx + | 1<<24 // fxsr (fxsave, fxrestore) + | 1<<25 // SSE + | 1<<26 // SSE2 + | (BOX64ENV(cputype)?0:1)<<28 // HT / Multi-core + ; + R_ECX = 1<<0 // SSE3 + | 1<<1 // PCLMULQDQ + | (BOX64ENV(cputype)?0:1)<<2 // DS 64bits + | 1<<3 // Monitor/MWait (priviledge instructions) + | (BOX64ENV(cputype)?0:1)<<5 // VMX //is that usefull + | 1<<9 // SSSE3 + | BOX64ENV(avx2)<<12 // fma + | 1<<13 // cx16 (cmpxchg16) + | 1<<19 // SSE4_1 + | BOX64ENV(sse42)<<20 // SSE4_2 can be hiden + | 1<<22 // MOVBE + | 1<<23 // POPCOUNT + | 1<<25 // aesni + | BOX64ENV(avx)<<26 // xsave + | BOX64ENV(avx)<<27 // osxsave + | BOX64ENV(avx)<<28 // AVX + | BOX64ENV(avx)<<29 // F16C + | BOX64ENV(avx2)<<30 // RDRAND + | 0<<31 // Hypervisor guest running + ; + break; + case 0x2: + if(BOX64ENV(cputype)) { + // reserved + R_EAX = R_EBX = R_ECX = R_EDX = 0 ; + } else { + // TLB and Cache info. Sending 1st gen P4 info... + R_EAX = 0x665B5001; + R_EBX = 0x00000000; + R_ECX = 0x00000000; + R_EDX = 0x007A7000; + } + break; + + case 0x4: + if(BOX64ENV(cputype)) { + // reserved + R_EAX = R_EBX = R_ECX = R_EDX = 0 ; + } else { + // Cache info + switch (R_ECX) { + case 0: // L1 data cache + R_EAX = (1 | (1<<5) | (1<<8) | ((ncpu-1)<<26)); //type + (26-31):max cores per packages-1 + R_EBX = (63 | (7<<22)); // size + R_ECX = 63; + R_EDX = 1; + break; + case 1: // L1 inst cache + R_EAX = (2 | (1<<5) | (1<<8)); //type + R_EBX = (63 | (7<<22)); // size + R_ECX = 63; + R_EDX = 1; + break; + case 2: // L2 cache + R_EAX = (3 | (2<<5) | (1<<8)); //type + R_EBX = (63 | (15<<22)); // size + R_ECX = 4095; + R_EDX = 1; + break; + + default: + R_EAX = 0x00000000; + R_EBX = 0x00000000; + R_ECX = 0x00000000; + R_EDX = 0x00000000; + break; + } + } + break; + case 0x5: //mwait info + R_EAX = 0; + R_EBX = 0; + R_ECX = 1 | 2; + R_EDX = 0; + break; + case 0x3: // PSN + case 0x6: // thermal + case 0x8: // more extended capabilities + case 0x9: // direct cache access + case 0xA: // Architecture performance monitor + R_EAX = 0; + R_EBX = 0; + R_ECX = 0; + R_EDX = 0; + break; + case 0x7: + // extended bits... + if(R_ECX==0) { + R_EAX = 0; + R_EBX = + BOX64ENV(avx)<<3 | // BMI1 + BOX64ENV(avx2)<<5 | //AVX2 + (BOX64ENV(cputype)?0:1)<<6 | // FDP_EXCPTN_ONLY + 1<<7 | // SMEP + BOX64ENV(avx2)<<8 | //BMI2 + (BOX64ENV(cputype)?0:1)<<9 | // Enhanced REP MOVSB // is it a good idea? + 1<<10 | //INVPCID (priviledge instruction + (BOX64ENV(cputype)?0:1)<<13 | // Deprecates FPU CS and FPU DS + 0<<18 | // RDSEED + BOX64ENV(avx2)<<19 | //ADX + 1<<23 | // CLFLUSHOPT + 1<<24 | // CLWB + BOX64ENV(shaext)<<29| // SHA extension + 0; + R_RCX = + BOX64ENV(avx)<<9 | //VAES + BOX64ENV(avx2)<<10 | //VPCLMULQDQ. + 1<<22 | // RDPID + 0; + R_RDX = 0; + + } else {R_EAX = R_ECX = R_EBX = R_EDX = 0;} + break; + case 0xB: + if(BOX64ENV(cputype)) { + // reserved + R_EAX = R_EBX = R_ECX = R_EDX = 0 ; + } else { + // Extended Topology Enumeration Leaf + //TODO! + R_EAX = 0; + R_EBX = 0; + } + break; + case 0xC: + if(BOX64ENV(cputype)) { + // reserved + R_EAX = R_EBX = R_ECX = R_EDX = 0 ; + } else { + //? + R_EAX = 0; + } + break; + case 0xD: + // Processor Extended State Enumeration Main Leaf / Sub Leaf + switch(R_CX) { + case 0: + R_EAX = 0b111; // x87 SSE AVX saved + R_EBX = 512+64+16*16; // size of xsave/xrstor + R_ECX = 512+64+16*16; // maximum size of xsave area + R_EDX = 0; // more bits + break; + case 1: + R_EAX = 0; // XSAVEOPT (0) and XSAVEC (1), XGETBV with ECX=1 (2) XSAVES (3) and XFD (4) not supported yet + R_ECX = R_EBX = R_EDX = 0; + break; + case 2: + // componant 2: avx + R_EAX = 16*16; // size of the avx block + R_EBX = 512+64; // offset + R_ECX = 0; + R_EDX = 0; + break; + default: + R_EAX = R_ECX = R_EBX = R_EDX = 0; + break; + } + break; + case 0xE: //? + R_EAX = 0; + break; + case 0xF: + if(BOX64ENV(cputype)) { + // reserved + R_EAX = R_EBX = R_ECX = R_EDX = 0 ; + } else { + //L3 Cache + switch(R_ECX) { + case 0: + R_EAX = 0; + R_EBX = 0; // maximum range of RMID of physical processor + R_ECX = 0; + R_EDX = 0; // bit 1 support L3 RDT Cache monitoring + break; + case 1: + R_EAX = 0; + R_EBX = 0; // Conversion factor + R_EDX = 0; // bit 0 = occupency monitoring + break; + default: R_EAX = 0; + } + } + break; + case 0x14: + if(BOX64ENV(cputype)) { + // reserved + R_EAX = R_EBX = R_ECX = R_EDX = 0 ; + } else { + // Processor Trace Enumeration Main Leaf + switch(R_ECX) { + case 0: // main leaf + R_EAX = 0; // max sub-leaf + R_EBX = 0; + R_ECX = 0; + R_EDX = 0; + break; + default: R_EAX = 0; + } + } + break; + case 0x15: + if(BOX64ENV(cputype)) { + // reserved + R_EAX = R_EBX = R_ECX = R_EDX = 0 ; + } else { + // TSC core frenquency + R_EAX = 1; // denominator + R_EBX = 1; // numerator + { + uint64_t freq = ReadTSCFrequency(emu); + while(freq>100000000) { + freq/=10; + R_EAX *= 10; + } + R_ECX = freq; // nominal frequency in Hz + } + R_EDX = 0; + } + break; + + case 0x80000000: // max extended + if(BOX64ENV(cputype)) { + R_EAX = 0x8000001a; + R_EBX = 0x68747541; + R_ECX = 0x444d4163; + R_EDX = 0x69746E65; + } else { + R_EAX = 0x80000005; // was 0x80000007 before, but L2 cache description 0x80000006 is not correct and make some AC games to assert about l2 cache value coherency... + } + break; + case 0x80000001: //Extended Processor Signature and Feature Bits + if(BOX64ENV(cputype)) { + R_EAX = (0xc<<0) | // stepping 0-3 + (0x1<<4) | // base model 4-7 + (0xf<<8) | // base familly 8-11 + (0x0<<12)| // reserved 12-15 + (0x7<<16)| // Extented model 16-19 + (0x8<<20)| // extended familly 20-27 + (0x0<<28)| // reserved 28-31 + 0 ; // family and all, simulating a Ryzen 5 type of cpu + R_EBX = 0; //0-15 brandID, 16-27 reserved, 28-31 PkgType + R_ECX = 1<<0 // LAHF/SAHF + | 1<<1 // cmplegacy? + | 1<<2 // securevm + | 1<<5 // ABM (LZCNT) + | 1<<6 // SSE4a (extrq, instrq, movntss, movntsd) + //| 1<<7 // misaligned SSE + | 1<<8 // 3DNowPrefetch + //| 1<<10 // IBS + //| 1<<11 // XOP + //| 1<<16 // FMA4 + ; + R_EDX = 1 // fpu + | 1<<2 // debugging extension + | 1<<3 // pse + | 1<<4 // rdtsc + | 1<<5 // msr + | 1<<6 // pae + | 1<<8 // cmpxchg8 + | 1<<11 // sep (sysenter & sysexit) + | 1<<12 // mtrr + | 1<<13 // pge + | 1<<15 // cmov + | 1<<16 // pat + | 1<<17 // pse36 + | 1<<19 // clflush (seems to be with SSE2) + | 1<<20 // NX + | 1<<21 // DS, used with VMX, is that usefull? + | 1<<22 // MMXext + | 1<<23 // mmx + | 1<<24 // fxsr (fxsave, fxrestore) + //| 1<<25 // FFXSR + //| 1<<26 // Page1GB + | 1<<27 // RDTSCP + | 1<<29 //LM + //| 1<<30 //3DNowExt + //| 1<<31 //3DNow! + ; + } else { + R_EAX = 0; // reserved + R_EBX = 0; // reserved + R_ECX = (1<<0) // LAHF_LM + | (1<<5) // LZCNT + | (1<<8) // PREFETCHW + ; + R_EDX = 1 // x87 FPU + | (1<<8) // cx8: cmpxchg8b opcode + | (1<<11) // syscall + | (1<<15) // cmov: FCMOV opcodes + | (1<<20) // NX + | (1<<23) // mmx: MMX available + | (1<<24) // fxsave + | (1<<27) // rdtscp + | (1<<29); // long mode 64bits available + } + break; + case 0x80000002: // Brand part 1 (branding signature) + R_EAX = ((uint32_t*)branding)[0]; + R_EBX = ((uint32_t*)branding)[1]; + R_ECX = ((uint32_t*)branding)[2]; + R_EDX = ((uint32_t*)branding)[3]; + break; + case 0x80000003: // Brand part 2 + R_EAX = ((uint32_t*)branding)[4]; + R_EBX = ((uint32_t*)branding)[5]; + R_ECX = ((uint32_t*)branding)[6]; + R_EDX = ((uint32_t*)branding)[7]; + break; + case 0x80000004: // Brand part 3, with frequency + R_EAX = ((uint32_t*)branding)[8]; + R_EBX = ((uint32_t*)branding)[9]; + R_ECX = ((uint32_t*)branding)[10]; + R_EDX = ((uint32_t*)branding)[11]; + break; + case 0x80000005: + if(BOX64ENV(cputype)) { + //L1 cache and TLB + R_EAX = 0; + R_EBX = 0; + R_ECX = 0; + R_EDX = 0; + } else { + R_EAX = 0; + R_EBX = 0; + R_ECX = 0; + R_EDX = 0; + } + break; + case 0x80000006: // L2 cache line size and associativity + if(BOX64ENV(cputype)) { + R_EAX = 0; + R_EBX = 0; + R_ECX = 64 | (0x6<<12) | (256<<16); // bits: 0-7 line size, 15-12: assoc (using special encoding), 31-16: size in K //TODO: read info from /sys/devices/system/cpu/cpuX/cache/index2 + R_EDX = 0; + } else { + R_EAX = 0; + R_EBX = 0; + R_ECX = 64 | (0x6<<12) | (256<<16); // bits: 0-7 line size, 15-12: assoc (using special encoding), 31-16: size in K //TODO: read info from /sys/devices/system/cpu/cpuX/cache/index2 + R_EDX = 0; + } + break; + case 0x80000007: + if(BOX64ENV(cputype)) { + // Advanced Power Management Information + R_EAX = 0; + R_EBX = 0; + R_ECX = 0; + R_EDX = 0 | (1<<8); // Invariant TSC + } else { + // Invariant TSC + R_EAX = 0; + R_EBX = 0; + R_ECX = 0; + R_EDX = 0 | (1<<8); // Invariant TSC + } + break; + case 0x80000008: + if(BOX64ENV(cputype)) { + // Address Size And Physical Core Count Information + R_EAX = 0; // 23-16 guest / 15-8 linear / 7-0 phys + R_EBX = 0; // reserved + R_ECX = ncpu-1; + R_EDX = 0; + } else { + // ? + R_EAX = 0; + R_EBX = 0; + R_ECX = 0; + R_EDX = 0; + } + break; + case 0x8000000a: + if(BOX64ENV(cputype)) { + // SVM Revision and Feature Identification + R_EAX = 0; + R_EBX = 0; + R_ECX = 0; + R_EDX = 0; + } else { + // ? + R_EAX = 0; + R_EBX = 0; + R_ECX = 0; + R_EDX = 0; + } + break; + case 0x8000001a: + if(BOX64ENV(cputype)) { + // Performance Optimization Identifiers + R_EAX = 1<<0 // FP128 + | 1<<1 // MOVU + | 0; + R_EBX = 0; + R_ECX = 0; + R_EDX = 0; + } else { + // ? + R_EAX = 0; + R_EBX = 0; + R_ECX = 0; + R_EDX = 0; + } + break; + default: + if(warned) { + printf_log(LOG_INFO, "Warning, CPUID command %X unsupported (ECX=%08x)\n", tmp32u, R_ECX); + --warned; + if(!warned) + printf_log(LOG_INFO, "Stopped logging CPUID issues\n"); + } + R_EAX = 0; + R_EBX = 0; + R_ECX = 0; + R_EDX = 0; + } +} + +uint32_t helper_getcpu(x64emu_t* emu) { + #if defined(__GLIBC__) && defined(__GLIBC_MINOR__) && !defined(ANDROID) + #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 28) + uint32_t cpu, node; + if(!getcpu(&cpu, &node)) + return (node&0xff)<<12 | (cpu&0xff); + #endif + #endif + return 0; +} + +uint32_t fallback_random32() +{ + return random() ^ (random()<<1); +} + +uint32_t get_random32() +{ + uint32_t ret; + FILE* f = fopen("/dev/urandom", "rb"); + if(f) { + if(fread(&ret, sizeof(ret), 1, f)!=1) + ret = fallback_random32(); + fclose(f); + } else + ret = fallback_random32(); + return ret; +} +uint64_t fallback_random64() +{ + return random() ^ (((uint64_t)random())<<18) ^ (((uint64_t)random())<<41); +} + +uint64_t get_random64() +{ + uint64_t ret; + FILE* f = fopen("/dev/urandom", "rb"); + if(f) { + if(fread(&ret, sizeof(ret), 1, f)!=1) + ret = fallback_random64(); + fclose(f); + } else + ret = fallback_random64(); + return ret; +} diff --git a/src/os/my_cpuid_wine.c b/src/os/my_cpuid_wine.c new file mode 100644 index 00000000..c2d24b1c --- /dev/null +++ b/src/os/my_cpuid_wine.c @@ -0,0 +1,29 @@ +#include <windows.h> + +#include "my_cpuid.h" + +const char* getBoxCpuName() +{ + return NULL; +} + +void my_cpuid(x64emu_t* emu, uint32_t tmp32u) +{ + // FIXME +} + +uint32_t helper_getcpu(x64emu_t* emu) { + return 0; +} + +uint32_t get_random32(void) +{ + // FIXME + return 0; +} + +uint64_t get_random64(void) +{ + // FIXME + return 0; +} \ No newline at end of file diff --git a/src/os/os_linux.c b/src/os/os_linux.c index 6d9db214..556d4d9b 100644 --- a/src/os/os_linux.c +++ b/src/os/os_linux.c @@ -1,8 +1,11 @@ +#define _GNU_SOURCE #include <sys/syscall.h> #include <sched.h> #include <unistd.h> #include <stdint.h> #include <sys/personality.h> +#include <dlfcn.h> +#include <string.h> #include "os.h" #include "signals.h" @@ -10,6 +13,9 @@ #include "bridge.h" #include "elfloader.h" #include "env.h" +#include "debug.h" +#include "x64tls.h" +#include "librarian.h" int GetTID(void) { @@ -51,6 +57,70 @@ void EmuX86Syscall(void* emu) x86Syscall((x64emu_t*)emu); } +extern int box64_is32bits; + +void* GetSeg43Base() +{ + tlsdatasize_t* ptr = getTLSData(my_context); + return ptr->data; +} + +void* GetSegmentBase(uint32_t desc) +{ + if (!desc) { + printf_log(LOG_NONE, "Warning, accessing segment NULL\n"); + return NULL; + } + int base = desc >> 3; + if (!box64_is32bits && base == 0x8 && !my_context->segtls[base].key_init) + return GetSeg43Base(); + if (box64_is32bits && (base == 0x6)) + return GetSeg43Base(); + if (base > 15) { + printf_log(LOG_NONE, "Warning, accessing segment unknown 0x%x or unset\n", desc); + return NULL; + } + if (my_context->segtls[base].key_init) { + void* ptr = pthread_getspecific(my_context->segtls[base].key); + return ptr; + } + + void* ptr = (void*)my_context->segtls[base].base; + return ptr; +} + +const char* GetNativeName(void* p) +{ + static char buff[500] = { 0 }; + { + const char* n = getBridgeName(p); + if (n) + return n; + } + Dl_info info; + if (dladdr(p, &info) == 0) { + const char* ret = GetNameOffset(my_context->maplib, p); + if (ret) + return ret; + sprintf(buff, "%s(%p)", "???", p); + return buff; + } else { + if (info.dli_sname) { + strcpy(buff, info.dli_sname); + if (info.dli_fname) { + strcat(buff, "("); + strcat(buff, info.dli_fname); + strcat(buff, ")"); + } + } else { + sprintf(buff, "%s(%s+%p)", "???", info.dli_fname, (void*)(p - info.dli_fbase)); + return buff; + } + } + return buff; +} + + void PersonalityAddrLimit32Bit(void) { personality(ADDR_LIMIT_32BIT); diff --git a/src/os/os_wine.c b/src/os/os_wine.c index 7e3c58fb..06a8317b 100644 --- a/src/os/os_wine.c +++ b/src/os/os_wine.c @@ -17,13 +17,53 @@ int IsBridgeSignature(char s, char c) return FALSE; } -void PersonalityAddrLimit32Bit(void) { } +void* GetSeg43Base() +{ + return NULL; +} + +void* GetSegmentBase(uint32_t desc) +{ + // FIXME + return NULL; +} + +void EmuInt3(void* emu, void* addr) { } +void* EmuFork(void* emu, int forktype) { return NULL; } + + +void EmuX64Syscall(void* emu) +{ + // FIXME +} + +void EmuX86Syscall(void* emu) +{ + // FIXME +} + +const char* GetNativeName(void* p) +{ + return NULL; +} + + +void PersonalityAddrLimit32Bit(void) +{ +} int IsAddrElfOrFileMapped(uintptr_t addr) { return 0; } + +int IsNativeCall(uintptr_t addr, int is32bits, uintptr_t* calladdress, uint16_t* retn) +{ + return 0; +} + + ULONG_PTR default_zero_bits32 = 0x7fffffff; static uint32_t prot_unix_to_win32(uint32_t unx) diff --git a/src/os/perfmap.c b/src/os/perfmap.c new file mode 100644 index 00000000..700863cf --- /dev/null +++ b/src/os/perfmap.c @@ -0,0 +1,27 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <assert.h> +#include <unistd.h> + +#include "debug.h" +#include "box64context.h" +#include "perfmap.h" + +#ifndef _WIN32 +#include "elfloader.h" + +void writePerfMap(uintptr_t func_addr, uintptr_t code_addr, size_t code_size, const char* inst_name) +{ + char pbuf[128]; + uint64_t sz = 0; + uintptr_t start = 0; + const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, func_addr), (void*)func_addr, &start, &sz); + snprintf(pbuf, sizeof(pbuf), "0x%lx %ld %s:%s\n", code_addr, code_size, symbname, inst_name); + write(BOX64ENV(dynarec_perf_map_fd), pbuf, strlen(pbuf)); +} +#else +void writePerfMap(uintptr_t func_addr, uintptr_t code_addr, size_t code_size, const char* inst_name) { } +#endif \ No newline at end of file |