refactor(context-mgmt): move EL1 save/restore routines into C
Similar to the refactoring process followed for EL2 system registers,
moving the save and restore routines of EL1 system registers into C
file, thereby reducing assembly code.
Change-Id: Ib59fbbe2eef2aa815effe854cf962fc4ac62a2ae
Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index 6fdc7e8..2d97018 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -464,6 +464,9 @@
DEFINE_SYSREG_RW_FUNCS(cntp_cval_el0)
DEFINE_SYSREG_READ_FUNC(cntpct_el0)
DEFINE_SYSREG_RW_FUNCS(cnthctl_el2)
+DEFINE_SYSREG_RW_FUNCS(cntv_ctl_el0)
+DEFINE_SYSREG_RW_FUNCS(cntv_cval_el0)
+DEFINE_SYSREG_RW_FUNCS(cntkctl_el1)
DEFINE_SYSREG_RW_FUNCS(vtcr_el2)
@@ -480,6 +483,9 @@
#define clr_cntp_ctl_enable(x) ((x) &= ~(U(1) << CNTP_CTL_ENABLE_SHIFT))
#define clr_cntp_ctl_imask(x) ((x) &= ~(U(1) << CNTP_CTL_IMASK_SHIFT))
+DEFINE_SYSREG_RW_FUNCS(tpidr_el0)
+DEFINE_SYSREG_RW_FUNCS(tpidr_el1)
+DEFINE_SYSREG_RW_FUNCS(tpidr_el2)
DEFINE_SYSREG_RW_FUNCS(tpidr_el3)
DEFINE_SYSREG_RW_FUNCS(cntvoff_el2)
@@ -489,7 +495,7 @@
DEFINE_SYSREG_RW_FUNCS(hacr_el2)
DEFINE_SYSREG_RW_FUNCS(hpfar_el2)
-DEFINE_SYSREG_RW_FUNCS(tpidr_el2)
+
DEFINE_SYSREG_RW_FUNCS(dbgvcr32_el2)
DEFINE_RENAME_SYSREG_RW_FUNCS(ich_hcr_el2, ICH_HCR_EL2)
DEFINE_RENAME_SYSREG_RW_FUNCS(ich_vmcr_el2, ICH_VMCR_EL2)
@@ -501,6 +507,16 @@
DEFINE_SYSREG_RW_FUNCS(hstr_el2)
DEFINE_SYSREG_RW_FUNCS(pmcr_el0)
+DEFINE_SYSREG_RW_FUNCS(csselr_el1)
+DEFINE_SYSREG_RW_FUNCS(tpidrro_el0)
+DEFINE_SYSREG_RW_FUNCS(contextidr_el1)
+DEFINE_SYSREG_RW_FUNCS(spsr_abt)
+DEFINE_SYSREG_RW_FUNCS(spsr_und)
+DEFINE_SYSREG_RW_FUNCS(spsr_irq)
+DEFINE_SYSREG_RW_FUNCS(spsr_fiq)
+DEFINE_SYSREG_RW_FUNCS(dacr32_el2)
+DEFINE_SYSREG_RW_FUNCS(ifsr32_el2)
+
/* GICv3 System Registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1)
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index 910026e..d5bd890 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -574,9 +574,6 @@
/*******************************************************************************
* Function prototypes
******************************************************************************/
-void el1_sysregs_context_save(el1_sysregs_t *regs);
-void el1_sysregs_context_restore(el1_sysregs_t *regs);
-
#if CTX_INCLUDE_FPREGS
void fpregs_context_save(fp_regs_t *regs);
void fpregs_context_restore(fp_regs_t *regs);
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 176308e..76aebf9 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -10,8 +10,6 @@
#include <context.h>
#include <el3_common_macros.S>
- .global el1_sysregs_context_save
- .global el1_sysregs_context_restore
#if CTX_INCLUDE_FPREGS
.global fpregs_context_save
.global fpregs_context_restore
@@ -21,220 +19,6 @@
.global save_and_update_ptw_el1_sys_regs
.global el3_exit
-
-/* ------------------------------------------------------------------
- * 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 el1_sysregs_context_save
-
- mrs x9, spsr_el1
- mrs x10, elr_el1
- stp x9, x10, [x0, #CTX_SPSR_EL1]
-
-#if !ERRATA_SPECULATIVE_AT
- mrs x15, sctlr_el1
- mrs x16, tcr_el1
- stp x15, x16, [x0, #CTX_SCTLR_EL1]
-#endif /* ERRATA_SPECULATIVE_AT */
-
- 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, actlr_el1
- mrs x17, tpidr_el1
- stp x16, x17, [x0, #CTX_ACTLR_EL1]
-
- mrs x9, tpidr_el0
- mrs x10, tpidrro_el0
- stp x9, x10, [x0, #CTX_TPIDR_EL0]
-
- 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]
-
- /* Save AArch32 system registers if the build has instructed so */
-#if CTX_INCLUDE_AARCH32_REGS
- 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, dacr32_el2
- mrs x16, ifsr32_el2
- stp x15, x16, [x0, #CTX_DACR32_EL2]
-#endif /* CTX_INCLUDE_AARCH32_REGS */
-
- /* Save NS timer registers if the build has instructed so */
-#if NS_TIMER_SWITCH
- 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
- str x14, [x0, #CTX_CNTKCTL_EL1]
-#endif /* NS_TIMER_SWITCH */
-
- /* Save MTE system registers if the build has instructed so */
-#if ENABLE_FEAT_MTE
-#if ENABLE_FEAT_MTE == 2
- mrs x8, id_aa64pfr1_el1
- and x8, x8, #(ID_AA64PFR1_EL1_MTE_MASK << ID_AA64PFR1_EL1_MTE_SHIFT)
- cbz x8, no_mte_save
-#endif
- mrs x15, TFSRE0_EL1
- mrs x16, TFSR_EL1
- stp x15, x16, [x0, #CTX_TFSRE0_EL1]
-
- mrs x9, RGSR_EL1
- mrs x10, GCR_EL1
- stp x9, x10, [x0, #CTX_RGSR_EL1]
-
-no_mte_save:
-#endif /* ENABLE_FEAT_MTE */
-
- ret
-endfunc el1_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 el1_sysregs_context_restore
-
- ldp x9, x10, [x0, #CTX_SPSR_EL1]
- msr spsr_el1, x9
- msr elr_el1, x10
-
-#if !ERRATA_SPECULATIVE_AT
- ldp x15, x16, [x0, #CTX_SCTLR_EL1]
- msr sctlr_el1, x15
- msr tcr_el1, x16
-#endif /* ERRATA_SPECULATIVE_AT */
-
- 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_ACTLR_EL1]
- msr actlr_el1, x16
- msr tpidr_el1, x17
-
- ldp x9, x10, [x0, #CTX_TPIDR_EL0]
- msr tpidr_el0, x9
- msr tpidrro_el0, x10
-
- 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
-
- /* Restore AArch32 system registers if the build has instructed so */
-#if CTX_INCLUDE_AARCH32_REGS
- 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_DACR32_EL2]
- msr dacr32_el2, x15
- msr ifsr32_el2, x16
-#endif /* CTX_INCLUDE_AARCH32_REGS */
-
- /* Restore NS timer registers if the build has instructed so */
-#if NS_TIMER_SWITCH
- 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
-
- ldr x14, [x0, #CTX_CNTKCTL_EL1]
- msr cntkctl_el1, x14
-#endif /* NS_TIMER_SWITCH */
-
- /* Restore MTE system registers if the build has instructed so */
-#if ENABLE_FEAT_MTE
-#if ENABLE_FEAT_MTE == 2
- mrs x8, id_aa64pfr1_el1
- and x8, x8, #(ID_AA64PFR1_EL1_MTE_MASK << ID_AA64PFR1_EL1_MTE_SHIFT)
- cbz x8, no_mte_restore
-#endif
-
- ldp x11, x12, [x0, #CTX_TFSRE0_EL1]
- msr TFSRE0_EL1, x11
- msr TFSR_EL1, x12
-
- ldp x13, x14, [x0, #CTX_RGSR_EL1]
- msr RGSR_EL1, x13
- msr GCR_EL1, x14
-
-no_mte_restore:
-#endif /* ENABLE_FEAT_MTE */
-
- /* No explict ISB required here as ERET covers it */
- ret
-endfunc el1_sysregs_context_restore
-
/* ------------------------------------------------------------------
* The following function follows the aapcs_64 strictly to use
* x9-x17 (temporary caller-saved registers according to AArch64 PCS)
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index c3b7e78..52e917e 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -1429,6 +1429,116 @@
#endif /* CTX_INCLUDE_EL2_REGS */
}
+static void el1_sysregs_context_save(el1_sysregs_t *ctx)
+{
+ write_ctx_reg(ctx, CTX_SPSR_EL1, read_spsr_el1());
+ write_ctx_reg(ctx, CTX_ELR_EL1, read_elr_el1());
+
+#if !ERRATA_SPECULATIVE_AT
+ write_ctx_reg(ctx, CTX_SCTLR_EL1, read_sctlr_el1());
+ write_ctx_reg(ctx, CTX_TCR_EL1, read_tcr_el1());
+#endif /* (!ERRATA_SPECULATIVE_AT) */
+
+ write_ctx_reg(ctx, CTX_CPACR_EL1, read_cpacr_el1());
+ write_ctx_reg(ctx, CTX_CSSELR_EL1, read_csselr_el1());
+ write_ctx_reg(ctx, CTX_SP_EL1, read_sp_el1());
+ write_ctx_reg(ctx, CTX_ESR_EL1, read_esr_el1());
+ write_ctx_reg(ctx, CTX_TTBR0_EL1, read_ttbr0_el1());
+ write_ctx_reg(ctx, CTX_TTBR1_EL1, read_ttbr1_el1());
+ write_ctx_reg(ctx, CTX_MAIR_EL1, read_mair_el1());
+ write_ctx_reg(ctx, CTX_AMAIR_EL1, read_amair_el1());
+ write_ctx_reg(ctx, CTX_ACTLR_EL1, read_actlr_el1());
+ write_ctx_reg(ctx, CTX_TPIDR_EL1, read_tpidr_el1());
+ write_ctx_reg(ctx, CTX_TPIDR_EL0, read_tpidr_el0());
+ write_ctx_reg(ctx, CTX_TPIDRRO_EL0, read_tpidrro_el0());
+ write_ctx_reg(ctx, CTX_PAR_EL1, read_par_el1());
+ write_ctx_reg(ctx, CTX_FAR_EL1, read_far_el1());
+ write_ctx_reg(ctx, CTX_AFSR0_EL1, read_afsr0_el1());
+ write_ctx_reg(ctx, CTX_AFSR1_EL1, read_afsr1_el1());
+ write_ctx_reg(ctx, CTX_CONTEXTIDR_EL1, read_contextidr_el1());
+ write_ctx_reg(ctx, CTX_VBAR_EL1, read_vbar_el1());
+
+#if CTX_INCLUDE_AARCH32_REGS
+ write_ctx_reg(ctx, CTX_SPSR_ABT, read_spsr_abt());
+ write_ctx_reg(ctx, CTX_SPSR_UND, read_spsr_und());
+ write_ctx_reg(ctx, CTX_SPSR_IRQ, read_spsr_irq());
+ write_ctx_reg(ctx, CTX_SPSR_FIQ, read_spsr_fiq());
+ write_ctx_reg(ctx, CTX_DACR32_EL2, read_dacr32_el2());
+ write_ctx_reg(ctx, CTX_IFSR32_EL2, read_ifsr32_el2());
+#endif /* CTX_INCLUDE_AARCH32_REGS */
+
+#if NS_TIMER_SWITCH
+ write_ctx_reg(ctx, CTX_CNTP_CTL_EL0, read_cntp_ctl_el0());
+ write_ctx_reg(ctx, CTX_CNTP_CVAL_EL0, read_cntp_cval_el0());
+ write_ctx_reg(ctx, CTX_CNTV_CTL_EL0, read_cntv_ctl_el0());
+ write_ctx_reg(ctx, CTX_CNTV_CVAL_EL0, read_cntv_cval_el0());
+ write_ctx_reg(ctx, CTX_CNTKCTL_EL1, read_cntkctl_el1());
+#endif /* NS_TIMER_SWITCH */
+
+#if ENABLE_FEAT_MTE
+ write_ctx_reg(ctx, CTX_TFSRE0_EL1, read_tfsre0_el1());
+ write_ctx_reg(ctx, CTX_TFSR_EL1, read_tfsr_el1());
+ write_ctx_reg(ctx, CTX_RGSR_EL1, read_rgsr_el1());
+ write_ctx_reg(ctx, CTX_GCR_EL1, read_gcr_el1());
+#endif /* ENABLE_FEAT_MTE */
+
+}
+
+static void el1_sysregs_context_restore(el1_sysregs_t *ctx)
+{
+ write_spsr_el1(read_ctx_reg(ctx, CTX_SPSR_EL1));
+ write_elr_el1(read_ctx_reg(ctx, CTX_ELR_EL1));
+
+#if !ERRATA_SPECULATIVE_AT
+ write_sctlr_el1(read_ctx_reg(ctx, CTX_SCTLR_EL1));
+ write_tcr_el1(read_ctx_reg(ctx, CTX_TCR_EL1));
+#endif /* (!ERRATA_SPECULATIVE_AT) */
+
+ write_cpacr_el1(read_ctx_reg(ctx, CTX_CPACR_EL1));
+ write_csselr_el1(read_ctx_reg(ctx, CTX_CSSELR_EL1));
+ write_sp_el1(read_ctx_reg(ctx, CTX_SP_EL1));
+ write_esr_el1(read_ctx_reg(ctx, CTX_ESR_EL1));
+ write_ttbr0_el1(read_ctx_reg(ctx, CTX_TTBR0_EL1));
+ write_ttbr1_el1(read_ctx_reg(ctx, CTX_TTBR1_EL1));
+ write_mair_el1(read_ctx_reg(ctx, CTX_MAIR_EL1));
+ write_amair_el1(read_ctx_reg(ctx, CTX_AMAIR_EL1));
+ write_actlr_el1(read_ctx_reg(ctx, CTX_ACTLR_EL1));
+ write_tpidr_el1(read_ctx_reg(ctx, CTX_TPIDR_EL1));
+ write_tpidr_el0(read_ctx_reg(ctx, CTX_TPIDR_EL0));
+ write_tpidrro_el0(read_ctx_reg(ctx, CTX_TPIDRRO_EL0));
+ write_par_el1(read_ctx_reg(ctx, CTX_PAR_EL1));
+ write_far_el1(read_ctx_reg(ctx, CTX_FAR_EL1));
+ write_afsr0_el1(read_ctx_reg(ctx, CTX_AFSR0_EL1));
+ write_afsr1_el1(read_ctx_reg(ctx, CTX_AFSR1_EL1));
+ write_contextidr_el1(read_ctx_reg(ctx, CTX_CONTEXTIDR_EL1));
+ write_vbar_el1(read_ctx_reg(ctx, CTX_VBAR_EL1));
+
+#if CTX_INCLUDE_AARCH32_REGS
+ write_spsr_abt(read_ctx_reg(ctx, CTX_SPSR_ABT));
+ write_spsr_und(read_ctx_reg(ctx, CTX_SPSR_UND));
+ write_spsr_irq(read_ctx_reg(ctx, CTX_SPSR_IRQ));
+ write_spsr_fiq(read_ctx_reg(ctx, CTX_SPSR_FIQ));
+ write_dacr32_el2(read_ctx_reg(ctx, CTX_DACR32_EL2));
+ write_ifsr32_el2(read_ctx_reg(ctx, CTX_IFSR32_EL2));
+#endif /* CTX_INCLUDE_AARCH32_REGS */
+
+#if NS_TIMER_SWITCH
+ write_cntp_ctl_el0(read_ctx_reg(ctx, CTX_CNTP_CTL_EL0));
+ write_cntp_cval_el0(read_ctx_reg(ctx, CTX_CNTP_CVAL_EL0));
+ write_cntv_ctl_el0(read_ctx_reg(ctx, CTX_CNTV_CTL_EL0));
+ write_cntv_cval_el0(read_ctx_reg(ctx, CTX_CNTV_CVAL_EL0));
+ write_cntkctl_el1(read_ctx_reg(ctx, CTX_CNTKCTL_EL1));
+#endif /* NS_TIMER_SWITCH */
+
+#if ENABLE_FEAT_MTE
+ write_tfsre0_el1(read_ctx_reg(ctx, CTX_TFSRE0_EL1));
+ write_tfsr_el1(read_ctx_reg(ctx, CTX_TFSR_EL1));
+ write_rgsr_el1(read_ctx_reg(ctx, CTX_RGSR_EL1));
+ write_gcr_el1(read_ctx_reg(ctx, CTX_GCR_EL1));
+#endif /* ENABLE_FEAT_MTE */
+
+}
+
/*******************************************************************************
* The next four functions are used by runtime services to save and restore
* EL1 context on the 'cpu_context' structure for the specified security