RISC-V: KVM: update next_cycles in kvm_riscv_vcpu_update_vstimecmp() kvm_riscv_vcpu_update_vstimecmp() writes the guest's new timer compare value to CSR_VSTIMECMP but does not update t->next_cycles, unlike the hrtimer variant. t->next_cycles is only refreshed by kvm_riscv_vcpu_timer_sync() at VM-exit time, which runs before the SBI set_timer handler. If the vcpu is scheduled out or exits to userspace after handling an SBI set_timer call but before re-entering the guest, kvm_riscv_vcpu_timer_save() disarms the hardware (vstimecmp = -1UL, since 57f576e860d3) and kvm_riscv_vcpu_timer_restore() then restores the stale pre-SBI value, silently discarding the guest's armed timer. Guests arming their timer via SBI (e.g. OpenBSD/riscv64, which uses a one-shot design with no periodic fallback) lose their clock permanently within minutes under host load. Guests using Sstc directly are unaffected because timer_sync recaptures the hardware value at every exit. Fixes: 8f5cb44b1bae ("RISC-V: KVM: Support sstc extension") --- a/arch/riscv/kvm/vcpu_timer.c +++ b/arch/riscv/kvm/vcpu_timer.c @@ -71,6 +71,10 @@ static int kvm_riscv_vcpu_timer_cancel(struct kvm_vcpu_timer *t) static int kvm_riscv_vcpu_update_vstimecmp(struct kvm_vcpu *vcpu, u64 ncycles) { + struct kvm_vcpu_timer *t = &vcpu->arch.timer; + + t->next_cycles = ncycles; + #if defined(CONFIG_32BIT) ncsr_write(CSR_VSTIMECMP, ncycles & 0xFFFFFFFF); ncsr_write(CSR_VSTIMECMPH, ncycles >> 32);