Add helper library for cpu context management
authorAchin Gupta <achin.gupta@arm.com>
Thu, 16 Jan 2014 12:08:03 +0000 (12:08 +0000)
committerDan Handley <dan.handley@arm.com>
Mon, 17 Feb 2014 18:51:44 +0000 (18:51 +0000)
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

bl31/aarch64/context.S [new file with mode: 0644]
bl31/bl31.mk
include/context.h [new file with mode: 0644]

diff --git a/bl31/aarch64/context.S b/bl31/aarch64/context.S
new file mode 100644 (file)
index 0000000..5fe8bab
--- /dev/null
@@ -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
index f7c21688ac4aa726614e69aca08614f2f07b3216..9df71280e9675a63a73e575cd7e17ac756047db2 100644 (file)
@@ -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 (file)
index 0000000..615f4f4
--- /dev/null
@@ -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__ */