aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAchin Gupta <achin.gupta@arm.com>2014-02-01 07:51:28 +0000
committerDan Handley <dan.handley@arm.com>2014-02-17 18:51:44 +0000
commit7aea908761a6a2923940b8c9491cc1e749142ad1 (patch)
treea9becb56474891281bd5abdf70a85b6520908b20
parent9ac63c59c4b6de7e48a6702ad799dc961a4fd6de (diff)
Add context management library
This patch adds support for a cpu context management library. This library will be used to: 1. Share pointers to secure and non-secure state cpu contexts between runtime services e.g. PSCI and Secure Payload Dispatcher services 2. Set SP_EL3 to a context structure which will be used for programming an ERET into a lower EL 3. Provide wrapper functions to save and restore EL3 & EL1 state. These functions will in turn use the helper functions in context.S Change-Id: I655eeef83dcd2a0c6f2eb2ac23efab866ac83ca0
-rw-r--r--bl31/bl31.mk1
-rw-r--r--bl31/bl31_main.c12
-rw-r--r--bl31/context_mgmt.c176
-rw-r--r--include/aarch64/arch.h1
-rw-r--r--include/context_mgmt.h51
5 files changed, 239 insertions, 2 deletions
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 @@ BL31_OBJS += bl31_arch_setup.o \
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 <bl_common.h>
#include <bl31.h>
#include <runtime_svc.h>
+#include <context_mgmt.h>
+
+/*******************************************************************************
+ * 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 @@ void bl31_main(void)
#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 <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <arch_helpers.h>
+#include <platform.h>
+#include <bl_common.h>
+#include <runtime_svc.h>
+#include <context_mgmt.h>
+
+/*******************************************************************************
+ * 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 <context.h>
+
+#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__ */