about summary refs log tree commit diff stats
path: root/src/os
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-04-11 18:26:51 +0800
committerGitHub <noreply@github.com>2025-04-11 12:26:51 +0200
commit6c46e3d9b15be3e5c6227bb97fd542a4100ec4d2 (patch)
treebf7552c358c240e44e53c176db44bad11a415de3 /src/os
parentfa85d4d900c3e03b69bdea65204b51151fc62114 (diff)
downloadbox64-6c46e3d9b15be3e5c6227bb97fd542a4100ec4d2.tar.gz
box64-6c46e3d9b15be3e5c6227bb97fd542a4100ec4d2.zip
[WOW64] Splitted freq and cleanup functions from x64emu (#2521)
Diffstat (limited to 'src/os')
-rw-r--r--src/os/freq_linux.c137
-rw-r--r--src/os/freq_wine.c17
2 files changed, 154 insertions, 0 deletions
diff --git a/src/os/freq_linux.c b/src/os/freq_linux.c
new file mode 100644
index 00000000..6bdca050
--- /dev/null
+++ b/src/os/freq_linux.c
@@ -0,0 +1,137 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <math.h>
+
+#include "freq.h"
+#include "debug.h"
+
+#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;
+
+    val = readBinarySizeFromFile("/sys/firmware/devicetree/base/cpus/timebase-frequency");
+    if (val != (size_t)-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;
+}
+#elif defined(LA64)
+static inline uint64_t readCycleCounter()
+{
+    uint64_t val;
+    asm volatile("rdtime.d %0, %1"
+                 : "=r"(val) : "r"(0));
+    return val;
+}
+
+static inline uint64_t readFreq()
+{
+    static size_t val = -1;
+
+    FILE* f = popen("cat /proc/cpuinfo | grep -i \"CPU MHz\" | head -n 1 | sed -r 's/CPU MHz.+:\\s{1,}//g'", "r");
+    if(f) {
+        char tmp[200] = "";
+        ssize_t s = fread(tmp, 1, 200, f);
+        pclose(f);
+        if (s > 0) return (uint64_t)atof(tmp) * 1e6;
+    }
+
+    // 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;
+}
+#endif
+
+uint64_t ReadTSC(x64emu_t* emu)
+{
+    (void)emu;
+
+    // Hardware counter, per architecture
+#if defined(ARM64) || defined(RV64) || defined(LA64)
+    if (!box64_rdtsc) return readCycleCounter();
+#endif
+    // fall back to gettime...
+#if !defined(NOGETCLOCK)
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
+    return (uint64_t)(ts.tv_sec) * 1000000000LL + ts.tv_nsec;
+#else
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return (uint64_t)(tv.tv_sec) * 1000000 + tv.tv_usec;
+#endif
+}
+
+uint64_t ReadTSCFrequency(x64emu_t* emu)
+{
+    (void)emu;
+    // Hardware counter, per architecture
+#if defined(ARM64) || defined(RV64) || defined(LA64)
+    if (!box64_rdtsc) return readFreq();
+#endif
+    // fall back to get time
+#if !defined(NOGETCLOCK)
+    return 1000000000LL;
+#else
+    return 1000000;
+#endif
+}
diff --git a/src/os/freq_wine.c b/src/os/freq_wine.c
new file mode 100644
index 00000000..6b2a9dc4
--- /dev/null
+++ b/src/os/freq_wine.c
@@ -0,0 +1,17 @@
+#incldue "freq.h"
+
+// TODO: box64_rdtsc?
+
+uint64_t ReadTSC(x64emu_t* emu) {
+    uint64_t val;
+    asm volatile("mrs %0, cntvct_el0"
+                 : "=r"(val));
+    return val;
+}
+
+uint64_t ReadTSCFrequency(x64emu_t* emu) {
+    uint64_t val;
+    asm volatile("mrs %0, cntfrq_el0"
+                 : "=r"(val));
+    return val;
+}
\ No newline at end of file