Enable Xen to handle timer reprogramming on RISC-V using
standard SBI calls.
Add a RISC-V implementation of reprogram_timer() to replace the stub:
- Re-enable the function previously stubbed in stubs.c.
- Use sbi_set_timer() to program the timer for the given timeout.
- Disable the timer when timeout == 0 by clearing the SIE.STIE bit.
- Calculate the deadline based on the current boot clock cycle count
and timer ticks.
- Ensure correct behavior when the deadline is already passed.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/riscv/stubs.c | 5 -----
xen/arch/riscv/time.c | 31 +++++++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/xen/arch/riscv/stubs.c b/xen/arch/riscv/stubs.c
index 68ee859ca1a8..d120274af2fe 100644
--- a/xen/arch/riscv/stubs.c
+++ b/xen/arch/riscv/stubs.c
@@ -21,11 +21,6 @@ nodemask_t __read_mostly node_online_map = { { [0] = 1UL } };
/* time.c */
-int reprogram_timer(s_time_t timeout)
-{
- BUG_ON("unimplemented");
-}
-
void send_timer_event(struct vcpu *v)
{
BUG_ON("unimplemented");
diff --git a/xen/arch/riscv/time.c b/xen/arch/riscv/time.c
index e962f8518d78..53ba1cfb4a99 100644
--- a/xen/arch/riscv/time.c
+++ b/xen/arch/riscv/time.c
@@ -4,8 +4,12 @@
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/sections.h>
+#include <xen/time.h>
#include <xen/types.h>
+#include <asm/csr.h>
+#include <asm/sbi.h>
+
unsigned long __ro_after_init cpu_khz; /* CPU clock frequency in kHz. */
uint64_t __ro_after_init boot_clock_cycles;
@@ -39,6 +43,33 @@ static void __init preinit_dt_xen_time(void)
cpu_khz = rate / 1000;
}
+int reprogram_timer(s_time_t timeout)
+{
+ uint64_t deadline, now;
+ int rc;
+
+ if ( timeout == 0 )
+ {
+ /* Disable timers */
+ csr_clear(CSR_SIE, BIT(IRQ_S_TIMER, UL));
+
+ return 1;
+ }
+
+ deadline = ns_to_ticks(timeout) + boot_clock_cycles;
+ now = get_cycles();
+ if ( deadline <= now )
+ return 0;
+
+ /* Enable timer */
+ csr_set(CSR_SIE, BIT(IRQ_S_TIMER, UL));
+
+ if ( (rc = sbi_set_timer(deadline)) )
+ panic("%s: timer wasn't set because: %d\n", __func__, rc);
+
+ return 1;
+}
+
void __init preinit_xen_time(void)
{
if ( acpi_disabled )
--
2.52.0