Download raw body.
riscv64: explicitly enable u-mode timer access
hi,
with edk2 under linux kvm, it seems kvm sets scounteren register to 0
and edk2 doesn't enable scounteren.TM bit itself. because of that,
attempts to read time in u-mode just get a SIGILL.
since the register state is unspecified, we should explicitly enable
scounteren.TM so that time works.
diff --git a/sys/arch/riscv64/include/riscvreg.h b/sys/arch/riscv64/include/riscvreg.h
index 38b750c65a3..4a78c210567 100644
--- a/sys/arch/riscv64/include/riscvreg.h
+++ b/sys/arch/riscv64/include/riscvreg.h
@@ -115,6 +115,10 @@
#define USTATUS_UIE (1 << 0)
#define USTATUS_UPIE (1 << 4)
+#define SCOUNTEREN_CY (1 << 0)
+#define SCOUNTEREN_TM (1 << 1)
+#define SCOUNTEREN_IR (1 << 2)
+
#define MSTATUS_PRV_U 0 /* user */
#define MSTATUS_PRV_S 1 /* supervisor */
#define MSTATUS_PRV_H 2 /* hypervisor */
diff --git a/sys/arch/riscv64/riscv64/cpu.c b/sys/arch/riscv64/riscv64/cpu.c
index 9f83ed32ad6..a7b0df257f7 100644
--- a/sys/arch/riscv64/riscv64/cpu.c
+++ b/sys/arch/riscv64/riscv64/cpu.c
@@ -672,6 +672,7 @@ cpu_start_secondary(void)
cpu_startclock();
csr_clear(sstatus, SSTATUS_FS_MASK | SSTATUS_VS_MASK);
+ csr_write(scounteren, SCOUNTEREN_TM);
csr_set(sie, SIE_SSIE);
atomic_setbits_int(&ci->ci_flags, CPUF_RUNNING);
diff --git a/sys/arch/riscv64/riscv64/machdep.c b/sys/arch/riscv64/riscv64/machdep.c
index d2d75165092..65dd7ff9db1 100644
--- a/sys/arch/riscv64/riscv64/machdep.c
+++ b/sys/arch/riscv64/riscv64/machdep.c
@@ -582,6 +582,8 @@ initriscv(struct riscv_bootparams *rbp)
/* Set the per-CPU pointer. */
__asm volatile("mv tp, %0" :: "r"(&cpu_info_primary));
+ csr_write(scounteren, SCOUNTEREN_TM);
+
sbi_init();
/* The bootloader has loaded us into a 64MB block. */
riscv64: explicitly enable u-mode timer access