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;
