AArch64 EL2 hypervisor for QEMU virt that boots at EL2
1#include "hv/config.h"
2#include "hv/arch.h"
3#include "hv/panic.h"
4#include "hv/string.h"
5#include "hv/uart.h"
6#include "hv/vcpu.h"
7
8_Static_assert(offsetof(struct trap_frame, x) == 0u, "trap_frame x offset");
9_Static_assert(offsetof(struct trap_frame, sp_el0) == 248u, "trap_frame sp_el0 offset");
10_Static_assert(offsetof(struct trap_frame, sp_el1) == 256u, "trap_frame sp_el1 offset");
11_Static_assert(offsetof(struct trap_frame, elr_el2) == 264u, "trap_frame elr offset");
12_Static_assert(offsetof(struct trap_frame, spsr_el2) == 272u, "trap_frame spsr offset");
13_Static_assert(offsetof(struct trap_frame, esr_el2) == 280u, "trap_frame esr offset");
14_Static_assert(offsetof(struct trap_frame, far_el2) == 288u, "trap_frame far offset");
15_Static_assert(offsetof(struct trap_frame, hpfar_el2) == 296u, "trap_frame hpfar offset");
16_Static_assert(sizeof(struct trap_frame) == 304u, "trap_frame size");
17
18_Static_assert(offsetof(struct vcpu, x) == 0u, "vcpu x offset");
19_Static_assert(offsetof(struct vcpu, sp_el0) == 248u, "vcpu sp_el0 offset");
20_Static_assert(offsetof(struct vcpu, sp_el1) == 256u, "vcpu sp_el1 offset");
21_Static_assert(offsetof(struct vcpu, pc) == 264u, "vcpu pc offset");
22_Static_assert(offsetof(struct vcpu, pstate) == 272u, "vcpu pstate offset");
23
24static struct vcpu *g_current_vcpu;
25
26void vcpu_init(struct vcpu *vcpu, uint32_t id, uint64_t entry, uint64_t stack_top)
27{
28 BUG_ON(vcpu == (struct vcpu *)0);
29 hv_memset(vcpu, 0, sizeof(*vcpu));
30 vcpu->id = id;
31 vcpu->state = VCPU_CREATED;
32 vcpu->pc = entry;
33 vcpu->pstate = 0x3c5u;
34 vcpu->sp_el1 = stack_top;
35 vcpu->sysregs.sctlr_el1 = 0x30d00800ull;
36 vcpu->sysregs.mair_el1 = 0xffull;
37 vcpu->sysregs.cntkctl_el1 = 0u;
38 vcpu->pending_virtual_irq = 0u;
39 vcpu->active_virtual_irq = 0u;
40 vcpu->state = VCPU_READY;
41}
42
43void vcpu_load_frame(struct vcpu *vcpu, const struct trap_frame *frame)
44{
45 BUG_ON(vcpu == (struct vcpu *)0 || frame == (const struct trap_frame *)0);
46 for (uint32_t i = 0; i < 31u; i++) {
47 vcpu->x[i] = frame->x[i];
48 }
49 vcpu->sp_el0 = frame->sp_el0;
50 vcpu->sp_el1 = frame->sp_el1;
51 vcpu->pc = frame->elr_el2;
52 vcpu->pstate = frame->spsr_el2;
53 vcpu->last_esr = frame->esr_el2;
54 vcpu->last_far = frame->far_el2;
55 vcpu->last_hpfar = frame->hpfar_el2;
56 arch_capture_el1_sysregs(vcpu);
57}
58
59void vcpu_store_frame(const struct vcpu *vcpu, struct trap_frame *frame)
60{
61 BUG_ON(vcpu == (const struct vcpu *)0 || frame == (struct trap_frame *)0);
62 for (uint32_t i = 0; i < 31u; i++) {
63 frame->x[i] = vcpu->x[i];
64 }
65 frame->sp_el0 = vcpu->sp_el0;
66 frame->sp_el1 = vcpu->sp_el1;
67 frame->elr_el2 = vcpu->pc;
68 frame->spsr_el2 = vcpu->pstate;
69}
70
71uint64_t vcpu_read_gpr(const struct vcpu *vcpu, uint32_t rt)
72{
73 BUG_ON(vcpu == (const struct vcpu *)0);
74 if (rt >= 31u) {
75 return 0u;
76 }
77 return vcpu->x[rt];
78}
79
80void vcpu_write_gpr(struct vcpu *vcpu, uint32_t rt, uint64_t value)
81{
82 BUG_ON(vcpu == (struct vcpu *)0);
83 if (rt < 31u) {
84 vcpu->x[rt] = value;
85 }
86}
87
88void vcpu_set_pending_irq(struct vcpu *vcpu, uint32_t intid)
89{
90 BUG_ON(vcpu == (struct vcpu *)0);
91 if (intid < 64u) {
92 vcpu->pending_virtual_irq |= (1ull << intid);
93 }
94}
95
96void vcpu_clear_pending_irq(struct vcpu *vcpu, uint32_t intid)
97{
98 BUG_ON(vcpu == (struct vcpu *)0);
99 if (intid < 64u) {
100 vcpu->pending_virtual_irq &= ~(1ull << intid);
101 }
102}
103
104struct vcpu *vcpu_current(void)
105{
106 return g_current_vcpu;
107}
108
109void vcpu_set_current(struct vcpu *vcpu)
110{
111 g_current_vcpu = vcpu;
112}
113
114void vcpu_dump(const struct vcpu *vcpu)
115{
116 if (vcpu == (const struct vcpu *)0) {
117 uart_puts("vcpu none\n");
118 return;
119 }
120 uart_puts("vcpu id=");
121 uart_put_dec64(vcpu->id);
122 uart_puts(" state=");
123 uart_put_dec64((uint64_t)vcpu->state);
124 uart_puts(" pc=");
125 uart_put_hex64(vcpu->pc);
126 uart_puts(" pstate=");
127 uart_put_hex64(vcpu->pstate);
128 uart_puts(" sp_el1=");
129 uart_put_hex64(vcpu->sp_el1);
130 uart_puts(" traps=");
131 uart_put_dec64(vcpu->stats.traps);
132 uart_puts(" injected_undefs=");
133 uart_put_dec64(vcpu->stats.injected_undefs);
134 uart_puts(" pending_irq=");
135 uart_put_hex64(vcpu->pending_virtual_irq);
136 uart_puts(" virq_inj=");
137 uart_put_dec64(vcpu->stats.virtual_irqs_injected);
138 uart_puts(" virq_done=");
139 uart_put_dec64(vcpu->stats.virtual_irqs_completed);
140 uart_puts(" timer_syncs=");
141 uart_put_dec64(vcpu->stats.timer_syncs);
142 uart_puts(" timer_delta=");
143 uart_put_dec64(vcpu->stats.timer_last_delta);
144 uart_puts("\n");
145 for (uint32_t i = 0; i < 31u; i++) {
146 uart_puts("x");
147 uart_put_dec64(i);
148 uart_puts("=");
149 uart_put_hex64(vcpu->x[i]);
150 uart_puts((i % 4u) == 3u ? "\n" : " ");
151 }
152 uart_puts("\n");
153}
154
155bool vcpu_frame_selftest(void)
156{
157 struct trap_frame frame;
158 struct trap_frame out;
159 struct vcpu vcpu;
160
161 hv_memset(&frame, 0, sizeof(frame));
162 hv_memset(&out, 0, sizeof(out));
163 hv_memset(&vcpu, 0, sizeof(vcpu));
164 for (uint32_t i = 0; i < 31u; i++) {
165 frame.x[i] = 0x1000u + i;
166 }
167 frame.sp_el0 = 0x2000u;
168 frame.sp_el1 = 0x3000u;
169 frame.elr_el2 = 0x4000u;
170 frame.spsr_el2 = 0x3c5u;
171 frame.esr_el2 = 0x96000000u;
172 frame.far_el2 = 0x5000u;
173 frame.hpfar_el2 = 0x6000u;
174
175 vcpu_load_frame(&vcpu, &frame);
176 vcpu_store_frame(&vcpu, &out);
177 return hv_memcmp(frame.x, out.x, sizeof(frame.x)) == 0 &&
178 frame.sp_el0 == out.sp_el0 &&
179 frame.sp_el1 == out.sp_el1 &&
180 frame.elr_el2 == out.elr_el2 &&
181 frame.spsr_el2 == out.spsr_el2 &&
182 vcpu.last_esr == frame.esr_el2 &&
183 vcpu.last_far == frame.far_el2 &&
184 vcpu.last_hpfar == frame.hpfar_el2;
185}