#include "hv/arch.h" #include "hv/config.h" #include "hv/timer.h" #include "hv/uart.h" #include "hv/vcpu.h" static uint64_t g_cntfrq; void timer_init(void) { g_cntfrq = arch_cntfrq_el0(); } uint64_t timer_now(void) { return arch_cntpct_el0(); } void timer_dump(void) { uart_puts("timer cntfrq="); uart_put_dec64(g_cntfrq); uart_puts(" cntpct="); uart_put_dec64(timer_now()); uart_puts("\n"); } void timer_vcpu_sync(struct vcpu *vcpu) { uint64_t now; if (vcpu == (struct vcpu *)0) { return; } vcpu->stats.timer_syncs++; now = timer_now(); uint64_t ctl = vcpu->sysregs.cntv_ctl_el0; bool enabled = (ctl & 1u) != 0u; bool masked = (ctl & 2u) != 0u; if (!enabled || masked) { vcpu_clear_pending_irq(vcpu, CONFIG_VTIMER_IRQ); return; } if (now >= vcpu->sysregs.cntv_cval_el0) { vcpu->stats.timer_last_delta = now - vcpu->sysregs.cntv_cval_el0; vcpu->sysregs.cntv_ctl_el0 |= 4u; vcpu_set_pending_irq(vcpu, CONFIG_VTIMER_IRQ); } else { vcpu->stats.timer_last_delta = vcpu->sysregs.cntv_cval_el0 - now; vcpu->sysregs.cntv_ctl_el0 &= ~4ull; vcpu_clear_pending_irq(vcpu, CONFIG_VTIMER_IRQ); } }