133 lines
2.9 KiB
Plaintext
133 lines
2.9 KiB
Plaintext
#include <lib/macros.aarch64_asm.h>
|
|
|
|
.section .text
|
|
|
|
// noreturn void enter_in_el1(uint64_t entry, uint64_t sp, uint64_t sctlr,
|
|
// uint64_t mair, uint64_t tcr, uint64_t ttbr0,
|
|
// uint64_t ttbr1, uint64_t direct_map_offset)
|
|
// Configure EL1 state and jump to kernel. Must be called at EL1.
|
|
|
|
.global enter_in_el1
|
|
enter_in_el1:
|
|
msr spsel, #0
|
|
mov sp, x1
|
|
|
|
// Switch to the new page tables
|
|
|
|
// Point the EL1t handler to the continuation, such that after we page fault,
|
|
// execution continues and the kernel is entered.
|
|
adrp x8, 1f
|
|
add x8, x8, #:lo12:1f
|
|
add x8, x8, x7
|
|
msr vbar_el1, x8
|
|
isb
|
|
dsb sy
|
|
isb
|
|
|
|
// Switch the page table registers
|
|
msr mair_el1, x3
|
|
msr tcr_el1, x4
|
|
msr ttbr0_el1, x5
|
|
msr ttbr1_el1, x6
|
|
msr sctlr_el1, x2
|
|
isb
|
|
dsb sy
|
|
isb
|
|
|
|
// Jump to the higher half mapping in case we didn't immediately crash
|
|
br x8
|
|
|
|
// Alignment required by VBAR register
|
|
.align 11
|
|
1:
|
|
// Zero out VBAR to avoid confusion
|
|
msr vbar_el1, xzr
|
|
|
|
// Disable FP/SIMD/SVE
|
|
msr cpacr_el1, xzr
|
|
|
|
// Enter kernel in EL1
|
|
mov x8, #0x3c4
|
|
msr spsr_el1, x8
|
|
msr elr_el1, x0
|
|
|
|
mov x0, xzr
|
|
ZERO_REGS_EXCEPT_X0
|
|
|
|
eret
|
|
|
|
// noreturn void enter_in_el2(uint64_t entry, uint64_t sp, uint64_t sctlr,
|
|
// uint64_t mair, uint64_t tcr, uint64_t ttbr0,
|
|
// uint64_t ttbr1, uint64_t direct_map_offset)
|
|
// Enter kernel at EL2 with VHE. Must be called at EL2.
|
|
|
|
.global enter_in_el2
|
|
enter_in_el2:
|
|
msr spsel, #0
|
|
mov sp, x1
|
|
|
|
// Enable E2H if not already set
|
|
mrs x8, hcr_el2
|
|
orr x8, x8, #(1 << 34)
|
|
msr hcr_el2, x8
|
|
isb
|
|
|
|
// Switch page tables using VHE-redirected register names.
|
|
// Under VHE, *_el1 writes go to the EL2 register bank.
|
|
|
|
// Point the exception handler to the continuation so that if we page fault
|
|
// during the switch, execution continues at the kernel entry.
|
|
adrp x8, 5f
|
|
add x8, x8, #:lo12:5f
|
|
add x8, x8, x7
|
|
msr vbar_el1, x8
|
|
isb
|
|
dsb sy
|
|
isb
|
|
|
|
// Switch the page table registers (VHE redirects to EL2)
|
|
msr mair_el1, x3
|
|
msr tcr_el1, x4
|
|
msr ttbr0_el1, x5
|
|
msr ttbr1_el1, x6
|
|
msr sctlr_el1, x2
|
|
isb
|
|
dsb sy
|
|
isb
|
|
|
|
// Jump to the higher half mapping in case we didn't immediately crash
|
|
br x8
|
|
|
|
// Alignment required by VBAR register
|
|
.align 11
|
|
5:
|
|
// Zero out VBAR to avoid confusion
|
|
msr vbar_el1, xzr
|
|
|
|
// Configure EL2 state for VHE
|
|
|
|
// Don't trap counters
|
|
mov x8, #3
|
|
msr cnthctl_el2, x8
|
|
msr cntvoff_el2, xzr
|
|
|
|
// HCR: E2H + TGE + RW + SWIO
|
|
ldr x8, =0x488000002
|
|
msr hcr_el2, x8
|
|
|
|
// Disable FP/SIMD/SVE (VHE CPTR_EL2 layout, CPACR-like)
|
|
msr cptr_el2, xzr
|
|
msr hstr_el2, xzr
|
|
|
|
// Enter kernel in EL2
|
|
mov x8, #0x3c8
|
|
msr spsr_el1, x8
|
|
msr elr_el1, x0
|
|
|
|
mov x0, xzr
|
|
ZERO_REGS_EXCEPT_X0
|
|
|
|
eret
|
|
|
|
.section .note.GNU-stack,"",%progbits
|