:: commit 397057ad7d203d4df32effeb9a7b040706bbe8a8

Mintsuki <mintsuki@protonmail.com> — 2026-02-08 18:54

parents: 2b7bc64e27

sys/cpu: Use rdtime and time_base_frequency for RISC-V performance timing

diff --git a/common/sys/cpu.h b/common/sys/cpu.h
index 8c2da436..4918d8f5 100644
--- a/common/sys/cpu.h
+++ b/common/sys/cpu.h
@@ -312,12 +312,14 @@ static inline int current_el(void) {
 
 static inline uint64_t rdtsc(void) {
     uint64_t v;
-    asm volatile ("rdcycle %0" : "=r"(v));
+    asm volatile ("rdtime %0" : "=r"(v));
     return v;
 }
 
+uint64_t riscv_time_base_frequency(void);
+
 static inline uint64_t tsc_freq_arch(void) {
-    return 0; // FIXME
+    return riscv_time_base_frequency();
 }
 
 #define csr_read(csr) ({\
diff --git a/common/sys/cpu_riscv.c b/common/sys/cpu_riscv.c
index 4bdb0541..93daf154 100644
--- a/common/sys/cpu_riscv.c
+++ b/common/sys/cpu_riscv.c
@@ -65,6 +65,12 @@ struct riscv_hart *hart_list = NULL;
 struct riscv_hart *bsp_hart;
 static const char *current_config = NULL;
 
+static uint64_t cached_time_base_freq = 0;
+
+uint64_t riscv_time_base_frequency(void) {
+    return cached_time_base_freq;
+}
+
 static struct riscv_hart *riscv_get_hart(size_t hartid) {
     for (struct riscv_hart *hart = hart_list; hart != NULL; hart = hart->next) {
         if (hart->hartid == hartid) {
@@ -99,6 +105,8 @@ static void init_riscv_acpi(void) {
         panic(false, "riscv: requires `APIC` and `RHCT` ACPI tables");
     }
 
+    cached_time_base_freq = rhct->time_base_frequency;
+
     for (uint8_t *madt_ptr = (uint8_t *)madt->madt_entries_begin;
          (uintptr_t)madt_ptr + 1 < (uintptr_t)madt + madt->header.length; madt_ptr += *(madt_ptr + 1)) {
         if (*(madt_ptr + 1) == 0) {
@@ -201,6 +209,16 @@ static void init_riscv_fdt(const void *fdt) {
         panic(false, "riscv: missing `/cpus` node");
     }
 
+    int len;
+    const void *tbf = fdt_getprop(fdt, cpus, "timebase-frequency", &len);
+    if (tbf != NULL) {
+        if (len == 8) {
+            cached_time_base_freq = fdt64_ld(tbf);
+        } else if (len == 4) {
+            cached_time_base_freq = fdt32_ld(tbf);
+        }
+    }
+
     int node;
     fdt_for_each_subnode(node, fdt, cpus) {
         const void *prop;
tab: 248 wrap: offon