about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2024-02-28 17:10:30 +0800
committerGitHub <noreply@github.com>2024-02-28 10:10:30 +0100
commit6a4a58185e3f3d62aea51211e6a3d98dafe318b2 (patch)
tree81ff10885d77863acfb55558ffbcf372e8c8fbc6 /src
parent6cffabacb38499ca1b12269f7989fe0bb78418f0 (diff)
downloadbox64-6a4a58185e3f3d62aea51211e6a3d98dafe318b2.tar.gz
box64-6a4a58185e3f3d62aea51211e6a3d98dafe318b2.zip
[RV64_INTERP] Added TSC freq support (#1293)
* [RV64_INTERP] Added TSC freq support

* Simplify
Diffstat (limited to 'src')
-rw-r--r--src/emu/x64emu.c80
-rw-r--r--src/main.c2
-rw-r--r--src/tools/rcfile.c2
3 files changed, 67 insertions, 17 deletions
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c
index fc737242..18e997b3 100644
--- a/src/emu/x64emu.c
+++ b/src/emu/x64emu.c
@@ -579,21 +579,75 @@ void EmuCall(x64emu_t* emu, uintptr_t addr)
     }
 }
 
+#if defined(RV64)
+static size_t readBinarySizeFromFile(const char* fname)
+{
+    if (access(fname, R_OK) != 0) return -1;
+    FILE* fp = fopen(fname, "r");
+    if (fp == NULL) return -1;
+
+    char b[sizeof(uint64_t)] = { 0 }, tmp;
+    ssize_t n = fread(b, 1, sizeof(b), fp);
+    if (n <= 0) return -1;
+
+    for (ssize_t i = 0; i < n / 2; i++) {
+        tmp = b[n - i - 1];
+        b[n - i - 1] = b[i];
+        b[i] = tmp;
+    }
+    return *(uint64_t*)b;
+}
+
+static inline uint64_t readCycleCounter()
+{
+    uint64_t val;
+    asm volatile("rdtime %0"
+                 : "=r"(val));
+    return val;
+}
+
+static inline uint64_t readFreq()
+{
+    static size_t val = -1;
+    if (val != -1) return val;
+
+    val = readBinarySizeFromFile("/sys/firmware/devicetree/base/cpus/timebase-frequency");
+    if (val != -1) return val;
+
+    // fallback to rdtime + sleep
+    struct timespec ts;
+    ts.tv_sec = 0;
+    ts.tv_nsec = 50000000; // 50 milliseconds
+    uint64_t cycles = readCycleCounter();
+    nanosleep(&ts, NULL);
+    // round to MHz
+    val = (size_t)round(((double)(readCycleCounter() - cycles) * 20) / 1e6) * 1e6;
+    return (uint64_t)val;
+}
+#elif defined(ARM64)
+static inline uint64_t readCycleCounter()
+{
+    uint64_t val;
+    asm volatile("mrs %0, cntvct_el0"
+                 : "=r"(val));
+    return val;
+}
+static inline uint64_t readFreq()
+{
+    uint64_t val;
+    asm volatile("mrs %0, cntfrq_el0"
+                 : "=r"(val));
+    return val;
+}
+#endif
+
 uint64_t ReadTSC(x64emu_t* emu)
 {
     (void)emu;
     
     // Hardware counter, per architecture
 #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;
-    }
+    if (!box64_rdtsc) return readCycleCounter();
 #endif
     // fall back to gettime...
 #if !defined(NOGETCLOCK)
@@ -611,12 +665,8 @@ uint64_t ReadTSCFrequency(x64emu_t* emu)
 {
     (void)emu;
     // Hardware counter, per architecture
-#ifdef ARM64
-    if(!box64_rdtsc) {
-        uint64_t val;
-        asm volatile("mrs %0, cntfrq_el0" : "=r" (val));
-        return val;
-    }
+#if defined(ARM64) || defined(RV64)
+    if (!box64_rdtsc) return readFreq();
 #endif
     // fall back to get time
 #if !defined(NOGETCLOCK)
diff --git a/src/main.c b/src/main.c
index 8cecf8ac..14d86798 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1007,7 +1007,7 @@ void LoadLogEnv()
                 box64_rdtsc = p[0]-'0';
         }
         if(box64_rdtsc==2) {
-            #if defined(ARM64)
+            #if defined(ARM64) || defined(RV64)
             box64_rdtsc = 0;    // allow hardxare counter
             uint64_t freq = ReadTSCFrequency(NULL);
             printf_log(LOG_INFO, "Hardware counter measured at %d Mhz, ", freq/1000);
diff --git a/src/tools/rcfile.c b/src/tools/rcfile.c
index 9c44336c..9980e07b 100644
--- a/src/tools/rcfile.c
+++ b/src/tools/rcfile.c
@@ -577,7 +577,7 @@ void ApplyParams(const char* name)
         printf_log(LOG_INFO, "Applying %s=%s\n", "BOX64_BASH", param->bash);
     }
     if(param->is_box64_rdtsc_present && (box64_rdtsc==2)) {
-        #if defined(ARM64)
+        #if defined(ARM64) || defined(RV64)
         box64_rdtsc = 0;    // allow hardxware counter
         uint64_t freq = ReadTSCFrequency(NULL);
         printf_log(LOG_INFO, "Applying RDTSC: Hardware counter measured at %d Mhz, ", freq/1000);