Introduce vtimer_set_timer() to program a vCPU’s virtual timer based on
guest-provided tick values. The function handles clearing pending timer
interrupts, converting ticks to nanoseconds, and correctly treating
(uint64_t)-1 as a request to disable the timer per the RISC-V SBI
specification.

Additionally, update vtimer_expired() to inject IRQ_VS_TIMER into
the target vCPU instead of panicking, enabling basic virtual timer
operation.

Signed-off-by: Oleksii Kurochko <[email protected]>
---
 xen/arch/riscv/include/asm/vtimer.h |  2 ++
 xen/arch/riscv/vtimer.c             | 30 ++++++++++++++++++++++++++++-
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/xen/arch/riscv/include/asm/vtimer.h 
b/xen/arch/riscv/include/asm/vtimer.h
index a2ca704cf0cc..2cacaf74b83b 100644
--- a/xen/arch/riscv/include/asm/vtimer.h
+++ b/xen/arch/riscv/include/asm/vtimer.h
@@ -22,4 +22,6 @@ void vcpu_timer_destroy(struct vcpu *v);
 
 int domain_vtimer_init(struct domain *d, struct xen_arch_domainconfig *config);
 
+void vtimer_set_timer(struct vtimer *t, const uint64_t ticks);
+
 #endif /* ASM__RISCV__VTIMER_H */
diff --git a/xen/arch/riscv/vtimer.c b/xen/arch/riscv/vtimer.c
index 5ba533690bc2..99a0c5986f1d 100644
--- a/xen/arch/riscv/vtimer.c
+++ b/xen/arch/riscv/vtimer.c
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 
+#include <xen/domain.h>
 #include <xen/sched.h>
+#include <xen/time.h>
 
 #include <public/xen.h>
 
@@ -15,7 +17,9 @@ int domain_vtimer_init(struct domain *d, struct 
xen_arch_domainconfig *config)
 
 static void vtimer_expired(void *data)
 {
-    panic("%s: TBD\n", __func__);
+    struct vtimer *t = data;
+
+    vcpu_set_interrupt(t->v, IRQ_VS_TIMER);
 }
 
 int vcpu_vtimer_init(struct vcpu *v)
@@ -37,3 +41,27 @@ void vcpu_timer_destroy(struct vcpu *v)
 
     kill_timer(&v->arch.vtimer.timer);
 }
+
+void vtimer_set_timer(struct vtimer *t, const uint64_t ticks)
+{
+    s_time_t expires = ticks_to_ns(ticks - boot_clock_cycles);
+
+    vcpu_unset_interrupt(t->v, IRQ_VS_TIMER);
+
+    /*
+     * According to the RISC-V sbi spec:
+     *   If the supervisor wishes to clear the timer interrupt without
+     *   scheduling the next timer event, it can either request a timer
+     *   interrupt infinitely far into the future (i.e., (uint64_t)-1),
+     *   or it can instead mask the timer interrupt by clearing sie.STIE CSR
+     *   bit.
+     */
+    if ( ticks == ((uint64_t)~0ULL) )
+    {
+        stop_timer(&t->timer);
+
+        return;
+    }
+
+    set_timer(&t->timer, expires);
+}
-- 
2.52.0


Reply via email to