about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2024-02-28 03:44:34 +0800
committerGitHub <noreply@github.com>2024-02-27 20:44:34 +0100
commitd658c47cd02823bee50adebf8580537031ef7026 (patch)
tree13dde73cbf719499a32c874112b4b66fae587059
parent21b06ace43adb3bc8b88eea8d0e1db79110d4e9c (diff)
downloadbox64-d658c47cd02823bee50adebf8580537031ef7026.tar.gz
box64-d658c47cd02823bee50adebf8580537031ef7026.zip
[RV64_DYNAREC] Fixed RDTSC handling (#1291)
* [LIBWRAP] Fixed a typo in the clocksource wrapping

* [RV64_DYNAREC] Added hardware timer support for RDTSC

* [INTERP] Optmize RV64 ReadTSC using rdtime

* [RV64_DYNAREC] Added 0F 01 F9 RDTSCP opcode

* Fixed typo

* Fixed another typo
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c60
-rw-r--r--src/emu/x64emu.c6
-rw-r--r--src/wrapped/wrappedlibc.c17
3 files changed, 63 insertions, 20 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index 83ee96c9..8b9eb63c 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -61,19 +61,46 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
     switch (opcode) {
 
         case 0x01:
-            INST_NAME("FAKE xgetbv");
-            nextop = F8;
-            addr = fakeed(dyn, addr, ninst, nextop);
-            SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
-            GETIP(ip);
-            STORE_XEMU_CALL(x3);
-            CALL(native_ud, -1);
-            LOAD_XEMU_CALL();
-            jump_to_epilog(dyn, 0, xRIP, ninst);
-            *need_epilog = 0;
-            *ok = 0;
-            break;
+            // TODO:, /0 is SGDT. While 0F 01 D0 is XGETBV, etc...
+            nextop = F8;
+            if(MODREG) {
+                switch(nextop) {
+                    case 0xD0:
+                        INST_NAME("FAKE xgetbv");
+                        nextop = F8;
+                        addr = fakeed(dyn, addr, ninst, nextop);
+                        SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
+                        GETIP(ip);
+                        STORE_XEMU_CALL(x3);
+                        CALL(native_ud, -1);
+                        LOAD_XEMU_CALL();
+                        jump_to_epilog(dyn, 0, xRIP, ninst);
+                        *need_epilog = 0;
+                        *ok = 0;
+                        break;
 
+                    case 0xF9:
+                        INST_NAME("RDTSCP");
+                        NOTEST(x1);
+                        if (box64_rdtsc) {
+                            CALL(ReadTSC, x3); // will return the u64 in x3
+                        } else {
+                            CSRRS(x3, xZR, 0xC01); // RDTIME
+                        }
+                        SRLI(xRDX, x3, 32);
+                        AND(xRAX, x3, xMASK); // wipe upper part
+                        MV(xRCX, xZR);    // IA32_TSC, 0 for now
+                        break;
+                    default:
+                        DEFAULT;
+                }
+            } else {
+                switch((nextop>>3)&7) {
+                    default:
+                        DEFAULT;
+                }
+            }
+            break;
         case 0x05:
             INST_NAME("SYSCALL");
             NOTEST(x1);
@@ -380,10 +407,13 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0x31:
             INST_NAME("RDTSC");
             NOTEST(x1);
-            MESSAGE(LOG_DUMP, "Need Optimization\n");
-            CALL(ReadTSC, x3); // will return the u64 in x3
+            if (box64_rdtsc) {
+                CALL(ReadTSC, x3); // will return the u64 in x3
+            } else {
+                CSRRS(x3, xZR, 0xC01); // RDTIME
+            }
             SRLI(xRDX, x3, 32);
-            AND(xRAX, x3, 32); // wipe upper part
+            AND(xRAX, x3, xMASK); // wipe upper part
             break;
         case 0x38:
             // SSE3
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index 4d8bf629..fc737242 100644
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -584,10 +584,14 @@ uint64_t ReadTSC(x64emu_t* emu)
     (void)emu;
     
     // Hardware counter, per architecture
-#ifdef ARM64
+#if defined(ARM64) || defined(RV64)
     if(!box64_rdtsc) {
         uint64_t val;
+#ifdef ARM64
         asm volatile("mrs %0, cntvct_el0" : "=r" (val));
+#else // RV64
+        asm volatile("rdtime %0" : "=r" (val));
+#endif
         return val;
     }
 #endif
diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c
index 77d9ff45..c8f23d0c 100644
--- a/src/wrapped/wrappedlibc.c
+++ b/src/wrapped/wrappedlibc.c
@@ -1626,7 +1626,7 @@ void CreateCPUPresentFile(int fd)
 void CreateClocksourceFile(int fd)
 {
     size_t dummy;
-    write(fd, "tsc", strlen("tsc"));
+    write(fd, "tsc\n", strlen("tsc\n"));
 }
 
 #ifdef ANDROID
@@ -1690,7 +1690,7 @@ EXPORT int32_t my_open(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mo
         // special case to say tsc as current clocksource
         int tmp = shm_open(TMP_CLOCKSOURCE, O_RDWR | O_CREAT, S_IRWXU);
         if(tmp<0) return open(pathname, flags, mode); // error fallback
-        shm_unlink(TMP_CPUINFO);    // remove the shm file, but it will still exist because it's currently in use
+        shm_unlink(TMP_CLOCKSOURCE);    // remove the shm file, but it will still exist because it's currently in use
         CreateClocksourceFile(tmp);
         lseek(tmp, 0, SEEK_SET);
         return tmp;
@@ -1782,6 +1782,15 @@ EXPORT int32_t my_open64(x64emu_t* emu, void* pathname, int32_t flags, uint32_t
         lseek(tmp, 0, SEEK_SET);
         return tmp;
     }
+    if(!strcmp((const char*)pathname, "/sys/bus/clocksource/devices/clocksource0/current_clocksource")) {
+        // special case to say tsc as current clocksource
+        int tmp = shm_open(TMP_CLOCKSOURCE, O_RDWR | O_CREAT, S_IRWXU);
+        if(tmp<0) return open64(pathname, flags, mode); // error fallback
+        shm_unlink(TMP_CLOCKSOURCE);    // remove the shm file, but it will still exist because it's currently in use
+        CreateClocksourceFile(tmp);
+        lseek(tmp, 0, SEEK_SET);
+        return tmp;
+    }
     #endif
     return open64(pathname, flags, mode);
 }
@@ -1817,10 +1826,10 @@ EXPORT FILE* my_fopen64(x64emu_t* emu, const char* path, const char* mode)
         return fdopen(tmp, mode);
     }
     if(strcmp(path, "/sys/bus/clocksource/devices/clocksource0/current_clocksource")==0) {
-        // special case for cpuinfo
+        // special case to say tsc as current clocksource
         int tmp = shm_open(TMP_CLOCKSOURCE, O_RDWR | O_CREAT, S_IRWXU);
         if(tmp<0) return fopen64(path, mode); // error fallback
-        shm_unlink(TMP_CPUINFO);    // remove the shm file, but it will still exist because it's currently in use
+        shm_unlink(TMP_CLOCKSOURCE);    // remove the shm file, but it will still exist because it's currently in use
         CreateClocksourceFile(tmp);
         lseek(tmp, 0, SEEK_SET);
         return fdopen(tmp, mode);