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
