transition.c
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <arch/cache.h> 4 #include <arch/lib_helpers.h> 5 #include <arch/mmu.h> 6 #include <arch/transition.h> 7 #include <assert.h> 8 9 void __weak exc_dispatch(struct exc_state *exc_state, uint64_t id) 10 { 11 /* Default weak implementation does nothing. */ 12 } 13 14 void exc_entry(struct exc_state *exc_state, uint64_t id) 15 { 16 struct elx_state *elx = &exc_state->elx; 17 struct regs *regs = &exc_state->regs; 18 uint8_t elx_mode; 19 20 elx->spsr = raw_read_spsr(); 21 elx->elr = raw_read_elr(); 22 23 elx_mode = get_mode_from_spsr(elx->spsr); 24 25 if (elx_mode == SPSR_USE_H) 26 regs->sp = (uint64_t)&exc_state[1]; 27 else 28 regs->sp = raw_read_sp_el0(); 29 30 exc_dispatch(exc_state, id); 31 } 32 33 void transition_to_el2(void *entry, void *arg, uint64_t spsr) 34 { 35 struct exc_state exc_state; 36 struct elx_state *elx = &exc_state.elx; 37 struct regs *regs = &exc_state.regs; 38 39 regs->x[X0_INDEX] = (uint64_t)arg; 40 elx->elr = (uint64_t)entry; 41 elx->spsr = spsr; 42 43 /* 44 * Policies enforced: 45 * 1. We support only transitions to EL2 46 * 2. We support transitions to Aarch64 mode only 47 * 48 * If any of the above conditions holds false, then we need a proper way 49 * to update SCR/HCR before removing the checks below 50 */ 51 assert(get_el_from_spsr(spsr) == EL2 && !(spsr & SPSR_ERET_32)); 52 53 /* Initialize SCR with defaults for running without secure monitor 54 (disable all traps, enable all instructions, run NS at AArch64). */ 55 raw_write_scr_el3(SCR_FIEN | SCR_API | SCR_APK | SCR_ST | SCR_RW | 56 SCR_HCE | SCR_SMD | SCR_RES1 | SCR_NS); 57 58 /* Initialize CPTR to not trap anything to EL3. */ 59 raw_write_cptr_el3(CPTR_EL3_TCPAC_DISABLE | CPTR_EL3_TTA_DISABLE | 60 CPTR_EL3_TFP_DISABLE); 61 62 /* ELR/SPSR: Write entry point and processor state of program */ 63 raw_write_elr_el3(elx->elr); 64 raw_write_spsr_el3(elx->spsr); 65 66 /* SCTLR: Initialize EL with everything disabled */ 67 raw_write_sctlr_el2(SCTLR_RES1); 68 69 /* SP_ELx: Initialize stack pointer */ 70 raw_write_sp_el2(elx->sp_elx); 71 72 /* Payloads expect to be entered with MMU disabled. Includes an ISB. */ 73 mmu_disable(); 74 75 /* Eret to the entry point */ 76 trans_switch(regs); 77 }