diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 9df7128..280aa88 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -64,6 +64,7 @@ bakery_lock.o \ runtime_svc.o \ early_exceptions.o \ + context_mgmt.o \ context.o BL31_ENTRY_POINT := bl31_entrypoint diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c index 538280a..fb69718 100644 --- a/bl31/bl31_main.c +++ b/bl31/bl31_main.c @@ -38,6 +38,15 @@ #include #include #include +#include + +/******************************************************************************* + * Simple function to initialise all BL31 helper libraries. + ******************************************************************************/ +void bl31_lib_init() +{ + cm_init(); +} void bl31_arch_next_el_setup(void); @@ -59,7 +68,8 @@ #if defined (__GNUC__) printf("BL31 Built : %s, %s\n\r", __TIME__, __DATE__); #endif - + /* Initialise helper libraries */ + bl31_lib_init(); /* Initialize the runtime services e.g. psci */ runtime_svc_init(mpidr); diff --git a/bl31/context_mgmt.c b/bl31/context_mgmt.c new file mode 100644 index 0000000..bbdbad2 --- /dev/null +++ b/bl31/context_mgmt.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Data structure which holds the pointers to non-secure and secure security + * state contexts for each cpu. It is aligned to the cache line boundary to + * allow efficient concurrent manipulation of these pointers on different cpus + ******************************************************************************/ +typedef struct { + void *ptr[2]; +} __aligned (CACHE_WRITEBACK_GRANULE) context_info; + +static context_info cm_context_info[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * Context management library initialisation routine. This library is used by + * runtime services to share pointers to 'cpu_context' structures for the secure + * and non-secure states. Management of the structures and their associated + * memory is not done by the context management library e.g. the PSCI service + * manages the cpu context used for entry from and exit to the non-secure state. + * The Secure payload dispatcher service manages the context(s) corresponding to + * the secure state. It also uses this library to get access to the non-secure + * state cpu context pointers. + * Lastly, this library provides the api to make SP_EL3 point to the cpu context + * which will used for programming an entry into a lower EL. The same context + * will used to save state upon exception entry from that EL. + ******************************************************************************/ +void cm_init() +{ + /* + * The context management library has only global data to intialize, but + * that will be done when the BSS is zeroed out + */ +} + +/******************************************************************************* + * This function returns a pointer to the most recent 'cpu_context' structure + * that was set as the context for the specified security state. NULL is + * returned if no such structure has been specified. + ******************************************************************************/ +void *cm_get_context(uint64_t mpidr, uint32_t security_state) +{ + uint32_t linear_id = platform_get_core_pos(mpidr); + + assert(security_state <= NON_SECURE); + + return cm_context_info[linear_id].ptr[security_state]; +} + +/******************************************************************************* + * This function sets the pointer to the current 'cpu_context' structure for the + * specified security state. + ******************************************************************************/ +void cm_set_context(uint64_t mpidr, void *context, uint32_t security_state) +{ + uint32_t linear_id = platform_get_core_pos(mpidr); + + assert(security_state <= NON_SECURE); + + cm_context_info[linear_id].ptr[security_state] = context; +} + +/******************************************************************************* + * The next four functions are used by runtime services to save and restore EL3 + * and EL1 contexts on the 'cpu_context' structure for the specified security + * state. + ******************************************************************************/ +void cm_el3_sysregs_context_save(uint32_t security_state) +{ + cpu_context *ctx; + + ctx = cm_get_context(read_mpidr(), security_state); + assert(ctx); + + el3_sysregs_context_save(get_el3state_ctx(ctx)); +} + +void cm_el3_sysregs_context_restore(uint32_t security_state) +{ + cpu_context *ctx; + + ctx = cm_get_context(read_mpidr(), security_state); + assert(ctx); + + el3_sysregs_context_restore(get_el3state_ctx(ctx)); +} + +void cm_el1_sysregs_context_save(uint32_t security_state) +{ + cpu_context *ctx; + + ctx = cm_get_context(read_mpidr(), security_state); + assert(ctx); + + el1_sysregs_context_save(get_sysregs_ctx(ctx)); +} + +void cm_el1_sysregs_context_restore(uint32_t security_state) +{ + cpu_context *ctx; + + ctx = cm_get_context(read_mpidr(), security_state); + assert(ctx); + + el1_sysregs_context_restore(get_sysregs_ctx(ctx)); +} + +/******************************************************************************* + * This function is used to program SP_EL3 to point to the 'cpu_context' + * structure which will be used for programming the EL3 architectural state to + * enable an ERET into a lower EL e.g. general purpose registers and system + * registers like SCR_EL3, SPSR_EL3, SCR_EL3 etc. The same structure will be + * used to save the same registers after an exception entry from the lower EL. + ******************************************************************************/ +void cm_set_next_eret_context(uint32_t security_state) +{ + cpu_context *ctx; +#if DEBUG + uint64_t sp_mode; +#endif + ctx = cm_get_context(read_mpidr(), security_state); + assert(ctx); + +#if DEBUG + /* + * Check that this function is called with SP_EL0 as the stack + * pointer + */ + __asm__ volatile("mrs %0, SPSel\n" + : "=r" (sp_mode)); + + assert(sp_mode == MODE_SP_EL0); +#endif + + __asm__ volatile("msr spsel, #1\n" + "mov sp, %0\n" + "msr spsel, #0\n" + : : "r" (ctx)); +} diff --git a/include/aarch64/arch.h b/include/aarch64/arch.h index f40e148..0e2df4f 100644 --- a/include/aarch64/arch.h +++ b/include/aarch64/arch.h @@ -214,7 +214,6 @@ #define GET_RW(mode) ((mode >> MODE_RW_SHIFT) & 0x1) #define GET_EL(mode) ((mode >> MODE_EL_SHIFT) & 0x3) -#define GET_SP(mode) ((mode >> MODE_SP_SHIFT) & 0x1) #define PSR_MODE(rw, el, sp) (rw << MODE_RW_SHIFT | el << MODE_EL_SHIFT \ | sp << MODE_SP_SHIFT) diff --git a/include/context_mgmt.h b/include/context_mgmt.h new file mode 100644 index 0000000..2150a55 --- /dev/null +++ b/include/context_mgmt.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CM_H__ +#define __CM_H__ + +#include + +#ifndef __ASSEMBLY__ +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +extern void cm_init(void); +extern void *cm_get_context(uint64_t mpidr, uint32_t security_state); +extern void cm_set_context(uint64_t mpidr, + void *context, + uint32_t security_state); +extern void cm_el3_sysregs_context_save(uint32_t security_state); +extern void cm_el3_sysregs_context_restore(uint32_t security_state); +extern void cm_el1_sysregs_context_save(uint32_t security_state); +extern void cm_el1_sysregs_context_restore(uint32_t security_state); +extern void cm_set_next_eret_context(uint32_t security_state); +#endif /*__ASSEMBLY__*/ +#endif /* __CM_H__ */