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 / arch / aarch64 / arch.c
6.9 kB 276 lines
1#include "hv/arch.h" 2#include "hv/config.h" 3#include "hv/mmio.h" 4#include "hv/panic.h" 5#include "hv/uart.h" 6#include "hv/vcpu.h" 7 8uint64_t arch_current_el(void) 9{ 10 uint64_t v; 11 __asm__ volatile("mrs %0, CurrentEL" : "=r"(v)); 12 return (v >> 2u) & 0x3u; 13} 14 15uint64_t arch_mpidr_el1(void) 16{ 17 uint64_t v; 18 __asm__ volatile("mrs %0, mpidr_el1" : "=r"(v)); 19 return v; 20} 21 22uint64_t arch_cntpct_el0(void) 23{ 24 uint64_t v; 25 __asm__ volatile("mrs %0, cntpct_el0" : "=r"(v)); 26 return v; 27} 28 29uint64_t arch_cntfrq_el0(void) 30{ 31 uint64_t v; 32 __asm__ volatile("mrs %0, cntfrq_el0" : "=r"(v)); 33 return v; 34} 35 36uint64_t arch_vectors_base(void) 37{ 38 return (uint64_t)(uintptr_t)__vectors_el2; 39} 40 41bool arch_vectors_aligned(void) 42{ 43 return hv_is_aligned_u64(arch_vectors_base(), 2048u); 44} 45 46uint64_t arch_irq_save(void) 47{ 48 uint64_t flags; 49 __asm__ volatile("mrs %0, daif\nmsr daifset, #0xf\nisb" : "=r"(flags) :: "memory"); 50 return flags; 51} 52 53void arch_irq_restore(uint64_t flags) 54{ 55 __asm__ volatile("msr daif, %0\nisb" :: "r"(flags) : "memory"); 56} 57 58void arch_context_barrier(void) 59{ 60 __asm__ volatile("dsb ish\nisb" ::: "memory"); 61} 62 63void arch_dump_el2_state(void) 64{ 65 uint64_t current_el; 66 uint64_t hcr; 67 uint64_t vtcr; 68 uint64_t vttbr; 69 uint64_t vbar; 70 uint64_t sctlr; 71 uint64_t mair; 72 uint64_t sp; 73 74 __asm__ volatile( 75 "mrs %0, CurrentEL\n" 76 "mrs %1, hcr_el2\n" 77 "mrs %2, vtcr_el2\n" 78 "mrs %3, vttbr_el2\n" 79 "mrs %4, vbar_el2\n" 80 "mrs %5, sctlr_el2\n" 81 "mrs %6, mair_el2\n" 82 "mov %7, sp\n" 83 : "=r"(current_el), "=r"(hcr), "=r"(vtcr), "=r"(vttbr), 84 "=r"(vbar), "=r"(sctlr), "=r"(mair), "=r"(sp)); 85 86 uart_puts("cpu current_el="); 87 uart_put_hex64(current_el); 88 uart_puts(" hcr_el2="); 89 uart_put_hex64(hcr); 90 uart_puts(" vtcr_el2="); 91 uart_put_hex64(vtcr); 92 uart_puts(" vttbr_el2="); 93 uart_put_hex64(vttbr); 94 uart_puts("\n"); 95 uart_puts("cpu vbar_el2="); 96 uart_put_hex64(vbar); 97 uart_puts(" sctlr_el2="); 98 uart_put_hex64(sctlr); 99 uart_puts(" mair_el2="); 100 uart_put_hex64(mair); 101 uart_puts(" sp="); 102 uart_put_hex64(sp); 103 uart_puts("\n"); 104} 105 106void arch_install_vectors(void) 107{ 108 if (!arch_vectors_aligned()) { 109 panic("VBAR_EL2 vector table is not 2KB aligned"); 110 } 111 __asm__ volatile("msr vbar_el2, %0\nisb" :: "r"(arch_vectors_base()) : "memory"); 112} 113 114void arch_tlbi_vmalle1is(void) 115{ 116 __asm__ volatile("dsb ish\n tlbi vmalle1is\n dsb ish\n isb" ::: "memory"); 117} 118 119void arch_enable_el2_mmu(uint64_t ttbr0, uint64_t tcr, uint64_t mair) 120{ 121 uint64_t sctlr; 122 123 __asm__ volatile( 124 "dsb sy\n" 125 "msr ttbr0_el2, %0\n" 126 "msr tcr_el2, %1\n" 127 "msr mair_el2, %2\n" 128 "isb\n" 129 "tlbi alle2\n" 130 "dsb sy\n" 131 "isb\n" 132 :: "r"(ttbr0), "r"(tcr), "r"(mair) 133 : "memory"); 134 135 __asm__ volatile("mrs %0, sctlr_el2" : "=r"(sctlr)); 136 sctlr |= HV_BIT(0) | HV_BIT(2) | HV_BIT(12); 137 __asm__ volatile( 138 "msr sctlr_el2, %0\n" 139 "isb\n" 140 :: "r"(sctlr) 141 : "memory"); 142} 143 144void arch_el2_configure(uint64_t vttbr, uint64_t vtcr) 145{ 146 const uint64_t mair = 0x000000000000ff00ull | 0x0000000000000004ull; 147 uint64_t hcr = 0; 148 149 hcr |= HV_BIT(31); 150 hcr |= HV_BIT(0); 151#if !CONFIG_BOOT_LINUX 152 hcr |= HV_BIT(26); 153#endif 154 hcr |= HV_BIT(22); 155 hcr |= HV_BIT(21); 156 hcr |= HV_BIT(19); 157#if !CONFIG_BOOT_LINUX 158 hcr |= HV_BIT(20); 159 hcr |= HV_BIT(18) | HV_BIT(17) | HV_BIT(16) | HV_BIT(15); 160#endif 161#if CONFIG_ENABLE_WFI_TRAPS 162 hcr |= HV_BIT(14) | HV_BIT(13); 163#endif 164 165 __asm__ volatile( 166 "msr mair_el2, %0\n" 167 "msr vtcr_el2, %1\n" 168 "msr vttbr_el2, %2\n" 169 "msr mdcr_el2, %3\n" 170 "msr cptr_el2, %4\n" 171 "msr cnthctl_el2, %5\n" 172 "msr hcr_el2, %6\n" 173 "isb\n" 174 :: "r"(mair), "r"(vtcr), "r"(vttbr), 175 "r"(0ull), "r"(0x33ffull), "r"(3ull), "r"(hcr) 176 : "memory"); 177} 178 179void arch_prepare_guest_entry(struct vcpu *vcpu) 180{ 181 BUG_ON(vcpu == (struct vcpu *)0); 182 __asm__ volatile( 183 "msr sctlr_el1, %0\n" 184 "msr ttbr0_el1, %1\n" 185 "msr ttbr1_el1, %2\n" 186 "msr tcr_el1, %3\n" 187 "msr mair_el1, %4\n" 188 "msr vbar_el1, %5\n" 189 "msr cntkctl_el1, %6\n" 190 "isb\n" 191 :: "r"(vcpu->sysregs.sctlr_el1), "r"(vcpu->sysregs.ttbr0_el1), 192 "r"(vcpu->sysregs.ttbr1_el1), "r"(vcpu->sysregs.tcr_el1), 193 "r"(vcpu->sysregs.mair_el1), "r"(vcpu->sysregs.vbar_el1), 194 "r"(vcpu->sysregs.cntkctl_el1) 195 : "memory"); 196} 197 198void arch_capture_el1_sysregs(struct vcpu *vcpu) 199{ 200 BUG_ON(vcpu == (struct vcpu *)0); 201 __asm__ volatile( 202 "mrs %0, vbar_el1\n" 203 "mrs %1, elr_el1\n" 204 "mrs %2, spsr_el1\n" 205 "mrs %3, esr_el1\n" 206 "mrs %4, far_el1\n" 207 : "=r"(vcpu->sysregs.vbar_el1), "=r"(vcpu->sysregs.elr_el1), 208 "=r"(vcpu->sysregs.spsr_el1), "=r"(vcpu->sysregs.esr_el1), 209 "=r"(vcpu->sysregs.far_el1)); 210} 211 212void arch_sync_el1_sysregs(const struct vcpu *vcpu) 213{ 214 BUG_ON(vcpu == (const struct vcpu *)0); 215 __asm__ volatile( 216 "dsb sy\n" 217 "msr mair_el1, %0\n" 218 "msr tcr_el1, %1\n" 219 "msr ttbr0_el1, %2\n" 220 "msr ttbr1_el1, %3\n" 221 "msr vbar_el1, %4\n" 222 "msr cntkctl_el1, %5\n" 223 "msr cpacr_el1, %6\n" 224 "isb\n" 225 "msr sctlr_el1, %7\n" 226 "isb\n" 227 :: "r"(vcpu->sysregs.mair_el1), "r"(vcpu->sysregs.tcr_el1), 228 "r"(vcpu->sysregs.ttbr0_el1), "r"(vcpu->sysregs.ttbr1_el1), 229 "r"(vcpu->sysregs.vbar_el1), "r"(vcpu->sysregs.cntkctl_el1), 230 "r"(vcpu->sysregs.cpacr_el1), "r"(vcpu->sysregs.sctlr_el1) 231 : "memory"); 232} 233 234void arch_advance_guest_pc(struct vcpu *vcpu) 235{ 236 BUG_ON(vcpu == (struct vcpu *)0); 237 vcpu->pc += 4u; 238} 239 240void arch_inject_guest_undef(struct vcpu *vcpu) 241{ 242 const uint64_t current_el_spx_sync = 0x200u; 243 const uint64_t pstate_el1h_daif = 0x3c5u; 244 245 BUG_ON(vcpu == (struct vcpu *)0); 246 arch_capture_el1_sysregs(vcpu); 247 if (!hv_is_aligned_u64(vcpu->sysregs.vbar_el1, 2048u)) { 248 vcpu->state = VCPU_PAUSED; 249 return; 250 } 251 252 vcpu->sysregs.elr_el1 = vcpu->pc; 253 vcpu->sysregs.spsr_el1 = vcpu->pstate; 254 vcpu->sysregs.esr_el1 = 0u; 255 vcpu->sysregs.far_el1 = 0u; 256 vcpu->pc = vcpu->sysregs.vbar_el1 + current_el_spx_sync; 257 vcpu->pstate = pstate_el1h_daif; 258 vcpu->stats.injected_undefs++; 259 260 __asm__ volatile( 261 "msr elr_el1, %0\n" 262 "msr spsr_el1, %1\n" 263 "msr esr_el1, %2\n" 264 "msr far_el1, %3\n" 265 "isb\n" 266 :: "r"(vcpu->sysregs.elr_el1), "r"(vcpu->sysregs.spsr_el1), 267 "r"(vcpu->sysregs.esr_el1), "r"(vcpu->sysregs.far_el1) 268 : "memory"); 269} 270 271void arch_halt(void) 272{ 273 for (;;) { 274 __asm__ volatile("wfe"); 275 } 276}