Browse Source
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: I8ee3aaa061d3caaedb28ae2c5becb9a206b6fd74pull/16/merge
Achin Gupta
11 years ago
committed by
Dan Handley
3 changed files with 598 additions and 1 deletions
@ -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 |
@ -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__ */ |
Loading…
Reference in new issue