diff options
author | Furquan Shaikh <furquan@google.com> | 2014-08-30 21:59:11 -0700 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2015-03-28 07:04:44 +0100 |
commit | 668316bdccdb0372c7e450398ad1c81a9205d158 (patch) | |
tree | c6d3a3da429fd32b3528de8cdca7852567ada87e /src/arch/arm64/include | |
parent | 0b606730c97ee2599b9992f6e5c4aa7d91176523 (diff) | |
download | coreboot-668316bdccdb0372c7e450398ad1c81a9205d158.tar.xz |
arm64: Add support for transition library
Transition library provides the following functionalities:
1) Setup the environment for switching to any particular EL and jump to the
loaded program at that EL. In short "Execute program X at exception level Y
using the state Z"
2) Provides routines for exception entry and exception exit that can be used by
any program to implement exception handling. The only routine required by the
program would be exc_dispatch which handles the exception in its own required
way and returns by making a call to exc_exit. On exc_exit, the transition
library unwinds the whole stack by popping out the saved state of xregs
BUG=chrome-os-partner:30785
BRANCH=None
TEST=Compiles successfully and exceptions are tested for ramstage on ryu
Change-Id: I8116556109665e61a53e4b3987d649e3cfed64a1
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 8ab888e8cae0c5f1e79b0e16ca292869f16f1cca
Original-Change-Id: I90f664ac657258724dc0c79bd9f6ceef70064f90
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/216375
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9070
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/arch/arm64/include')
-rw-r--r-- | src/arch/arm64/include/arch/transition.h | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/src/arch/arm64/include/arch/transition.h b/src/arch/arm64/include/arch/transition.h new file mode 100644 index 0000000000..e8ded5f2aa --- /dev/null +++ b/src/arch/arm64/include/arch/transition.h @@ -0,0 +1,188 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __ARCH_ARM64_TRANSITION_H__ +#define __ARCH_ARM64_TRANSITION_H__ + +/* ======================== Transition Library ================================= + * Transition library provides two main functionalities: + * 1) It allows any program X to be executed at EL Y using the state Z. It + * provides struct exc_state which holds the state of the EL to which we want to + * execute X at. Before performing an eret to the entry point of the program X, + * it initializes required registers using this exc_state structure. Here, X0 = + * args to the program X. IMP!!! : We do not initialize SP_EL0 for the program + * X, the program will have to handle that on its own. This is because while + * performing an eret to X, we could make SP_EL0 point to regs structure which + * then follows common exception exit path. + * 2) It serves as a common mechanism for handling exception entry and exit at + * any given EL. On entry to an exception, SP_ELx is selected by default. The + * exc entry routine stores all xregs and jumps to exc_entry which + * saves ELR, SPSR, EL, Mode and other information about the state from which + * exception was generated. On exit, xregs are restored by unwinding of SP_ELx. + * ============================================================================= + */ + +/* Macros for EL mode in SPSR */ +#define STACK_POP_BYTES 16 +#define STACK_PUSH_BYTES -16 + +#ifndef __ASSEMBLY__ + +#include <stdint.h> +#include <arch/lib_helpers.h> + +#define XI_INDEX(i) X##i##_INDEX = i + +enum { + XI_INDEX(0), + XI_INDEX(1), + XI_INDEX(2), + XI_INDEX(3), + XI_INDEX(4), + XI_INDEX(5), + XI_INDEX(6), + XI_INDEX(7), + XI_INDEX(8), + XI_INDEX(9), + XI_INDEX(10), + XI_INDEX(11), + XI_INDEX(12), + XI_INDEX(13), + XI_INDEX(14), + XI_INDEX(15), + XI_INDEX(16), + XI_INDEX(17), + XI_INDEX(18), + XI_INDEX(19), + XI_INDEX(20), + XI_INDEX(21), + XI_INDEX(22), + XI_INDEX(23), + XI_INDEX(24), + XI_INDEX(25), + XI_INDEX(26), + XI_INDEX(27), + XI_INDEX(28), + XI_INDEX(29), + XI_INDEX(30), + XMAX_INDEX, +}; + +/* + * Important: Any changes made to the two structures below should reflect in the + * exc_prologue and exc_exit routines in transition_asm.S + */ +struct regs { + uint64_t sp; + uint64_t x[31]; +}; + +struct elx_state { + uint64_t spsr; + uint64_t sp_el0; + uint64_t sp_elx; + uint64_t elr; +}; + +struct exc_state { + struct elx_state elx; + struct regs regs; +}; + +/* + * get_eret_EL returns the value of the exception state to which we will be + * returning. This value is saved in SPSR before performing an eret. + * + * Exception mode is defined by M[3:0] bits in SPSR: + * ( M[3:2] = EL, M[1] = unused, M[0] = t/h mode for stack + * + * 0b0000 EL0t + * 0b0100 EL1t + * 0b0101 EL1h + * 0b1000 EL2t + * 0b1001 EL2h + * 0b1100 EL3t + * 0b1101 EL3h + */ + +static inline uint8_t get_eret_el(uint8_t el, uint8_t l_or_h) +{ + uint8_t el_mode = el << CURRENT_EL_SHIFT; + + el_mode |= l_or_h; + + return el_mode; +} + +static inline uint8_t get_el_from_spsr(uint64_t spsr) +{ + return ((spsr >> CURRENT_EL_SHIFT) & CURRENT_EL_MASK); +} + +static inline uint8_t get_mode_from_spsr(uint64_t spsr) +{ + return (spsr & SPSR_L_H_MASK); +} + +/* Transitions supported are: + * 1. elx --> elx - 1 + * 2. Transitions to aarch64 state + * + * Other than this, if any transition needs to be supported, relevant changes + * need to be done to hcr/scr registers. + */ + +/* + * User of transition library can make a call to transition_with_entry and pass + * the entry point and its argument which are put into elr and x0 by this + * function. After that it makes a call to transition. + */ +void transition_with_entry(void *entry, void *arg, struct exc_state *exc_state); +/* + * transition function sets up all the registers as per the struct elx_state + * before jumping to trans_switch. + */ +void transition(struct exc_state *exc_state); + +/* + * exc_exit it called while returning from an exception. It expects pointer to + * the regs structure on stack so that it can unwind the used stack. + */ +void exc_exit(struct regs *regs); +/* + * trans_switch is called by the non-exception path i.e. transition C code + * while making a transition to lower EL. It select L mode so that SP_EL0 is + * used during the unwinding in exc_exit. + */ +void trans_switch(struct regs *regs); +/* exc_set_vbar sets up the vbar for exception vectors. */ +void exc_set_vbar(void); + +/* exc_dispatch is the user-defined exception handler. */ +void exc_dispatch(struct exc_state *exc_state, uint64_t id); +/* + * exc_entry is the C based component of the exception entry before we + * jump to user-defined handler. This initializes all the regs in elx_state and + * also sets the sp value in regs structure. + */ +void exc_entry(struct exc_state *exc_state, uint64_t id); + +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM64_TRANSITION_H__ */ |