aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAchin Gupta <achin.gupta@arm.com>2014-01-16 12:08:03 +0000
committerDan Handley <dan.handley@arm.com>2014-02-17 18:51:44 +0000
commit9ac63c59c4b6de7e48a6702ad799dc961a4fd6de (patch)
treefcb099ebf7519b5954199ca2feff8b12112b1172
parentb739f22a99c96d5a295f083125505b5b5ec2f8b6 (diff)
downloadarm-trusted-firmware-9ac63c59c4b6de7e48a6702ad799dc961a4fd6de.tar.gz
Add helper library for cpu context management
This patch introduces functions for saving and restoring shared system registers between secure and non-secure EL1 exception levels, VFP registers and essential EL3 system register and other state. It also defines the 'cpu_context' data structure which will used for saving and restoring execution context for a given security state. These functions will allow runtime services like PSCI and Secure payload dispatcher to implement logic for switching between the secure and non-secure states. The save and restore functions follow AArch64 PCS and only use caller-saved temporary registers. Change-Id: I8ee3aaa061d3caaedb28ae2c5becb9a206b6fd74
-rw-r--r--bl31/aarch64/context.S360
-rw-r--r--bl31/bl31.mk3
-rw-r--r--include/context.h236
3 files changed, 598 insertions, 1 deletions
diff --git a/bl31/aarch64/context.S b/bl31/aarch64/context.S
new file mode 100644
index 0000000..5fe8bab
--- /dev/null
+++ b/bl31/aarch64/context.S
@@ -0,0 +1,360 @@
+/*
+ * 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 <context.h>
+
+/* -----------------------------------------------------
+ * The following function strictly follows the AArch64
+ * PCS to use x9-x17 (temporary caller-saved registers)
+ * to save essential EL3 system register context. It
+ * assumes that 'x0' is pointing to a 'el1_sys_regs'
+ * structure where the register context will be saved.
+ * -----------------------------------------------------
+ */
+ .global el3_sysregs_context_save
+el3_sysregs_context_save:
+
+ mrs x9, scr_el3
+ mrs x10, sctlr_el3
+ stp x9, x10, [x0, #CTX_SCR_EL3]
+
+ mrs x11, cptr_el3
+ stp x11, xzr, [x0, #CTX_CPTR_EL3]
+
+ mrs x13, cntfrq_el0
+ mrs x14, mair_el3
+ stp x13, x14, [x0, #CTX_CNTFRQ_EL0]
+
+ mrs x15, tcr_el3
+ mrs x16, ttbr0_el3
+ stp x15, x16, [x0, #CTX_TCR_EL3]
+
+ mrs x17, daif
+ and x17, x17, #(DAIF_ABT_BIT | DAIF_DBG_BIT)
+ stp x17, xzr, [x0, #CTX_DAIF_EL3]
+
+ ret
+
+/* -----------------------------------------------------
+ * The following function strictly follows the AArch64
+ * PCS to use x9-x17 (temporary caller-saved registers)
+ * to restore essential EL3 system register context. It
+ * assumes that 'x0' is pointing to a 'el1_sys_regs'
+ * structure from where the register context will be
+ * restored.
+ *
+ * Note that the sequence differs from that of the save
+ * function as we want the MMU to be enabled last
+ * -----------------------------------------------------
+ */
+ .global el3_sysregs_context_restore
+el3_sysregs_context_restore:
+
+ ldp x11, xzr, [x0, #CTX_CPTR_EL3]
+ msr cptr_el3, x11
+
+ ldp x13, x14, [x0, #CTX_CNTFRQ_EL0]
+ msr cntfrq_el0, x13
+ msr mair_el3, x14
+
+ ldp x15, x16, [x0, #CTX_TCR_EL3]
+ msr tcr_el3, x15
+ msr ttbr0_el3, x16
+
+ ldp x17, xzr, [x0, #CTX_DAIF_EL3]
+ mrs x11, daif
+ orr x17, x17, x11
+ msr daif, x17
+
+ /* Make sure all the above changes are observed */
+ isb
+
+ ldp x9, x10, [x0, #CTX_SCR_EL3]
+ msr scr_el3, x9
+ msr sctlr_el3, x10
+ isb
+
+ ret
+
+/* -----------------------------------------------------
+ * The following function strictly follows the AArch64
+ * PCS to use x9-x17 (temporary caller-saved registers)
+ * to save EL1 system register context. It assumes that
+ * 'x0' is pointing to a 'el1_sys_regs' structure where
+ * the register context will be saved.
+ * -----------------------------------------------------
+ */
+ .global el1_sysregs_context_save
+el1_sysregs_context_save:
+
+ mrs x9, spsr_el1
+ mrs x10, elr_el1
+ stp x9, x10, [x0, #CTX_SPSR_EL1]
+
+ mrs x11, spsr_abt
+ mrs x12, spsr_und
+ stp x11, x12, [x0, #CTX_SPSR_ABT]
+
+ mrs x13, spsr_irq
+ mrs x14, spsr_fiq
+ stp x13, x14, [x0, #CTX_SPSR_IRQ]
+
+ mrs x15, sctlr_el1
+ mrs x16, actlr_el1
+ stp x15, x16, [x0, #CTX_SCTLR_EL1]
+
+ mrs x17, cpacr_el1
+ mrs x9, csselr_el1
+ stp x17, x9, [x0, #CTX_CPACR_EL1]
+
+ mrs x10, sp_el1
+ mrs x11, esr_el1
+ stp x10, x11, [x0, #CTX_SP_EL1]
+
+ mrs x12, ttbr0_el1
+ mrs x13, ttbr1_el1
+ stp x12, x13, [x0, #CTX_TTBR0_EL1]
+
+ mrs x14, mair_el1
+ mrs x15, amair_el1
+ stp x14, x15, [x0, #CTX_MAIR_EL1]
+
+ mrs x16, tcr_el1
+ mrs x17, tpidr_el1
+ stp x16, x17, [x0, #CTX_TCR_EL1]
+
+ mrs x9, tpidr_el0
+ mrs x10, tpidrro_el0
+ stp x9, x10, [x0, #CTX_TPIDR_EL0]
+
+ mrs x11, dacr32_el2
+ mrs x12, ifsr32_el2
+ stp x11, x12, [x0, #CTX_DACR32_EL2]
+
+ mrs x13, par_el1
+ mrs x14, far_el1
+ stp x13, x14, [x0, #CTX_PAR_EL1]
+
+ mrs x15, afsr0_el1
+ mrs x16, afsr1_el1
+ stp x15, x16, [x0, #CTX_AFSR0_EL1]
+
+ mrs x17, contextidr_el1
+ mrs x9, vbar_el1
+ stp x17, x9, [x0, #CTX_CONTEXTIDR_EL1]
+
+ mrs x10, cntp_ctl_el0
+ mrs x11, cntp_cval_el0
+ stp x10, x11, [x0, #CTX_CNTP_CTL_EL0]
+
+ mrs x12, cntv_ctl_el0
+ mrs x13, cntv_cval_el0
+ stp x12, x13, [x0, #CTX_CNTV_CTL_EL0]
+
+ mrs x14, cntkctl_el1
+ mrs x15, fpexc32_el2
+ stp x14, x15, [x0, #CTX_CNTKCTL_EL1]
+
+ ret
+
+/* -----------------------------------------------------
+ * The following function strictly follows the AArch64
+ * PCS to use x9-x17 (temporary caller-saved registers)
+ * to restore EL1 system register context. It assumes
+ * that 'x0' is pointing to a 'el1_sys_regs' structure
+ * from where the register context will be restored
+ * -----------------------------------------------------
+ */
+ .global el1_sysregs_context_restore
+el1_sysregs_context_restore:
+
+ ldp x9, x10, [x0, #CTX_SPSR_EL1]
+ msr spsr_el1, x9
+ msr elr_el1, x10
+
+ ldp x11, x12, [x0, #CTX_SPSR_ABT]
+ msr spsr_abt, x11
+ msr spsr_und, x12
+
+ ldp x13, x14, [x0, #CTX_SPSR_IRQ]
+ msr spsr_irq, x13
+ msr spsr_fiq, x14
+
+ ldp x15, x16, [x0, #CTX_SCTLR_EL1]
+ msr sctlr_el1, x15
+ msr actlr_el1, x16
+
+ ldp x17, x9, [x0, #CTX_CPACR_EL1]
+ msr cpacr_el1, x17
+ msr csselr_el1, x9
+
+ ldp x10, x11, [x0, #CTX_SP_EL1]
+ msr sp_el1, x10
+ msr esr_el1, x11
+
+ ldp x12, x13, [x0, #CTX_TTBR0_EL1]
+ msr ttbr0_el1, x12
+ msr ttbr1_el1, x13
+
+ ldp x14, x15, [x0, #CTX_MAIR_EL1]
+ msr mair_el1, x14
+ msr amair_el1, x15
+
+ ldp x16, x17, [x0, #CTX_TCR_EL1]
+ msr tcr_el1, x16
+ msr tpidr_el1, x17
+
+ ldp x9, x10, [x0, #CTX_TPIDR_EL0]
+ msr tpidr_el0, x9
+ msr tpidrro_el0, x10
+
+ ldp x11, x12, [x0, #CTX_DACR32_EL2]
+ msr dacr32_el2, x11
+ msr ifsr32_el2, x12
+
+ ldp x13, x14, [x0, #CTX_PAR_EL1]
+ msr par_el1, x13
+ msr far_el1, x14
+
+ ldp x15, x16, [x0, #CTX_AFSR0_EL1]
+ msr afsr0_el1, x15
+ msr afsr1_el1, x16
+
+ ldp x17, x9, [x0, #CTX_CONTEXTIDR_EL1]
+ msr contextidr_el1, x17
+ msr vbar_el1, x9
+
+ ldp x10, x11, [x0, #CTX_CNTP_CTL_EL0]
+ msr cntp_ctl_el0, x10
+ msr cntp_cval_el0, x11
+
+ ldp x12, x13, [x0, #CTX_CNTV_CTL_EL0]
+ msr cntv_ctl_el0, x12
+ msr cntv_cval_el0, x13
+
+ ldp x14, x15, [x0, #CTX_CNTKCTL_EL1]
+ msr cntkctl_el1, x14
+ msr fpexc32_el2, x15
+
+ /* No explict ISB required here as ERET covers it */
+
+ ret
+
+/* -----------------------------------------------------
+ * The followsing function follows the aapcs_64 strictly
+ * to use x9-x17 (temporary caller-saved registers
+ * according to AArch64 PCS) to save floating point
+ * register context. It assumes that 'x0' is pointing to
+ * a 'fp_regs' structure where the register context will
+ * be saved.
+ *
+ * Access to VFP registers will trap if CPTR_EL3.TFP is
+ * set. However currently we don't use VFP registers
+ * nor set traps in Trusted Firmware, and assume it's
+ * cleared
+ *
+ * TODO: Revisit when VFP is used in secure world
+ * -----------------------------------------------------
+ */
+ .global fpregs_context_save
+fpregs_context_save:
+ stp q0, q1, [x0, #CTX_FP_Q0]
+ stp q2, q3, [x0, #CTX_FP_Q2]
+ stp q4, q5, [x0, #CTX_FP_Q4]
+ stp q6, q7, [x0, #CTX_FP_Q6]
+ stp q8, q9, [x0, #CTX_FP_Q8]
+ stp q10, q11, [x0, #CTX_FP_Q10]
+ stp q12, q13, [x0, #CTX_FP_Q12]
+ stp q14, q15, [x0, #CTX_FP_Q14]
+ stp q16, q17, [x0, #CTX_FP_Q16]
+ stp q18, q19, [x0, #CTX_FP_Q18]
+ stp q20, q21, [x0, #CTX_FP_Q20]
+ stp q22, q23, [x0, #CTX_FP_Q22]
+ stp q24, q25, [x0, #CTX_FP_Q24]
+ stp q26, q27, [x0, #CTX_FP_Q26]
+ stp q28, q29, [x0, #CTX_FP_Q28]
+ stp q30, q31, [x0, #CTX_FP_Q30]
+
+ mrs x9, fpsr
+ str x9, [x0, #CTX_FP_FPSR]
+
+ mrs x10, fpcr
+ str x10, [x0, #CTX_FP_FPCR]
+
+ ret
+
+/* -----------------------------------------------------
+ * The following function follows the aapcs_64 strictly
+ * to use x9-x17 (temporary caller-saved registers
+ * according to AArch64 PCS) to restore floating point
+ * register context. It assumes that 'x0' is pointing to
+ * a 'fp_regs' structure from where the register context
+ * will be restored.
+ *
+ * Access to VFP registers will trap if CPTR_EL3.TFP is
+ * set. However currently we don't use VFP registers
+ * nor set traps in Trusted Firmware, and assume it's
+ * cleared
+ *
+ * TODO: Revisit when VFP is used in secure world
+ * -----------------------------------------------------
+ */
+ .global fpregs_context_restore
+fpregs_context_restore:
+ ldp q0, q1, [x0, #CTX_FP_Q0]
+ ldp q2, q3, [x0, #CTX_FP_Q2]
+ ldp q4, q5, [x0, #CTX_FP_Q4]
+ ldp q6, q7, [x0, #CTX_FP_Q6]
+ ldp q8, q9, [x0, #CTX_FP_Q8]
+ ldp q10, q11, [x0, #CTX_FP_Q10]
+ ldp q12, q13, [x0, #CTX_FP_Q12]
+ ldp q14, q15, [x0, #CTX_FP_Q14]
+ ldp q16, q17, [x0, #CTX_FP_Q16]
+ ldp q18, q19, [x0, #CTX_FP_Q18]
+ ldp q20, q21, [x0, #CTX_FP_Q20]
+ ldp q22, q23, [x0, #CTX_FP_Q22]
+ ldp q24, q25, [x0, #CTX_FP_Q24]
+ ldp q26, q27, [x0, #CTX_FP_Q26]
+ ldp q28, q29, [x0, #CTX_FP_Q28]
+ ldp q30, q31, [x0, #CTX_FP_Q30]
+
+ ldr x9, [x0, #CTX_FP_FPSR]
+ msr fpsr, x9
+
+ str x10, [x0, #CTX_FP_FPCR]
+ msr fpcr, x10
+
+ /*
+ * No explict ISB required here as ERET to
+ * swtich to secure EL1 or non-secure world
+ * covers it
+ */
+
+ ret
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index f7c2168..9df7128 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -63,7 +63,8 @@ BL31_OBJS += bl31_arch_setup.o \
gic_v3_sysregs.o \
bakery_lock.o \
runtime_svc.o \
- early_exceptions.o
+ early_exceptions.o \
+ context.o
BL31_ENTRY_POINT := bl31_entrypoint
BL31_MAPFILE := bl31.map
diff --git a/include/context.h b/include/context.h
new file mode 100644
index 0000000..615f4f4
--- /dev/null
+++ b/include/context.h
@@ -0,0 +1,236 @@
+/*
+ * 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 __CONTEXT_H__
+#define __CONTEXT_H__
+
+#include <bl_common.h>
+#include <arch.h>
+
+/*******************************************************************************
+ * Constants that allow assembler code to access members of and the 'el3_state'
+ * structure at their correct offsets. Note that some of the registers are only
+ * 32-bits wide but are stored as 64-bit values for convenience
+ ******************************************************************************/
+#define CTX_EL3STATE_OFFSET 0x0
+#define CTX_SAVED_SP_EL3 0x0
+#define CTX_SAVED_SP_EL0 0x8
+#define CTX_SPSR_EL3 0x10
+#define CTX_ELR_EL3 0x18
+#define CTX_SCR_EL3 0x20
+#define CTX_SCTLR_EL3 0x28
+#define CTX_CPTR_EL3 0x30
+/* Unused space to allow registers to be stored as pairs */
+#define CTX_CNTFRQ_EL0 0x40
+#define CTX_MAIR_EL3 0x48
+#define CTX_TCR_EL3 0x50
+#define CTX_TTBR0_EL3 0x58
+#define CTX_DAIF_EL3 0x60
+#define CTX_VBAR_EL3 0x68 /* Currently unused */
+#define CTX_EL3STATE_END 0x70
+
+/*******************************************************************************
+ * Constants that allow assembler code to access members of and the
+ * 'el1_sys_regs' structure at their correct offsets. Note that some of the
+ * registers are only 32-bits wide but are stored as 64-bit values for
+ * convenience
+ ******************************************************************************/
+#define CTX_SYSREGS_OFFSET (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END)
+#define CTX_SPSR_EL1 0x0
+#define CTX_ELR_EL1 0x8
+#define CTX_SPSR_ABT 0x10
+#define CTX_SPSR_UND 0x18
+#define CTX_SPSR_IRQ 0x20
+#define CTX_SPSR_FIQ 0x28
+#define CTX_SCTLR_EL1 0x30
+#define CTX_ACTLR_EL1 0x38
+#define CTX_CPACR_EL1 0x40
+#define CTX_CSSELR_EL1 0x48
+#define CTX_SP_EL1 0x50
+#define CTX_ESR_EL1 0x58
+#define CTX_TTBR0_EL1 0x60
+#define CTX_TTBR1_EL1 0x68
+#define CTX_MAIR_EL1 0x70
+#define CTX_AMAIR_EL1 0x78
+#define CTX_TCR_EL1 0x80
+#define CTX_TPIDR_EL1 0x88
+#define CTX_TPIDR_EL0 0x90
+#define CTX_TPIDRRO_EL0 0x98
+#define CTX_DACR32_EL2 0xa0
+#define CTX_IFSR32_EL2 0xa8
+#define CTX_PAR_EL1 0xb0
+#define CTX_FAR_EL1 0xb8
+#define CTX_AFSR0_EL1 0xc0
+#define CTX_AFSR1_EL1 0xc8
+#define CTX_CONTEXTIDR_EL1 0xd0
+#define CTX_VBAR_EL1 0xd8
+#define CTX_CNTP_CTL_EL0 0xe0
+#define CTX_CNTP_CVAL_EL0 0xe8
+#define CTX_CNTV_CTL_EL0 0xf0
+#define CTX_CNTV_CVAL_EL0 0xf8
+#define CTX_CNTKCTL_EL1 0x100
+#define CTX_FP_FPEXC32_EL2 0x108
+#define CTX_SYSREGS_END 0x110
+
+/*******************************************************************************
+ * Constants that allow assembler code to access members of and the 'fp_regs'
+ * structure at their correct offsets.
+ ******************************************************************************/
+#define CTX_FPREGS_OFFSET (CTX_SYSREGS_OFFSET + CTX_SYSREGS_END)
+#define CTX_FP_Q0 0x0
+#define CTX_FP_Q1 0x10
+#define CTX_FP_Q2 0x20
+#define CTX_FP_Q3 0x30
+#define CTX_FP_Q4 0x40
+#define CTX_FP_Q5 0x50
+#define CTX_FP_Q6 0x60
+#define CTX_FP_Q7 0x70
+#define CTX_FP_Q8 0x80
+#define CTX_FP_Q9 0x90
+#define CTX_FP_Q10 0xa0
+#define CTX_FP_Q11 0xb0
+#define CTX_FP_Q12 0xc0
+#define CTX_FP_Q13 0xd0
+#define CTX_FP_Q14 0xe0
+#define CTX_FP_Q15 0xf0
+#define CTX_FP_Q16 0x100
+#define CTX_FP_Q17 0x110
+#define CTX_FP_Q18 0x120
+#define CTX_FP_Q19 0x130
+#define CTX_FP_Q20 0x140
+#define CTX_FP_Q21 0x150
+#define CTX_FP_Q22 0x160
+#define CTX_FP_Q23 0x170
+#define CTX_FP_Q24 0x180
+#define CTX_FP_Q25 0x190
+#define CTX_FP_Q26 0x1a0
+#define CTX_FP_Q27 0x1b0
+#define CTX_FP_Q28 0x1c0
+#define CTX_FP_Q29 0x1d0
+#define CTX_FP_Q30 0x1e0
+#define CTX_FP_Q31 0x1f0
+#define CTX_FP_FPSR 0x200
+#define CTX_FP_FPCR 0x208
+#define CTX_FPREGS_END 0x210
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Common constants to help define the 'cpu_context' structure and its
+ * members below.
+ */
+#define DWORD_SHIFT 3
+#define DEFINE_REG_STRUCT(name, num_regs) \
+ typedef struct { \
+ uint64_t _regs[num_regs]; \
+ } __aligned(16) name
+
+/* Constants to determine the size of individual context structures */
+#define CTX_SYSREG_ALL (CTX_SYSREGS_END >> DWORD_SHIFT)
+#define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT)
+#define CTX_EL3STATE_ALL (CTX_EL3STATE_END >> DWORD_SHIFT)
+
+/*
+ * AArch64 EL1 system register context structure for preserving the
+ * architectural state during switches from one security state to
+ * another in EL1.
+ */
+DEFINE_REG_STRUCT(el1_sys_regs, CTX_SYSREG_ALL);
+
+/*
+ * AArch64 floating point register context structure for preserving
+ * the floating point state during switches from one security state to
+ * another.
+ */
+DEFINE_REG_STRUCT(fp_regs, CTX_FPREG_ALL);
+
+/*
+ * Miscellaneous registers used by EL3 firmware to maintain its state
+ * across exception entries and exits
+ */
+DEFINE_REG_STRUCT(el3_state, CTX_EL3STATE_ALL);
+
+/*
+ * Macros to access members of any of the above structures using their
+ * offsets
+ */
+#define read_ctx_reg(ctx, offset) ((ctx)->_regs[offset >> DWORD_SHIFT])
+#define write_ctx_reg(ctx, offset, val) (((ctx)->_regs[offset >> DWORD_SHIFT]) \
+ = val)
+
+/*
+ * Top-level context structure which is used by EL3 firmware to
+ * preserve the state of a core at EL1 in one of the two security
+ * states and save enough EL3 meta data to be able to return to that
+ * EL and security state. The context management library will be used
+ * to ensure that SP_EL3 always points to an instance of this
+ * structure at exception entry and exit. Each instance will
+ * correspond to either the secure or the non-secure state.
+ */
+typedef struct {
+ el3_state el3state_ctx;
+ el1_sys_regs sysregs_ctx;
+ fp_regs fpregs_ctx;
+} cpu_context;
+
+/* Macros to access members of the 'cpu_context' structure */
+#define get_el3state_ctx(h) (&((cpu_context *) h)->el3state_ctx)
+#define get_fpregs_ctx(h) (&((cpu_context *) h)->fpregs_ctx)
+#define get_sysregs_ctx(h) (&((cpu_context *) h)->sysregs_ctx)
+
+/*
+ * Compile time assertions related to the 'cpu_context' structure to
+ * ensure that the assembler and the compiler view of the offsets of
+ * the structure members is the same.
+ */
+CASSERT(CTX_SYSREGS_OFFSET == __builtin_offsetof(cpu_context, sysregs_ctx), \
+ assert_core_context_sys_offset_mismatch);
+CASSERT(CTX_FPREGS_OFFSET == __builtin_offsetof(cpu_context, fpregs_ctx), \
+ assert_core_context_fp_offset_mismatch);
+CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context, el3state_ctx), \
+ assert_core_context_el3state_offset_mismatch);
+
+/*******************************************************************************
+ * Function prototypes
+ ******************************************************************************/
+void el3_sysregs_context_save(el3_state *regs);
+void el3_sysregs_context_restore(el3_state *regs);
+void el1_sysregs_context_save(el1_sys_regs *regs);
+void el1_sysregs_context_restore(el1_sys_regs *regs);
+void fpregs_context_save(fp_regs *regs);
+void fpregs_context_restore(fp_regs *regs);
+
+#undef CTX_SYSREG_ALL
+#undef CTX_FP_ALL
+#undef CTX_EL3STATE_ALL
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __CONTEXT_H__ */