From 668316bdccdb0372c7e450398ad1c81a9205d158 Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Sat, 30 Aug 2014 21:59:11 -0700 Subject: 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 Original-Commit-Id: 8ab888e8cae0c5f1e79b0e16ca292869f16f1cca Original-Change-Id: I90f664ac657258724dc0c79bd9f6ceef70064f90 Original-Signed-off-by: Furquan Shaikh Original-Reviewed-on: https://chromium-review.googlesource.com/216375 Original-Reviewed-by: Aaron Durbin Original-Tested-by: Furquan Shaikh Original-Commit-Queue: Furquan Shaikh Reviewed-on: http://review.coreboot.org/9070 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- src/arch/arm64/include/arch/transition.h | 188 +++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 src/arch/arm64/include/arch/transition.h (limited to 'src/arch/arm64/include') 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 +#include + +#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__ */ -- cgit v1.2.3