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
5.8 kB 185 lines
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}