AArch64 EL2 hypervisor for QEMU virt that boots at EL2
1#include "hv/arch.h"
2#include "hv/config.h"
3#include "hv/timer.h"
4#include "hv/uart.h"
5#include "hv/vcpu.h"
6
7static uint64_t g_cntfrq;
8
9void timer_init(void)
10{
11 g_cntfrq = arch_cntfrq_el0();
12}
13
14uint64_t timer_now(void)
15{
16 return arch_cntpct_el0();
17}
18
19void timer_dump(void)
20{
21 uart_puts("timer cntfrq=");
22 uart_put_dec64(g_cntfrq);
23 uart_puts(" cntpct=");
24 uart_put_dec64(timer_now());
25 uart_puts("\n");
26}
27
28void timer_vcpu_sync(struct vcpu *vcpu)
29{
30 if (vcpu == (struct vcpu *)0) {
31 return;
32 }
33
34 uint64_t ctl = vcpu->sysregs.cntv_ctl_el0;
35 bool enabled = (ctl & 1u) != 0u;
36 bool masked = (ctl & 2u) != 0u;
37 if (!enabled || masked) {
38 vcpu_clear_pending_irq(vcpu, CONFIG_VTIMER_IRQ);
39 return;
40 }
41
42 if (timer_now() >= vcpu->sysregs.cntv_cval_el0) {
43 vcpu->sysregs.cntv_ctl_el0 |= 4u;
44 vcpu_set_pending_irq(vcpu, CONFIG_VTIMER_IRQ);
45 } else {
46 vcpu->sysregs.cntv_ctl_el0 &= ~4ull;
47 vcpu_clear_pending_irq(vcpu, CONFIG_VTIMER_IRQ);
48 }
49}