AArch64 EL2 hypervisor for QEMU virt that boots at EL2
1

Configure Feed

Select the types of activity you want to include in your feed.

ariel / core / vcpu.c
7.6 kB 238 lines
1#include "hv/config.h" 2#include "hv/arch.h" 3#include "hv/panic.h" 4#include "hv/string.h" 5#include "hv/sysreg.h" 6#include "hv/uart.h" 7#include "hv/vcpu.h" 8 9_Static_assert(offsetof(struct trap_frame, x) == 0u, "trap_frame x offset"); 10_Static_assert(offsetof(struct trap_frame, sp_el0) == 248u, "trap_frame sp_el0 offset"); 11_Static_assert(offsetof(struct trap_frame, sp_el1) == 256u, "trap_frame sp_el1 offset"); 12_Static_assert(offsetof(struct trap_frame, elr_el2) == 264u, "trap_frame elr offset"); 13_Static_assert(offsetof(struct trap_frame, spsr_el2) == 272u, "trap_frame spsr offset"); 14_Static_assert(offsetof(struct trap_frame, esr_el2) == 280u, "trap_frame esr offset"); 15_Static_assert(offsetof(struct trap_frame, far_el2) == 288u, "trap_frame far offset"); 16_Static_assert(offsetof(struct trap_frame, hpfar_el2) == 296u, "trap_frame hpfar offset"); 17_Static_assert(sizeof(struct trap_frame) == 304u, "trap_frame size"); 18 19_Static_assert(offsetof(struct vcpu, x) == 0u, "vcpu x offset"); 20_Static_assert(offsetof(struct vcpu, sp_el0) == 248u, "vcpu sp_el0 offset"); 21_Static_assert(offsetof(struct vcpu, sp_el1) == 256u, "vcpu sp_el1 offset"); 22_Static_assert(offsetof(struct vcpu, pc) == 264u, "vcpu pc offset"); 23_Static_assert(offsetof(struct vcpu, pstate) == 272u, "vcpu pstate offset"); 24 25static struct vcpu *g_current_vcpu; 26 27void vcpu_init(struct vcpu *vcpu, uint32_t id, uint64_t entry, uint64_t stack_top) 28{ 29 BUG_ON(vcpu == (struct vcpu *)0); 30 hv_memset(vcpu, 0, sizeof(*vcpu)); 31 vcpu->id = id; 32 vcpu->state = VCPU_CREATED; 33 vcpu->pc = entry; 34 vcpu->pstate = 0x3c5u; 35 vcpu->sp_el1 = stack_top; 36 vcpu->sysregs.sctlr_el1 = 0x30d00800ull; 37 vcpu->sysregs.mair_el1 = 0xffull; 38 vcpu->sysregs.cntkctl_el1 = 0u; 39 vcpu->pending_virtual_irq = 0u; 40 vcpu->active_virtual_irq = 0u; 41 vcpu->state = VCPU_READY; 42} 43 44void vcpu_load_frame(struct vcpu *vcpu, const struct trap_frame *frame) 45{ 46 BUG_ON(vcpu == (struct vcpu *)0 || frame == (const struct trap_frame *)0); 47 for (uint32_t i = 0; i < 31u; i++) { 48 vcpu->x[i] = frame->x[i]; 49 } 50 vcpu->sp_el0 = frame->sp_el0; 51 vcpu->sp_el1 = frame->sp_el1; 52 vcpu->pc = frame->elr_el2; 53 vcpu->pstate = frame->spsr_el2; 54 vcpu->last_esr = frame->esr_el2; 55 vcpu->last_far = frame->far_el2; 56 vcpu->last_hpfar = frame->hpfar_el2; 57 arch_capture_el1_sysregs(vcpu); 58} 59 60void vcpu_store_frame(const struct vcpu *vcpu, struct trap_frame *frame) 61{ 62 BUG_ON(vcpu == (const struct vcpu *)0 || frame == (struct trap_frame *)0); 63 for (uint32_t i = 0; i < 31u; i++) { 64 frame->x[i] = vcpu->x[i]; 65 } 66 frame->sp_el0 = vcpu->sp_el0; 67 frame->sp_el1 = vcpu->sp_el1; 68 frame->elr_el2 = vcpu->pc; 69 frame->spsr_el2 = vcpu->pstate; 70} 71 72uint64_t vcpu_read_gpr(const struct vcpu *vcpu, uint32_t rt) 73{ 74 BUG_ON(vcpu == (const struct vcpu *)0); 75 if (rt >= 31u) { 76 return 0u; 77 } 78 return vcpu->x[rt]; 79} 80 81void vcpu_write_gpr(struct vcpu *vcpu, uint32_t rt, uint64_t value) 82{ 83 BUG_ON(vcpu == (struct vcpu *)0); 84 if (rt < 31u) { 85 vcpu->x[rt] = value; 86 } 87} 88 89void vcpu_set_pending_irq(struct vcpu *vcpu, uint32_t intid) 90{ 91 BUG_ON(vcpu == (struct vcpu *)0); 92 if (intid < 64u) { 93 vcpu->pending_virtual_irq |= (1ull << intid); 94 } 95} 96 97void vcpu_clear_pending_irq(struct vcpu *vcpu, uint32_t intid) 98{ 99 BUG_ON(vcpu == (struct vcpu *)0); 100 if (intid < 64u) { 101 vcpu->pending_virtual_irq &= ~(1ull << intid); 102 } 103} 104 105struct vcpu *vcpu_current(void) 106{ 107 return g_current_vcpu; 108} 109 110void vcpu_set_current(struct vcpu *vcpu) 111{ 112 g_current_vcpu = vcpu; 113} 114 115static void vcpu_dump_exception_telemetry(const struct vcpu *vcpu) 116{ 117 uart_puts("trap_ec ec="); 118 uart_put_hex64(ESR_EC_HVC64); 119 uart_puts(" name="); 120 uart_puts(esr_ec_name(ESR_EC_HVC64)); 121 uart_puts(" count="); 122 uart_put_dec64(vcpu->stats.hvc_calls); 123 uart_puts("\ntrap_ec ec="); 124 uart_put_hex64(ESR_EC_SYSREG); 125 uart_puts(" name="); 126 uart_puts(esr_ec_name(ESR_EC_SYSREG)); 127 uart_puts(" count="); 128 uart_put_dec64(vcpu->stats.sysreg_traps); 129 uart_puts("\ntrap_ec ec="); 130 uart_put_hex64(ESR_EC_SMC64); 131 uart_puts(" name="); 132 uart_puts(esr_ec_name(ESR_EC_SMC64)); 133 uart_puts(" denied="); 134 uart_put_dec64(vcpu->stats.smc_denied); 135 uart_puts("\ntrap_ec ec="); 136 uart_put_hex64(ESR_EC_WFI_WFE); 137 uart_puts(" name="); 138 uart_puts(esr_ec_name(ESR_EC_WFI_WFE)); 139 uart_puts(" count="); 140 uart_put_dec64(vcpu->stats.wfx_traps); 141 uart_puts("\ntrap_ec ec="); 142 uart_put_hex64(ESR_EC_IABT_LOWER); 143 uart_puts(" name="); 144 uart_puts(esr_ec_name(ESR_EC_IABT_LOWER)); 145 uart_puts(" count="); 146 uart_put_dec64(vcpu->stats.instruction_aborts); 147 uart_puts("\ntrap_ec ec="); 148 uart_put_hex64(ESR_EC_DABT_LOWER); 149 uart_puts(" name="); 150 uart_puts(esr_ec_name(ESR_EC_DABT_LOWER)); 151 uart_puts(" count="); 152 uart_put_dec64(vcpu->stats.data_aborts); 153 uart_puts("\ntrap_ec ec="); 154 uart_put_hex64(ESR_EC_UNKNOWN); 155 uart_puts(" name="); 156 uart_puts(esr_ec_name(ESR_EC_UNKNOWN)); 157 uart_puts(" count="); 158 uart_put_dec64(vcpu->stats.unknown_exceptions); 159 uart_puts("\n"); 160} 161 162void vcpu_dump(const struct vcpu *vcpu) 163{ 164 if (vcpu == (const struct vcpu *)0) { 165 uart_puts("vcpu none\n"); 166 return; 167 } 168 uart_puts("vcpu id="); 169 uart_put_dec64(vcpu->id); 170 uart_puts(" state="); 171 uart_put_dec64((uint64_t)vcpu->state); 172 uart_puts(" pc="); 173 uart_put_hex64(vcpu->pc); 174 uart_puts(" pstate="); 175 uart_put_hex64(vcpu->pstate); 176 uart_puts(" sp_el1="); 177 uart_put_hex64(vcpu->sp_el1); 178 uart_puts(" traps="); 179 uart_put_dec64(vcpu->stats.traps); 180 uart_puts(" last_ec="); 181 uart_put_hex64(esr_ec(vcpu->last_esr)); 182 uart_puts(" last_ecname="); 183 uart_puts(esr_ec_name(esr_ec(vcpu->last_esr))); 184 uart_puts(" injected_undefs="); 185 uart_put_dec64(vcpu->stats.injected_undefs); 186 uart_puts(" pending_irq="); 187 uart_put_hex64(vcpu->pending_virtual_irq); 188 uart_puts(" virq_inj="); 189 uart_put_dec64(vcpu->stats.virtual_irqs_injected); 190 uart_puts(" virq_done="); 191 uart_put_dec64(vcpu->stats.virtual_irqs_completed); 192 uart_puts(" timer_syncs="); 193 uart_put_dec64(vcpu->stats.timer_syncs); 194 uart_puts(" timer_delta="); 195 uart_put_dec64(vcpu->stats.timer_last_delta); 196 uart_puts("\n"); 197 vcpu_dump_exception_telemetry(vcpu); 198 for (uint32_t i = 0; i < 31u; i++) { 199 uart_puts("x"); 200 uart_put_dec64(i); 201 uart_puts("="); 202 uart_put_hex64(vcpu->x[i]); 203 uart_puts((i % 4u) == 3u ? "\n" : " "); 204 } 205 uart_puts("\n"); 206} 207 208bool vcpu_frame_selftest(void) 209{ 210 struct trap_frame frame; 211 struct trap_frame out; 212 struct vcpu vcpu; 213 214 hv_memset(&frame, 0, sizeof(frame)); 215 hv_memset(&out, 0, sizeof(out)); 216 hv_memset(&vcpu, 0, sizeof(vcpu)); 217 for (uint32_t i = 0; i < 31u; i++) { 218 frame.x[i] = 0x1000u + i; 219 } 220 frame.sp_el0 = 0x2000u; 221 frame.sp_el1 = 0x3000u; 222 frame.elr_el2 = 0x4000u; 223 frame.spsr_el2 = 0x3c5u; 224 frame.esr_el2 = 0x96000000u; 225 frame.far_el2 = 0x5000u; 226 frame.hpfar_el2 = 0x6000u; 227 228 vcpu_load_frame(&vcpu, &frame); 229 vcpu_store_frame(&vcpu, &out); 230 return hv_memcmp(frame.x, out.x, sizeof(frame.x)) == 0 && 231 frame.sp_el0 == out.sp_el0 && 232 frame.sp_el1 == out.sp_el1 && 233 frame.elr_el2 == out.elr_el2 && 234 frame.spsr_el2 == out.spsr_el2 && 235 vcpu.last_esr == frame.esr_el2 && 236 vcpu.last_far == frame.far_el2 && 237 vcpu.last_hpfar == frame.hpfar_el2; 238}