about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-06-07 20:06:02 +0200
committerptitSeb <sebastien.chev@gmail.com>2021-06-07 20:06:02 +0200
commit508545aa874ac7c8de5fb589bc03e3f45c70adb5 (patch)
tree9bde8c750dbd39210a7012d884b05ae33a213c4f /src
parent52d86177c5d7e70df4018ec8c9ef7a7da5bf030a (diff)
downloadbox64-508545aa874ac7c8de5fb589bc03e3f45c70adb5.tar.gz
box64-508545aa874ac7c8de5fb589bc03e3f45c70adb5.zip
Added suport for arch_prctl syscall, and GL segment handling ([DYNAREC] too)
Diffstat (limited to 'src')
-rwxr-xr-xsrc/dynarec/dynarec_arm64_00.c6
-rw-r--r--src/dynarec/dynarec_arm64_64.c38
-rwxr-xr-xsrc/dynarec/dynarec_arm64_helper.h2
-rwxr-xr-xsrc/emu/x64run.c11
-rw-r--r--src/emu/x64run64.c4
-rwxr-xr-xsrc/emu/x64run_private.h2
-rwxr-xr-xsrc/emu/x64syscall.c6
-rwxr-xr-xsrc/emu/x64tls.c34
-rwxr-xr-xsrc/include/box64context.h2
-rwxr-xr-xsrc/include/x64tls.h2
10 files changed, 78 insertions, 29 deletions
diff --git a/src/dynarec/dynarec_arm64_00.c b/src/dynarec/dynarec_arm64_00.c
index 72d4d32b..c8c3a10b 100755
--- a/src/dynarec/dynarec_arm64_00.c
+++ b/src/dynarec/dynarec_arm64_00.c
@@ -530,9 +530,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             }
             break;
         case 0x64:
-            addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
+            addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog);
+            break;
+        case 0x65:
+            addr = dynarec64_64(dyn, addr, ip, ninst, rex, rep, _GS, ok, need_epilog);
             break;
-
         case 0x66:
             addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
             break;
diff --git a/src/dynarec/dynarec_arm64_64.c b/src/dynarec/dynarec_arm64_64.c
index e6f52fcc..546c5ff8 100644
--- a/src/dynarec/dynarec_arm64_64.c
+++ b/src/dynarec/dynarec_arm64_64.c
@@ -24,7 +24,7 @@
 
 #define GETG        gd = ((nextop&0x38)>>3)+(rex.r<<3)
 
-uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
+uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog)
 {
     (void)ip; (void)rep; (void)need_epilog;
 
@@ -61,9 +61,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
     switch(opcode) {
 
         case 0x03:
-            INST_NAME("ADD Gd, FS:Ed");
+            INST_NAME("ADD Gd, Seg:Ed");
             SETFLAGS(X_ALL, SF_SET);
-            grab_segdata(dyn, addr, ninst, x4, _FS);
+            grab_segdata(dyn, addr, ninst, x4, seg);
             nextop = F8;
             GETGD;
             GETEDO(x4, 0);
@@ -86,7 +86,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                                 d0 = sse_get_reg(dyn, ninst, x1, ed);
                                 VMOVeD(v0, 0, d0, 0);
                             } else {
-                                grab_segdata(dyn, addr, ninst, x4, _FS);
+                                grab_segdata(dyn, addr, ninst, x4, seg);
                                 v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
                                 addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
                                 ADDx_REG(x4, x4, ed);
@@ -102,7 +102,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                                 q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
                                 VMOVeS(v0, 0, q0, 0);
                             } else {
-                                grab_segdata(dyn, addr, ninst, x4, _FS);
+                                grab_segdata(dyn, addr, ninst, x4, seg);
                                 v0 = sse_get_reg_empty(dyn, ninst, x1, gd);
                                 addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
                                 ADDx_REG(x4, x4, ed);
@@ -125,7 +125,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                                 d0 = sse_get_reg(dyn, ninst, x1, ed);
                                 VMOVeD(d0, 0, v0, 0);
                             } else {
-                                grab_segdata(dyn, addr, ninst, x4, _FS);
+                                grab_segdata(dyn, addr, ninst, x4, seg);
                                 addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0);
                                 ADDx_REG(x4, x4, ed);
                                 VSTR64_U12(v0, x4, fixedaddress);
@@ -140,7 +140,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                                 q0 = sse_get_reg(dyn, ninst, x1, (nextop&7) + (rex.b<<3));
                                 VMOVeS(q0, 0, v0, 0);
                             } else {
-                                grab_segdata(dyn, addr, ninst, x4, _FS);
+                                grab_segdata(dyn, addr, ninst, x4, seg);
                                 addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<2, 3, rex, 0, 0);
                                 ADDx_REG(x4, x4, ed);
                                 VSTR32_U12(v0, x4, fixedaddress);
@@ -157,9 +157,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             break;
 
         case 0x33:
-            INST_NAME("XOR Gd, FS:Ed");
+            INST_NAME("XOR Gd, Seg:Ed");
             SETFLAGS(X_ALL, SF_SET);
-            grab_segdata(dyn, addr, ninst, x4, _FS);
+            grab_segdata(dyn, addr, ninst, x4, seg);
             nextop = F8;
             GETGD;
             GETEDO(x4, 0);
@@ -168,7 +168,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     
         case 0x80:
             nextop = F8;
-            grab_segdata(dyn, addr, ninst, x1, _FS);
+            grab_segdata(dyn, addr, ninst, x1, seg);
             switch((nextop>>3)&7) {
                 case 0: //ADD
                     INST_NAME("ADD Eb, Ib");
@@ -247,7 +247,7 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0x81:
         case 0x83:
             nextop = F8;
-            grab_segdata(dyn, addr, ninst, x6, _FS);
+            grab_segdata(dyn, addr, ninst, x6, seg);
             switch((nextop>>3)&7) {
                 case 0: //ADD
                     if(opcode==0x81) {INST_NAME("ADD Ed, Id");} else {INST_NAME("ADD Ed, Ib");}
@@ -324,8 +324,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             break;
             
         case 0x89:
-            INST_NAME("MOV FS:Ed, Gd");
-            grab_segdata(dyn, addr, ninst, x4, _FS);
+            INST_NAME("MOV Seg:Ed, Gd");
+            grab_segdata(dyn, addr, ninst, x4, seg);
             nextop=F8;
             GETGD;
             if(MODREG) {   // reg <= reg
@@ -337,8 +337,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             break;
 
         case 0x8B:
-            INST_NAME("MOV Gd, FS:Ed");
-            grab_segdata(dyn, addr, ninst, x4, _FS);
+            INST_NAME("MOV Gd, Seg:Ed");
+            grab_segdata(dyn, addr, ninst, x4, seg);
             nextop=F8;
             GETGD;
             if(MODREG) {   // reg <= reg
@@ -350,8 +350,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             break;
 
         case 0xC6:
-            INST_NAME("MOV FS:Eb, Ib");
-            grab_segdata(dyn, addr, ninst, x4, _FS);
+            INST_NAME("MOV Seg:Eb, Ib");
+            grab_segdata(dyn, addr, ninst, x4, seg);
             nextop=F8;
             if(MODREG) {   // reg <= u8
                 u8 = F8;
@@ -373,8 +373,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             }
             break;
         case 0xC7:
-            INST_NAME("MOV FS:Ed, Id");
-            grab_segdata(dyn, addr, ninst, x4, _FS);
+            INST_NAME("MOV Seg:Ed, Id");
+            grab_segdata(dyn, addr, ninst, x4, seg);
             nextop=F8;
             if(MODREG) {   // reg <= i32
                 i64 = F32S;
diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h
index 7cbad4c3..ec9ca63c 100755
--- a/src/dynarec/dynarec_arm64_helper.h
+++ b/src/dynarec/dynarec_arm64_helper.h
@@ -871,7 +871,7 @@ void fpu_popcache(dynarec_arm_t* dyn, int ninst, int s1);
 
 uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
-uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
+uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog);
 //uintptr_t dynarec64_65(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep,int* ok, int* need_epilog);
 uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
 uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog);
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index d56b3aa2..0ef1e84e 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -241,14 +241,21 @@ x64emurun:
                     GD->sdword[0] = ED->sdword[0];  // meh?
             break;
         case 0x64:                      /* FS: prefix */
-            if(Run64(emu, rex)) {
+            if(Run64(emu, rex, _FS)) {
+                unimp = 1;
+                goto fini;
+            }
+            if(emu->quit)
+                goto fini;
+            break;
+        case 0x65:                      /* GS: prefix */
+            if(Run64(emu, rex, _GS)) {
                 unimp = 1;
                 goto fini;
             }
             if(emu->quit)
                 goto fini;
             break;
-
         case 0x66:                      /* 16bits prefix */
             if(Run66(emu, rex, rep)) {
                 unimp = 1;
diff --git a/src/emu/x64run64.c b/src/emu/x64run64.c
index 1708bb79..c7f2fbec 100644
--- a/src/emu/x64run64.c
+++ b/src/emu/x64run64.c
@@ -22,7 +22,7 @@
 

 #include "modrm.h"

 

-int Run64(x64emu_t *emu, rex_t rex)

+int Run64(x64emu_t *emu, rex_t rex, int seg)

 {

     uint8_t opcode;

     uint8_t nextop;

@@ -35,7 +35,7 @@ int Run64(x64emu_t *emu, rex_t rex)
     reg64_t *oped, *opgd;

     sse_regs_t *opex, *opgx;

     int rep;

-    uintptr_t tlsdata = GetFSBaseEmu(emu);

+    uintptr_t tlsdata = GetSegmentBaseEmu(emu, seg);

 

     opcode = F8;

     // REX prefix before the F0 are ignored

diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h
index 7f4089fc..bcaea031 100755
--- a/src/emu/x64run_private.h
+++ b/src/emu/x64run_private.h
@@ -102,7 +102,7 @@ void UpdateFlags(x64emu_t *emu);
 #define RESET_FLAGS(emu) emu->df = d_none
 
 int Run0F(x64emu_t *emu, rex_t rex);
-int Run64(x64emu_t *emu, rex_t rex);
+int Run64(x64emu_t *emu, rex_t rex, int seg);
 int Run66(x64emu_t *emu, rex_t rex, int rep);
 int Run660F(x64emu_t *emu, rex_t rex);
 int Run6664(x64emu_t *emu, rex_t rex);
diff --git a/src/emu/x64syscall.c b/src/emu/x64syscall.c
index c43e1407..126dfb82 100755
--- a/src/emu/x64syscall.c
+++ b/src/emu/x64syscall.c
@@ -116,6 +116,7 @@ scwrap_t syscallwrap[] = {
     { 127, __NR_rt_sigpending, 2},
     //{ 131, __NR_sigaltstack, 2},  // wrapped to use my_sigaltstack
     { 157, __NR_prctl, 5 },     // needs wrapping?
+    //{ 158, __NR_arch_prctl, 2},   //need wrapping
     { 186, __NR_gettid, 0 },    //0xBA
     { 200, __NR_tkill, 2 },
     #ifdef __NR_time
@@ -324,6 +325,9 @@ void EXPORT x64Syscall(x64emu_t *emu)
         case 131: // sys_sigaltstack
             R_EAX = (uint32_t)my_sigaltstack(emu, (void*)R_RDI, (void*)R_RSI);
             break;
+        case 158: // sys_arch_prctl
+            R_EAX = (uint32_t)my_arch_prctl(emu, (int)R_EDI, (void*)R_RSI);
+            break;
         #ifndef __NR_time
         case 201: // sys_time
             R_RAX = (uintptr_t)time((void*)R_RDI);
@@ -433,6 +437,8 @@ uintptr_t EXPORT my_syscall(x64emu_t *emu)
             return (uintptr_t)my_readlink(emu,(void*)R_RSI, (void*)R_RDX, (size_t)R_RCX);
         case 131: // sys_sigaltstack
             return (uint32_t)my_sigaltstack(emu, (void*)R_RSI, (void*)R_RDX);
+        case 158: // sys_arch_prctl
+            return (uint32_t)my_arch_prctl(emu, (int)R_ESI, (void*)R_RDX);
         #ifndef __NR_time
         case 201: // sys_time
             return (uintptr_t)time((void*)R_RSI);
diff --git a/src/emu/x64tls.c b/src/emu/x64tls.c
index de573a45..59af88fb 100755
--- a/src/emu/x64tls.c
+++ b/src/emu/x64tls.c
@@ -8,6 +8,7 @@
 #include "debug.h"
 #include "box64context.h"
 #include "x64emu.h"
+#include "x64emu_private.h"
 #include "x64tls.h"
 #include "elfloader.h"
 
@@ -27,6 +28,7 @@ typedef struct thread_area_s
 static pthread_once_t thread_key_once0 = PTHREAD_ONCE_INIT;
 static pthread_once_t thread_key_once1 = PTHREAD_ONCE_INIT;
 static pthread_once_t thread_key_once2 = PTHREAD_ONCE_INIT;
+static pthread_once_t thread_key_once3 = PTHREAD_ONCE_INIT;
 
 static void thread_key_alloc0() {
 	pthread_key_create(&my_context->segtls[0].key, NULL);
@@ -37,6 +39,9 @@ static void thread_key_alloc1() {
 static void thread_key_alloc2() {
 	pthread_key_create(&my_context->segtls[2].key, NULL);
 }
+static void thread_key_alloc3() {
+	pthread_key_create(&my_context->segtls[3].key, NULL);
+}
 
 uint32_t my_set_thread_area(thread_area_t* td)
 {
@@ -128,6 +133,33 @@ uint32_t my_modify_ldt(x64emu_t* emu, int op, thread_area_t* td, int size)
     return 0;
 }
 
+int my_arch_prctl(x64emu_t *emu, int code, void* addr)
+{
+    #define ARCH_SET_GS          0x1001
+    #define ARCH_GET_GS          0x1004
+    switch(code) {
+        case ARCH_GET_GS:
+            *(void**)addr = GetSegmentBase(emu->segs[_GS]);
+            return 0;
+        case ARCH_SET_GS:
+            if(emu->segs[_GS]!=(0xa<<3)) {
+                pthread_once(&thread_key_once3, thread_key_alloc3);
+                emu->segs[_GS] = 0xa<<3;
+                if(!default_gs)
+                    default_gs = 0xa<<3;
+            }
+            my_context->segtls[3].base = (uintptr_t)addr;
+            my_context->segtls[3].limit = 0;
+            my_context->segtls[3].present = 1;
+            pthread_setspecific(my_context->segtls[3].key, (void*)my_context->segtls[3].base);
+            return 0;
+    }
+    // other are unsupported
+    printf_log(LOG_INFO, "warning, call to unsupported arch_prctl(0x%x, %p)\n", code, addr);
+    return -1;
+}
+
+
 #define POS_TLS     0x200
 /*
  tls record should looks like:
@@ -222,7 +254,7 @@ void* GetSegmentBase(uint32_t desc)
     if(base==0x6)
         return GetSeg33Base();
 
-    if(base>6 && base<10 && my_context->segtls[base-7].present) {
+    if(base>6 && base<11 && my_context->segtls[base-7].present) {
         void* ptr = pthread_getspecific(my_context->segtls[base-7].key);
         return ptr;
     }
diff --git a/src/include/box64context.h b/src/include/box64context.h
index 7ff6d8c0..4a53fed8 100755
--- a/src/include/box64context.h
+++ b/src/include/box64context.h
@@ -156,7 +156,7 @@ typedef struct box64context_s {
     pthread_key_t       tlskey;     // then tls key to have actual tlsdata
     void*               tlsdata;    // the initial global tlsdata
     int64_t             tlssize;    // wanted size of tlsdata
-    base_segment_t      segtls[3];  // only handling 0/1/2 descriptors
+    base_segment_t      segtls[4];  // only handling 0/1/2 descriptors (3 is internal use)
 
     uintptr_t           *auxval_start;
 
diff --git a/src/include/x64tls.h b/src/include/x64tls.h
index 61f58887..f26827c2 100755
--- a/src/include/x64tls.h
+++ b/src/include/x64tls.h
@@ -10,4 +10,6 @@ void* fillTLSData(box64context_t *context);
 void* resizeTLSData(box64context_t *context, void* oldptr);
 void* GetSegmentBase(uint32_t desc);
 
+int my_arch_prctl(x64emu_t *emu, int code, void* addr);
+
 #endif //__X64_TLS_H__
\ No newline at end of file