SPMD: save/restore EL2 system registers.
NOTE: Not all EL-2 system registers are saved/restored.
This subset includes registers recognized by ARMv8.0
Change-Id: I9993c7d78d8f5f8e72d1c6c8d6fd871283aa3ce0
Signed-off-by: Jose Marinho <jose.marinho@arm.com>
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Signed-off-by: Artsem Artsemenka <artsem.artsemenka@arm.com>
Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
diff --git a/Makefile b/Makefile
index 03f9fc6..a84c413 100644
--- a/Makefile
+++ b/Makefile
@@ -412,40 +412,45 @@
################################################################################
ifneq (${SPD},none)
-ifeq (${ARCH},aarch32)
+ ifeq (${ARCH},aarch32)
$(error "Error: SPD is incompatible with AArch32.")
-endif
-ifdef EL3_PAYLOAD_BASE
+ endif
+
+ ifdef EL3_PAYLOAD_BASE
$(warning "SPD and EL3_PAYLOAD_BASE are incompatible build options.")
$(warning "The SPD and its BL32 companion will be present but ignored.")
-endif
- ifeq (${SPD},spmd)
- # SPMD is located in std_svc directory
- SPD_DIR := std_svc
- else
- # All other SPDs in spd directory
- SPD_DIR := spd
- endif
-
- # We expect to locate an spd.mk under the specified SPD directory
- SPD_MAKE := $(wildcard services/${SPD_DIR}/${SPD}/${SPD}.mk)
+ endif
+ ifeq (${SPD},spmd)
+ # SPMD is located in std_svc directory
+ SPD_DIR := std_svc
- ifeq (${SPD_MAKE},)
- $(error Error: No services/${SPD_DIR}/${SPD}/${SPD}.mk located)
+ ifeq ($(CTX_INCLUDE_EL2_REGS),0)
+ $(error spmd requires CTX_INCLUDE_EL2_REGS option)
endif
- $(info Including ${SPD_MAKE})
- include ${SPD_MAKE}
+ else
+ # All other SPDs in spd directory
+ SPD_DIR := spd
+ endif
- # If there's BL32 companion for the chosen SPD, we expect that the SPD's
- # Makefile would set NEED_BL32 to "yes". In this case, the build system
- # supports two mutually exclusive options:
- # * BL32 is built from source: then BL32_SOURCES must contain the list
- # of source files to build BL32
- # * BL32 is a prebuilt binary: then BL32 must point to the image file
- # that will be included in the FIP
- # If both BL32_SOURCES and BL32 are defined, the binary takes precedence
- # over the sources.
+ # We expect to locate an spd.mk under the specified SPD directory
+ SPD_MAKE := $(wildcard services/${SPD_DIR}/${SPD}/${SPD}.mk)
+
+ ifeq (${SPD_MAKE},)
+ $(error Error: No services/${SPD_DIR}/${SPD}/${SPD}.mk located)
+ endif
+ $(info Including ${SPD_MAKE})
+ include ${SPD_MAKE}
+
+ # If there's BL32 companion for the chosen SPD, we expect that the SPD's
+ # Makefile would set NEED_BL32 to "yes". In this case, the build system
+ # supports two mutually exclusive options:
+ # * BL32 is built from source: then BL32_SOURCES must contain the list
+ # of source files to build BL32
+ # * BL32 is a prebuilt binary: then BL32 must point to the image file
+ # that will be included in the FIP
+ # If both BL32_SOURCES and BL32 are defined, the binary takes precedence
+ # over the sources.
endif
################################################################################
@@ -761,6 +766,7 @@
$(eval $(call assert_boolean,CTX_INCLUDE_FPREGS))
$(eval $(call assert_boolean,CTX_INCLUDE_PAUTH_REGS))
$(eval $(call assert_boolean,CTX_INCLUDE_MTE_REGS))
+$(eval $(call assert_boolean,CTX_INCLUDE_EL2_REGS))
$(eval $(call assert_boolean,DEBUG))
$(eval $(call assert_boolean,DYN_DISABLE_AUTH))
$(eval $(call assert_boolean,EL3_EXCEPTION_HANDLING))
@@ -832,6 +838,7 @@
$(eval $(call add_define,CTX_INCLUDE_PAUTH_REGS))
$(eval $(call add_define,EL3_EXCEPTION_HANDLING))
$(eval $(call add_define,CTX_INCLUDE_MTE_REGS))
+$(eval $(call add_define,CTX_INCLUDE_EL2_REGS))
$(eval $(call add_define,ENABLE_AMU))
$(eval $(call add_define,ENABLE_ASSERTIONS))
$(eval $(call add_define,ENABLE_BTI))
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 1faddbe..d593997 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -97,6 +97,33 @@
#define ICC_SGI0R_EL1 S3_0_c12_c11_7
/*******************************************************************************
+ * Definitions for EL2 system registers for save/restore routine
+ ******************************************************************************/
+
+#define CNTPOFF_EL2 S3_4_C14_C0_6
+#define HAFGRTR_EL2 S3_4_C3_C1_6
+#define HDFGRTR_EL2 S3_4_C3_C1_4
+#define HDFGWTR_EL2 S3_4_C3_C1_5
+#define HFGITR_EL2 S3_4_C1_C1_6
+#define HFGRTR_EL2 S3_4_C1_C1_4
+#define HFGWTR_EL2 S3_4_C1_C1_5
+#define ICH_EISR_EL2 S3_4_C12_C11_3
+#define ICH_ELRSR_EL2 S3_4_C12_C11_5
+#define ICH_HCR_EL2 S3_4_C12_C11_0
+#define ICH_MISR_EL2 S3_4_C12_C11_2
+#define ICH_VMCR_EL2 S3_4_C12_C11_7
+#define ICH_VTR_EL2 S3_4_C12_C11_1
+#define MPAMVPM0_EL2 S3_4_C10_C5_0
+#define MPAMVPM1_EL2 S3_4_C10_C5_1
+#define MPAMVPM2_EL2 S3_4_C10_C5_2
+#define MPAMVPM3_EL2 S3_4_C10_C5_3
+#define MPAMVPM4_EL2 S3_4_C10_C5_4
+#define MPAMVPM5_EL2 S3_4_C10_C5_5
+#define MPAMVPM6_EL2 S3_4_C10_C5_6
+#define MPAMVPM7_EL2 S3_4_C10_C5_7
+#define MPAMVPMV_EL2 S3_4_C10_C4_1
+
+/*******************************************************************************
* Generic timer memory mapped registers & offsets
******************************************************************************/
#define CNTCR_OFF U(0x000)
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 4158c02..6559b60 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -136,9 +136,87 @@
#endif /* CTX_INCLUDE_MTE_REGS */
/*
+ * S-EL2 register set
+ */
+
+#if CTX_INCLUDE_EL2_REGS
+/* For later discussion
+ * ICH_AP0R<n>_EL2
+ * ICH_AP1R<n>_EL2
+ * AMEVCNTVOFF0<n>_EL2
+ * AMEVCNTVOFF1<n>_EL2
+ * ICH_LR<n>_EL2
+ */
+#define CTX_ACTLR_EL2 (CTX_MTE_REGS_END + U(0x0))
+#define CTX_AFSR0_EL2 (CTX_MTE_REGS_END + U(0x8))
+#define CTX_AFSR1_EL2 (CTX_MTE_REGS_END + U(0x10))
+#define CTX_AMAIR_EL2 (CTX_MTE_REGS_END + U(0x18))
+#define CTX_CNTHCTL_EL2 (CTX_MTE_REGS_END + U(0x20))
+#define CTX_CNTHP_CTL_EL2 (CTX_MTE_REGS_END + U(0x28))
+#define CTX_CNTHP_CVAL_EL2 (CTX_MTE_REGS_END + U(0x30))
+#define CTX_CNTHP_TVAL_EL2 (CTX_MTE_REGS_END + U(0x38))
+#define CTX_CNTPOFF_EL2 (CTX_MTE_REGS_END + U(0x40))
+#define CTX_CNTVOFF_EL2 (CTX_MTE_REGS_END + U(0x48))
+#define CTX_CPTR_EL2 (CTX_MTE_REGS_END + U(0x50))
+#define CTX_DBGVCR32_EL2 (CTX_MTE_REGS_END + U(0x58))
+#define CTX_ELR_EL2 (CTX_MTE_REGS_END + U(0x60))
+#define CTX_ESR_EL2 (CTX_MTE_REGS_END + U(0x68))
+#define CTX_FAR_EL2 (CTX_MTE_REGS_END + U(0x70))
+#define CTX_FPEXC32_EL2 (CTX_MTE_REGS_END + U(0x78))
+#define CTX_HACR_EL2 (CTX_MTE_REGS_END + U(0x80))
+#define CTX_HAFGRTR_EL2 (CTX_MTE_REGS_END + U(0x88))
+#define CTX_HCR_EL2 (CTX_MTE_REGS_END + U(0x90))
+#define CTX_HDFGRTR_EL2 (CTX_MTE_REGS_END + U(0x98))
+#define CTX_HDFGWTR_EL2 (CTX_MTE_REGS_END + U(0xA0))
+#define CTX_HFGITR_EL2 (CTX_MTE_REGS_END + U(0xA8))
+#define CTX_HFGRTR_EL2 (CTX_MTE_REGS_END + U(0xB0))
+#define CTX_HFGWTR_EL2 (CTX_MTE_REGS_END + U(0xB8))
+#define CTX_HPFAR_EL2 (CTX_MTE_REGS_END + U(0xC0))
+#define CTX_HSTR_EL2 (CTX_MTE_REGS_END + U(0xC8))
+#define CTX_ICC_SRE_EL2 (CTX_MTE_REGS_END + U(0xD0))
+#define CTX_ICH_EISR_EL2 (CTX_MTE_REGS_END + U(0xD8))
+#define CTX_ICH_ELRSR_EL2 (CTX_MTE_REGS_END + U(0xE0))
+#define CTX_ICH_HCR_EL2 (CTX_MTE_REGS_END + U(0xE8))
+#define CTX_ICH_MISR_EL2 (CTX_MTE_REGS_END + U(0xF0))
+#define CTX_ICH_VMCR_EL2 (CTX_MTE_REGS_END + U(0xF8))
+#define CTX_ICH_VTR_EL2 (CTX_MTE_REGS_END + U(0x100))
+#define CTX_MAIR_EL2 (CTX_MTE_REGS_END + U(0x108))
+#define CTX_MDCR_EL2 (CTX_MTE_REGS_END + U(0x110))
+#define CTX_MPAM2_EL2 (CTX_MTE_REGS_END + U(0x118))
+#define CTX_MPAMHCR_EL2 (CTX_MTE_REGS_END + U(0x120))
+#define CTX_MPAMVPM0_EL2 (CTX_MTE_REGS_END + U(0x128))
+#define CTX_MPAMVPM1_EL2 (CTX_MTE_REGS_END + U(0x130))
+#define CTX_MPAMVPM2_EL2 (CTX_MTE_REGS_END + U(0x138))
+#define CTX_MPAMVPM3_EL2 (CTX_MTE_REGS_END + U(0x140))
+#define CTX_MPAMVPM4_EL2 (CTX_MTE_REGS_END + U(0x148))
+#define CTX_MPAMVPM5_EL2 (CTX_MTE_REGS_END + U(0x150))
+#define CTX_MPAMVPM6_EL2 (CTX_MTE_REGS_END + U(0x158))
+#define CTX_MPAMVPM7_EL2 (CTX_MTE_REGS_END + U(0x160))
+#define CTX_MPAMVPMV_EL2 (CTX_MTE_REGS_END + U(0x168))
+#define CTX_RMR_EL2 (CTX_MTE_REGS_END + U(0x170))
+#define CTX_SCTLR_EL2 (CTX_MTE_REGS_END + U(0x178))
+#define CTX_SPSR_EL2 (CTX_MTE_REGS_END + U(0x180))
+#define CTX_SP_EL2 (CTX_MTE_REGS_END + U(0x188))
+#define CTX_TCR_EL2 (CTX_MTE_REGS_END + U(0x190))
+#define CTX_TPIDR_EL2 (CTX_MTE_REGS_END + U(0x198))
+#define CTX_TTBR0_EL2 (CTX_MTE_REGS_END + U(0x1A0))
+#define CTX_VBAR_EL2 (CTX_MTE_REGS_END + U(0x1A8))
+#define CTX_VMPIDR_EL2 (CTX_MTE_REGS_END + U(0x1B0))
+#define CTX_VPIDR_EL2 (CTX_MTE_REGS_END + U(0x1B8))
+#define CTX_VTCR_EL2 (CTX_MTE_REGS_END + U(0x1C0))
+#define CTX_VTTBR_EL2 (CTX_MTE_REGS_END + U(0x1C8))
+#define CTX_ZCR_EL2 (CTX_MTE_REGS_END + U(0x1B0))
+
+/* Align to the next 16 byte boundary */
+#define CTX_EL2_REGS_END (CTX_MTE_REGS_END + U(0x1C0))
+#else
+#define CTX_EL2_REGS_END CTX_MTE_REGS_END
+#endif /* CTX_INCLUDE_EL2_REGS */
+
+/*
* End of system registers.
*/
-#define CTX_SYSREGS_END CTX_MTE_REGS_END
+#define CTX_SYSREGS_END CTX_EL2_REGS_END
/*******************************************************************************
* Constants that allow assembler code to access members of and the 'fp_regs'
@@ -255,11 +333,10 @@
DEFINE_REG_STRUCT(gp_regs, CTX_GPREG_ALL);
/*
- * AArch64 EL1 system register context structure for preserving the
- * architectural state during switches from one security state to
- * another in EL1.
+ * AArch64 EL1/EL2 system register context structure for preserving the
+ * architectural state during world switches.
*/
-DEFINE_REG_STRUCT(el1_sys_regs, CTX_SYSREG_ALL);
+DEFINE_REG_STRUCT(sys_regs, CTX_SYSREG_ALL);
/*
* AArch64 floating point register context structure for preserving
@@ -304,7 +381,7 @@
typedef struct cpu_context {
gp_regs_t gpregs_ctx;
el3_state_t el3state_ctx;
- el1_sys_regs_t sysregs_ctx;
+ sys_regs_t sysregs_ctx;
#if CTX_INCLUDE_FPREGS
fp_regs_t fpregs_ctx;
#endif
@@ -387,8 +464,14 @@
/*******************************************************************************
* Function prototypes
******************************************************************************/
-void el1_sysregs_context_save(el1_sys_regs_t *regs);
-void el1_sysregs_context_restore(el1_sys_regs_t *regs);
+void el1_sysregs_context_save(sys_regs_t *regs);
+void el1_sysregs_context_restore(sys_regs_t *regs);
+
+#if CTX_INCLUDE_EL2_REGS
+void el2_sysregs_context_save(sys_regs_t *regs);
+void el2_sysregs_context_restore(sys_regs_t *regs);
+#endif
+
#if CTX_INCLUDE_FPREGS
void fpregs_context_save(fp_regs_t *regs);
void fpregs_context_restore(fp_regs_t *regs);
diff --git a/include/lib/el3_runtime/context_mgmt.h b/include/lib/el3_runtime/context_mgmt.h
index 17955e3..b36cd3d 100644
--- a/include/lib/el3_runtime/context_mgmt.h
+++ b/include/lib/el3_runtime/context_mgmt.h
@@ -36,6 +36,11 @@
void cm_prepare_el3_exit(uint32_t security_state);
#ifdef __aarch64__
+#if CTX_INCLUDE_EL2_REGS
+void cm_el2_sysregs_context_save(uint32_t security_state);
+void cm_el2_sysregs_context_restore(uint32_t security_state);
+#endif
+
void cm_el1_sysregs_context_save(uint32_t security_state);
void cm_el1_sysregs_context_restore(uint32_t security_state);
void cm_set_elr_el3(uint32_t security_state, uintptr_t entrypoint);
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 9bd25ba..bcc7eef 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,6 +9,11 @@
#include <assert_macros.S>
#include <context.h>
+#if CTX_INCLUDE_EL2_REGS
+ .global el2_sysregs_context_save
+ .global el2_sysregs_context_restore
+#endif
+
.global el1_sysregs_context_save
.global el1_sysregs_context_restore
#if CTX_INCLUDE_FPREGS
@@ -19,6 +24,390 @@
.global restore_gp_pmcr_pauth_regs
.global el3_exit
+#if CTX_INCLUDE_EL2_REGS
+
+/* -----------------------------------------------------
+ * 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.
+ * -----------------------------------------------------
+ */
+func el2_sysregs_context_save
+
+ mrs x9, actlr_el2
+ str x9, [x0, #CTX_ACTLR_EL2]
+
+ mrs x9, afsr0_el2
+ str x9, [x0, #CTX_AFSR0_EL2]
+
+ mrs x9, afsr1_el2
+ str x9, [x0, #CTX_AFSR1_EL2]
+
+ mrs x9, amair_el2
+ str x9, [x0, #CTX_AMAIR_EL2]
+
+ mrs x9, cnthctl_el2
+ str x9, [x0, #CTX_CNTHCTL_EL2]
+
+ mrs x9, cnthp_ctl_el2
+ str x9, [x0, #CTX_CNTHP_CTL_EL2]
+
+ mrs x9, cnthp_cval_el2
+ str x9, [x0, #CTX_CNTHP_CVAL_EL2]
+
+ mrs x9, cnthp_tval_el2
+ str x9, [x0, #CTX_CNTHP_TVAL_EL2]
+
+ mrs x9, CNTPOFF_EL2
+ str x9, [x0, #CTX_CNTPOFF_EL2]
+
+ mrs x9, cntvoff_el2
+ str x9, [x0, #CTX_CNTVOFF_EL2]
+
+ mrs x9, cptr_el2
+ str x9, [x0, #CTX_CPTR_EL2]
+
+ mrs x9, dbgvcr32_el2
+ str x9, [x0, #CTX_DBGVCR32_EL2]
+
+ mrs x9, elr_el2
+ str x9, [x0, #CTX_ELR_EL2]
+
+ mrs x9, esr_el2
+ str x9, [x0, #CTX_ESR_EL2]
+
+ mrs x9, far_el2
+ str x9, [x0, #CTX_FAR_EL2]
+
+ mrs x9, fpexc32_el2
+ str x9, [x0, #CTX_FPEXC32_EL2]
+
+ mrs x9, hacr_el2
+ str x9, [x0, #CTX_HACR_EL2]
+
+ mrs x9, HAFGRTR_EL2
+ str x9, [x0, #CTX_HAFGRTR_EL2]
+
+ mrs x9, hcr_el2
+ str x9, [x0, #CTX_HCR_EL2]
+
+ mrs x9, HDFGRTR_EL2
+ str x9, [x0, #CTX_HDFGRTR_EL2]
+
+ mrs x9, HDFGWTR_EL2
+ str x9, [x0, #CTX_HDFGWTR_EL2]
+
+ mrs x9, HFGITR_EL2
+ str x9, [x0, #CTX_HFGITR_EL2]
+
+ mrs x9, HFGRTR_EL2
+ str x9, [x0, #CTX_HFGRTR_EL2]
+
+ mrs x9, HFGWTR_EL2
+ str x9, [x0, #CTX_HFGWTR_EL2]
+
+ mrs x9, hpfar_el2
+ str x9, [x0, #CTX_HPFAR_EL2]
+
+ mrs x9, hstr_el2
+ str x9, [x0, #CTX_HSTR_EL2]
+
+ mrs x9, ICC_SRE_EL2
+ str x9, [x0, #CTX_ICC_SRE_EL2]
+
+ mrs x9, ICH_EISR_EL2
+ str x9, [x0, #CTX_ICH_EISR_EL2]
+
+ mrs x9, ICH_ELRSR_EL2
+ str x9, [x0, #CTX_ICH_ELRSR_EL2]
+
+ mrs x9, ICH_HCR_EL2
+ str x9, [x0, #CTX_ICH_HCR_EL2]
+
+ mrs x9, ICH_MISR_EL2
+ str x9, [x0, #CTX_ICH_MISR_EL2]
+
+ mrs x9, ICH_VMCR_EL2
+ str x9, [x0, #CTX_ICH_VMCR_EL2]
+
+ mrs x9, ICH_VTR_EL2
+ str x9, [x0, #CTX_ICH_VTR_EL2]
+
+ mrs x9, mair_el2
+ str x9, [x0, #CTX_MAIR_EL2]
+
+ mrs x9, mdcr_el2
+ str x9, [x0, #CTX_MDCR_EL2]
+
+ mrs x9, MPAM2_EL2
+ str x9, [x0, #CTX_MPAM2_EL2]
+
+ mrs x9, MPAMHCR_EL2
+ str x9, [x0, #CTX_MPAMHCR_EL2]
+
+ mrs x9, MPAMVPM0_EL2
+ str x9, [x0, #CTX_MPAMVPM0_EL2]
+
+ mrs x9, MPAMVPM1_EL2
+ str x9, [x0, #CTX_MPAMVPM1_EL2]
+
+ mrs x9, MPAMVPM2_EL2
+ str x9, [x0, #CTX_MPAMVPM2_EL2]
+
+ mrs x9, MPAMVPM3_EL2
+ str x9, [x0, #CTX_MPAMVPM3_EL2]
+
+ mrs x9, MPAMVPM4_EL2
+ str x9, [x0, #CTX_MPAMVPM4_EL2]
+
+ mrs x9, MPAMVPM5_EL2
+ str x9, [x0, #CTX_MPAMVPM5_EL2]
+
+ mrs x9, MPAMVPM6_EL2
+ str x9, [x0, #CTX_MPAMVPM6_EL2]
+
+ mrs x9, MPAMVPM7_EL2
+ str x9, [x0, #CTX_MPAMVPM7_EL2]
+
+ mrs x9, MPAMVPMV_EL2
+ str x9, [x0, #CTX_MPAMVPMV_EL2]
+
+ mrs x9, rmr_el2
+ str x9, [x0, #CTX_RMR_EL2]
+
+ mrs x9, sctlr_el2
+ str x9, [x0, #CTX_SCTLR_EL2]
+
+ mrs x9, spsr_el2
+ str x9, [x0, #CTX_SPSR_EL2]
+
+ mrs x9, sp_el2
+ str x9, [x0, #CTX_SP_EL2]
+
+ mrs x9, tcr_el2
+ str x9, [x0, #CTX_TCR_EL2]
+
+ mrs x9, tpidr_el2
+ str x9, [x0, #CTX_TPIDR_EL2]
+
+ mrs x9, ttbr0_el2
+ str x9, [x0, #CTX_TTBR0_EL2]
+
+ mrs x9, vbar_el2
+ str x9, [x0, #CTX_VBAR_EL2]
+
+ mrs x9, vmpidr_el2
+ str x9, [x0, #CTX_VMPIDR_EL2]
+
+ mrs x9, vpidr_el2
+ str x9, [x0, #CTX_VPIDR_EL2]
+
+ mrs x9, vtcr_el2
+ str x9, [x0, #CTX_VTCR_EL2]
+
+ mrs x9, vttbr_el2
+ str x9, [x0, #CTX_VTTBR_EL2]
+
+ mrs x9, ZCR_EL2
+ str x9, [x0, #CTX_ZCR_EL2]
+
+ ret
+endfunc el2_sysregs_context_save
+
+/* -----------------------------------------------------
+ * 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
+ * -----------------------------------------------------
+ */
+func el2_sysregs_context_restore
+
+ ldr x9, [x0, #CTX_ACTLR_EL2]
+ msr actlr_el2, x9
+
+ ldr x9, [x0, #CTX_AFSR0_EL2]
+ msr afsr0_el2, x9
+
+ ldr x9, [x0, #CTX_AFSR1_EL2]
+ msr afsr1_el2, x9
+
+ ldr x9, [x0, #CTX_AMAIR_EL2]
+ msr amair_el2, x9
+
+ ldr x9, [x0, #CTX_CNTHCTL_EL2]
+ msr cnthctl_el2, x9
+
+ ldr x9, [x0, #CTX_CNTHP_CTL_EL2]
+ msr cnthp_ctl_el2, x9
+
+ ldr x9, [x0, #CTX_CNTHP_CVAL_EL2]
+ msr cnthp_cval_el2, x9
+
+ ldr x9, [x0, #CTX_CNTHP_TVAL_EL2]
+ msr cnthp_tval_el2, x9
+
+ ldr x9, [x0, #CTX_CNTPOFF_EL2]
+ msr CNTPOFF_EL2, x9
+
+ ldr x9, [x0, #CTX_CNTVOFF_EL2]
+ msr cntvoff_el2, x9
+
+ ldr x9, [x0, #CTX_CPTR_EL2]
+ msr cptr_el2, x9
+
+ ldr x9, [x0, #CTX_DBGVCR32_EL2]
+ msr dbgvcr32_el2, x9
+
+ ldr x9, [x0, #CTX_ELR_EL2]
+ msr elr_el2, x9
+
+ ldr x9, [x0, #CTX_ESR_EL2]
+ msr esr_el2, x9
+
+ ldr x9, [x0, #CTX_FAR_EL2]
+ msr far_el2, x9
+
+ ldr x9, [x0, #CTX_FPEXC32_EL2]
+ msr fpexc32_el2, x9
+
+ ldr x9, [x0, #CTX_HACR_EL2]
+ msr hacr_el2, x9
+
+ ldr x9, [x0, #CTX_HAFGRTR_EL2]
+ msr HAFGRTR_EL2, x9
+
+ ldr x9, [x0, #CTX_HCR_EL2]
+ msr hcr_el2, x9
+
+ ldr x9, [x0, #CTX_HDFGRTR_EL2]
+ msr HDFGRTR_EL2, x9
+
+ ldr x9, [x0, #CTX_HDFGWTR_EL2]
+ msr HDFGWTR_EL2, x9
+
+ ldr x9, [x0, #CTX_HFGITR_EL2]
+ msr HFGITR_EL2, x9
+
+ ldr x9, [x0, #CTX_HFGRTR_EL2]
+ msr HFGRTR_EL2, x9
+
+ ldr x9, [x0, #CTX_HFGWTR_EL2]
+ msr HFGWTR_EL2, x9
+
+ ldr x9, [x0, #CTX_HPFAR_EL2]
+ msr hpfar_el2, x9
+
+ ldr x9, [x0, #CTX_HSTR_EL2]
+ msr hstr_el2, x9
+
+ ldr x9, [x0, #CTX_ICC_SRE_EL2]
+ msr ICC_SRE_EL2, x9
+
+ ldr x9, [x0, #CTX_ICH_EISR_EL2]
+ msr ICH_EISR_EL2, x9
+
+ ldr x9, [x0, #CTX_ICH_ELRSR_EL2]
+ msr ICH_ELRSR_EL2, x9
+
+ ldr x9, [x0, #CTX_ICH_HCR_EL2]
+ msr ICH_HCR_EL2, x9
+
+ ldr x9, [x0, #CTX_ICH_MISR_EL2]
+ msr ICH_MISR_EL2, x9
+
+ ldr x9, [x0, #CTX_ICH_VMCR_EL2]
+ msr ICH_VMCR_EL2, x9
+
+ ldr x9, [x0, #CTX_ICH_VTR_EL2]
+ msr ICH_VTR_EL2, x9
+
+ ldr x9, [x0, #CTX_MAIR_EL2]
+ msr mair_el2, x9
+
+ ldr x9, [x0, #CTX_MDCR_EL2]
+ msr mdcr_el2, x9
+
+ ldr x9, [x0, #CTX_MPAM2_EL2]
+ msr MPAM2_EL2, x9
+
+ ldr x9, [x0, #CTX_MPAMHCR_EL2]
+ msr MPAMHCR_EL2, x9
+
+ ldr x9, [x0, #CTX_MPAMVPM0_EL2]
+ msr MPAMVPM0_EL2, x9
+
+ ldr x9, [x0, #CTX_MPAMVPM1_EL2]
+ msr MPAMVPM1_EL2, x9
+
+ ldr x9, [x0, #CTX_MPAMVPM2_EL2]
+ msr MPAMVPM2_EL2, x9
+
+ ldr x9, [x0, #CTX_MPAMVPM3_EL2]
+ msr MPAMVPM3_EL2, x9
+
+ ldr x9, [x0, #CTX_MPAMVPM4_EL2]
+ msr MPAMVPM4_EL2, x9
+
+ ldr x9, [x0, #CTX_MPAMVPM5_EL2]
+ msr MPAMVPM5_EL2, x9
+
+ ldr x9, [x0, #CTX_MPAMVPM6_EL2]
+ msr MPAMVPM6_EL2, x9
+
+ ldr x9, [x0, #CTX_MPAMVPM7_EL2]
+ msr MPAMVPM7_EL2, x9
+
+ ldr x9, [x0, #CTX_MPAMVPMV_EL2]
+ msr MPAMVPMV_EL2, x9
+
+ ldr x9, [x0, #CTX_RMR_EL2]
+ msr rmr_el2, x9
+
+ ldr x9, [x0, #CTX_SCTLR_EL2]
+ msr sctlr_el2, x9
+
+ ldr x9, [x0, #CTX_SPSR_EL2]
+ msr spsr_el2, x9
+
+ ldr x9, [x0, #CTX_SP_EL2]
+ msr sp_el2, x9
+
+ ldr x9, [x0, #CTX_TCR_EL2]
+ msr tcr_el2, x9
+
+ ldr x9, [x0, #CTX_TPIDR_EL2]
+ msr tpidr_el2, x9
+
+ ldr x9, [x0, #CTX_TTBR0_EL2]
+ msr ttbr0_el2, x9
+
+ ldr x9, [x0, #CTX_VBAR_EL2]
+ msr vbar_el2, x9
+
+ ldr x9, [x0, #CTX_VMPIDR_EL2]
+ msr vmpidr_el2, x9
+
+ ldr x9, [x0, #CTX_VPIDR_EL2]
+ msr vpidr_el2, x9
+
+ ldr x9, [x0, #CTX_VTCR_EL2]
+ msr vtcr_el2, x9
+
+ ldr x9, [x0, #CTX_VTTBR_EL2]
+ msr vttbr_el2, x9
+
+ ldr x9, [x0, #CTX_ZCR_EL2]
+ msr ZCR_EL2, x9
+
+ ret
+endfunc el2_sysregs_context_restore
+
+#endif /* CTX_INCLUDE_EL2_REGS */
+
/* ------------------------------------------------------------------
* The following function strictly follows the AArch64 PCS to use
* x9-x17 (temporary caller-saved registers) to save EL1 system
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 546e39e..f59bcfc 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -530,6 +530,52 @@
cm_set_next_eret_context(security_state);
}
+#if CTX_INCLUDE_EL2_REGS
+/*******************************************************************************
+ * Save EL2 sysreg context
+ ******************************************************************************/
+void cm_el2_sysregs_context_save(uint32_t security_state)
+{
+ u_register_t scr_el3 = read_scr();
+
+ /*
+ * Always save the non-secure EL2 context, only save the
+ * S-EL2 context if S-EL2 is enabled.
+ */
+ if ((security_state == NON_SECURE) ||
+ ((scr_el3 & SCR_EEL2_BIT) != 0U)) {
+ cpu_context_t *ctx;
+
+ ctx = cm_get_context(security_state);
+ assert(ctx != NULL);
+
+ el2_sysregs_context_save(get_sysregs_ctx(ctx));
+ }
+}
+
+/*******************************************************************************
+ * Restore EL2 sysreg context
+ ******************************************************************************/
+void cm_el2_sysregs_context_restore(uint32_t security_state)
+{
+ u_register_t scr_el3 = read_scr();
+
+ /*
+ * Always restore the non-secure EL2 context, only restore the
+ * S-EL2 context if S-EL2 is enabled.
+ */
+ if ((security_state == NON_SECURE) ||
+ ((scr_el3 & SCR_EEL2_BIT) != 0U)) {
+ cpu_context_t *ctx;
+
+ ctx = cm_get_context(security_state);
+ assert(ctx != NULL);
+
+ el2_sysregs_context_restore(get_sysregs_ctx(ctx));
+ }
+}
+#endif /* CTX_INCLUDE_EL2_REGS */
+
/*******************************************************************************
* The next four functions are used by runtime services to save and restore
* EL1 context on the 'cpu_context' structure for the specified security
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 60958a1..8e1f273 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -262,3 +262,8 @@
# Enable Link Time Optimization
ENABLE_LTO := 0
+
+# Build flag to include EL2 registers in cpu context save and restore during
+# S-EL2 firmware entry/exit. This flag is to be used with SPD=spmd option.
+# Default is 0.
+CTX_INCLUDE_EL2_REGS := 0
diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c
index 677f639..1107190 100644
--- a/services/std_svc/spmd/spmd_main.c
+++ b/services/std_svc/spmd/spmd_main.c
@@ -49,6 +49,7 @@
/* Restore the context assigned above */
cm_el1_sysregs_context_restore(SECURE);
+ cm_el2_sysregs_context_restore(SECURE);
cm_set_next_eret_context(SECURE);
/* Invalidate TLBs at EL1. */
@@ -60,6 +61,7 @@
/* Save secure state */
cm_el1_sysregs_context_save(SECURE);
+ cm_el2_sysregs_context_save(SECURE);
return rc;
}
@@ -321,9 +323,11 @@
/* Save incoming security state */
cm_el1_sysregs_context_save(in_sstate);
+ cm_el2_sysregs_context_save(in_sstate);
/* Restore outgoing security state */
cm_el1_sysregs_context_restore(out_sstate);
+ cm_el2_sysregs_context_restore(out_sstate);
cm_set_next_eret_context(out_sstate);
SMC_RET8(cm_get_context(out_sstate), smc_fid, x1, x2, x3, x4,
@@ -366,9 +370,11 @@
if (in_sstate == NON_SECURE) {
/* Save incoming security state */
cm_el1_sysregs_context_save(in_sstate);
+ cm_el2_sysregs_context_save(in_sstate);
/* Restore outgoing security state */
cm_el1_sysregs_context_restore(out_sstate);
+ cm_el2_sysregs_context_restore(out_sstate);
cm_set_next_eret_context(out_sstate);
SMC_RET8(cm_get_context(out_sstate), smc_fid,
@@ -432,9 +438,11 @@
/* Save incoming security state */
cm_el1_sysregs_context_save(in_sstate);
+ cm_el2_sysregs_context_save(in_sstate);
/* Restore outgoing security state */
cm_el1_sysregs_context_restore(out_sstate);
+ cm_el2_sysregs_context_restore(out_sstate);
cm_set_next_eret_context(out_sstate);
SMC_RET8(cm_get_context(out_sstate), smc_fid, x1, x2, x3, x4,
@@ -466,9 +474,11 @@
/* Save incoming security state */
cm_el1_sysregs_context_save(in_sstate);
+ cm_el2_sysregs_context_save(in_sstate);
/* Restore outgoing security state */
cm_el1_sysregs_context_restore(out_sstate);
+ cm_el2_sysregs_context_restore(out_sstate);
cm_set_next_eret_context(out_sstate);
SMC_RET8(cm_get_context(out_sstate), smc_fid, x1, x2, x3, x4,