feat(cm): add explicit context entries for ERRATA_SPECULATIVE_AT
* Currently, "ERRATA_SPECUALTIVE_AT" errata is enabled by default
for few cores and they need context entries for saving and
restoring EL1 regs "SCTLR_EL1 and TCR_EL1" registers at all times.
* This prevents the mechanism of decoupling EL1 and EL2 registers,
as EL3 firmware shouldn't be handling both simultaneously.
* Depending on the build configuration either EL1 or EL2 context
structures need to included, which would result in saving a good
amount of context memory.
* In order to achieve this it's essential to have explicit context
entries for registers supporting "ERRATA_SPECULATIVE_AT".
* This patch adds two context entries under "errata_speculative_at"
structure to assist this errata and thereby allows decoupling
EL1 and EL2 context structures.
Change-Id: Ia50626eea8fb64899a2e2d81622adbe07fe77d65
Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>
diff --git a/include/arch/aarch64/el2_common_macros.S b/include/arch/aarch64/el2_common_macros.S
index 9f82399..b9b0e3d 100644
--- a/include/arch/aarch64/el2_common_macros.S
+++ b/include/arch/aarch64/el2_common_macros.S
@@ -408,7 +408,7 @@
* -----------------------------------------------------------
*/
isb
- ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1]
+ ldp x28, x29, [sp, #CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_SCTLR_EL1]
msr sctlr_el1, x28
isb
msr tcr_el1, x29
diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S
index b4c5c1b..60c5a0c 100644
--- a/include/arch/aarch64/el3_common_macros.S
+++ b/include/arch/aarch64/el3_common_macros.S
@@ -437,7 +437,7 @@
* -----------------------------------------------------------
*/
isb
- ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1]
+ ldp x28, x29, [sp, #CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_SCTLR_EL1]
msr sctlr_el1, x28
isb
msr tcr_el1, x29
diff --git a/include/lib/el3_runtime/aarch64/context.h b/include/lib/el3_runtime/aarch64/context.h
index acf111b..005dcaf 100644
--- a/include/lib/el3_runtime/aarch64/context.h
+++ b/include/lib/el3_runtime/aarch64/context.h
@@ -280,9 +280,53 @@
#define CTX_CVE_2018_3639_END U(0x10) /* Align to the next 16 byte boundary */
/*******************************************************************************
+ * Registers related to ERRATA_SPECULATIVE_AT
+ *
+ * This is essential as with EL1 and EL2 context registers being decoupled,
+ * both will not be present for a given build configuration.
+ * As ERRATA_SPECULATIVE_AT errata requires SCTLR_EL1 and TCR_EL1 registers
+ * independent of the above logic, we need explicit context entries to be
+ * reserved for these registers.
+ *
+ * NOTE: Based on this we end up with following different configurations depending
+ * on the presence of errata and inclusion of EL1 or EL2 context.
+ *
+ * ============================================================================
+ * | ERRATA_SPECULATIVE_AT | EL1 context| Memory allocation(Sctlr_el1,Tcr_el1)|
+ * ============================================================================
+ * | 0 | 0 | None |
+ * | 0 | 1 | EL1 C-Context structure |
+ * | 1 | 0 | Errata Context Offset Entries |
+ * | 1 | 1 | Errata Context Offset Entries |
+ * ============================================================================
+ *
+ * In the above table, when ERRATA_SPECULATIVE_AT=1, EL1_Context=0, it implies
+ * there is only EL2 context and memory for SCTLR_EL1 and TCR_EL1 registers is
+ * reserved explicitly under ERRATA_SPECULATIVE_AT build flag here.
+ *
+ * In situations when EL1_Context=1 and ERRATA_SPECULATIVE_AT=1, since SCTLR_EL1
+ * and TCR_EL1 registers will be modified under errata and it happens at the
+ * early in the codeflow prior to el1 context (save and restore operations),
+ * context memory still will be reserved under the errata logic here explicitly.
+ * These registers will not be part of EL1 context save & restore routines.
+ *
+ * Only when ERRATA_SPECULATIVE_AT=0, EL1_Context=1, for this combination,
+ * SCTLR_EL1 and TCR_EL1 will be part of EL1 context structure (context_el1.h)
+ * -----------------------------------------------------------------------------
+ ******************************************************************************/
+#define CTX_ERRATA_SPEC_AT_OFFSET (CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_END)
+#if ERRATA_SPECULATIVE_AT
+#define CTX_ERRATA_SPEC_AT_SCTLR_EL1 U(0x0)
+#define CTX_ERRATA_SPEC_AT_TCR_EL1 U(0x8)
+#define CTX_ERRATA_SPEC_AT_END U(0x10) /* Align to the next 16 byte boundary */
+#else
+#define CTX_ERRATA_SPEC_AT_END U(0x0)
+#endif /* ERRATA_SPECULATIVE_AT */
+
+/*******************************************************************************
* Registers related to ARMv8.3-PAuth.
******************************************************************************/
-#define CTX_PAUTH_REGS_OFFSET (CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_END)
+#define CTX_PAUTH_REGS_OFFSET (CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_END)
#if CTX_INCLUDE_PAUTH_REGS
#define CTX_PACIAKEY_LO U(0x0)
#define CTX_PACIAKEY_HI U(0x8)
@@ -332,6 +376,10 @@
#endif
#define CTX_EL3STATE_ALL (CTX_EL3STATE_END >> DWORD_SHIFT)
#define CTX_CVE_2018_3639_ALL (CTX_CVE_2018_3639_END >> DWORD_SHIFT)
+
+#if ERRATA_SPECULATIVE_AT
+#define CTX_ERRATA_SPEC_AT_ALL (CTX_ERRATA_SPEC_AT_END >> DWORD_SHIFT)
+#endif
#if CTX_INCLUDE_PAUTH_REGS
# define CTX_PAUTH_REGS_ALL (CTX_PAUTH_REGS_END >> DWORD_SHIFT)
#endif
@@ -369,6 +417,11 @@
/* Function pointer used by CVE-2018-3639 dynamic mitigation */
DEFINE_REG_STRUCT(cve_2018_3639, CTX_CVE_2018_3639_ALL);
+/* Registers associated to Errata_Speculative */
+#if ERRATA_SPECULATIVE_AT
+DEFINE_REG_STRUCT(errata_speculative_at, CTX_ERRATA_SPEC_AT_ALL);
+#endif
+
/* Registers associated to ARMv8.3-PAuth */
#if CTX_INCLUDE_PAUTH_REGS
DEFINE_REG_STRUCT(pauth, CTX_PAUTH_REGS_ALL);
@@ -400,6 +453,10 @@
#endif
cve_2018_3639_t cve_2018_3639_ctx;
+#if ERRATA_SPECULATIVE_AT
+ errata_speculative_at_t errata_speculative_at_ctx;
+#endif
+
#if CTX_INCLUDE_PAUTH_REGS
pauth_t pauth_ctx;
#endif
@@ -433,6 +490,11 @@
#endif
#define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx)
#define get_cve_2018_3639_ctx(h) (&((cpu_context_t *) h)->cve_2018_3639_ctx)
+
+#if ERRATA_SPECULATIVE_AT
+#define get_errata_speculative_at_ctx(h) (&((cpu_context_t *) h)->errata_speculative_at_ctx)
+#endif
+
#if CTX_INCLUDE_PAUTH_REGS
# define get_pauth_ctx(h) (&((cpu_context_t *) h)->pauth_ctx)
#endif
@@ -459,6 +521,11 @@
CASSERT(CTX_CVE_2018_3639_OFFSET == __builtin_offsetof(cpu_context_t, cve_2018_3639_ctx),
assert_core_context_cve_2018_3639_offset_mismatch);
+#if ERRATA_SPECULATIVE_AT
+CASSERT(CTX_ERRATA_SPEC_AT_OFFSET == __builtin_offsetof(cpu_context_t, errata_speculative_at_ctx),
+ assert_core_context_errata_speculative_at_offset_mismatch);
+#endif
+
#if CTX_INCLUDE_PAUTH_REGS
CASSERT(CTX_PAUTH_REGS_OFFSET == __builtin_offsetof(cpu_context_t, pauth_ctx),
assert_core_context_pauth_offset_mismatch);
diff --git a/lib/el3_runtime/aarch64/context.S b/lib/el3_runtime/aarch64/context.S
index 1fce1bf..62895ff 100644
--- a/lib/el3_runtime/aarch64/context.S
+++ b/lib/el3_runtime/aarch64/context.S
@@ -14,9 +14,13 @@
.global fpregs_context_save
.global fpregs_context_restore
#endif /* CTX_INCLUDE_FPREGS */
+
+#if ERRATA_SPECULATIVE_AT
+ .global save_and_update_ptw_el1_sys_regs
+#endif /* ERRATA_SPECULATIVE_AT */
+
.global prepare_el3_entry
.global restore_gp_pmcr_pauth_regs
- .global save_and_update_ptw_el1_sys_regs
.global el3_exit
/* ------------------------------------------------------------------
@@ -329,10 +333,12 @@
ret
endfunc restore_gp_pmcr_pauth_regs
-/*
+#if ERRATA_SPECULATIVE_AT
+/* --------------------------------------------------------------------
* In case of ERRATA_SPECULATIVE_AT, save SCTLR_EL1 and TCR_EL1
* registers and update EL1 registers to disable stage1 and stage2
- * page table walk
+ * page table walk.
+ * --------------------------------------------------------------------
*/
func save_and_update_ptw_el1_sys_regs
/* ----------------------------------------------------------
@@ -340,9 +346,9 @@
* ----------------------------------------------------------
*/
mrs x29, sctlr_el1
- str x29, [sp, #(CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1)]
+ str x29, [sp, #(CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_SCTLR_EL1)]
mrs x29, tcr_el1
- str x29, [sp, #(CTX_EL1_SYSREGS_OFFSET + CTX_TCR_EL1)]
+ str x29, [sp, #(CTX_ERRATA_SPEC_AT_OFFSET + CTX_ERRATA_SPEC_AT_TCR_EL1)]
/* ------------------------------------------------------------
* Must follow below order in order to disable page table
@@ -367,10 +373,11 @@
orr x29, x29, #SCTLR_M_BIT
msr sctlr_el1, x29
isb
-
ret
endfunc save_and_update_ptw_el1_sys_regs
+#endif /* ERRATA_SPECULATIVE_AT */
+
/* -----------------------------------------------------------------
* The below macro returns the address of the per_world context for
* the security state, retrieved through "get_security_state" macro.
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index c525247..9b2774d 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -92,8 +92,13 @@
*/
sctlr_elx |= SCTLR_IESB_BIT;
#endif
+
/* Store the initialised SCTLR_EL1 value in the cpu_context */
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx), CTX_ERRATA_SPEC_AT_SCTLR_EL1, sctlr_elx);
+#else
write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx);
+#endif /* ERRATA_SPECULATIVE_AT */
/*
* Base the context ACTLR_EL1 on the current value, as it is
@@ -1551,7 +1556,7 @@
write_ctx_reg(ctx, CTX_SPSR_EL1, read_spsr_el1());
write_ctx_reg(ctx, CTX_ELR_EL1, read_elr_el1());
-#if !ERRATA_SPECULATIVE_AT
+#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) */
@@ -1660,7 +1665,7 @@
write_spsr_el1(read_ctx_reg(ctx, CTX_SPSR_EL1));
write_elr_el1(read_ctx_reg(ctx, CTX_ELR_EL1));
-#if !ERRATA_SPECULATIVE_AT
+#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) */
diff --git a/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c b/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c
index 371bde6..d49e6e9 100644
--- a/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c
+++ b/plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c
@@ -73,16 +73,26 @@
CTX_MAIR_EL1);
cpu_info->ErrCtxEl1Reg[5] = read_midr_el1();
cpu_info->ErrCtxEl1Reg[6] = read_mpidr_el1();
+#if (ERRATA_SPECULATIVE_AT)
+ cpu_info->ErrCtxEl1Reg[7] = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1);
+#else
cpu_info->ErrCtxEl1Reg[7] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
CTX_SCTLR_EL1);
+#endif /* ERRATA_SPECULATIVE_AT */
cpu_info->ErrCtxEl1Reg[8] = read_ctx_reg(get_gpregs_ctx(ctx),
CTX_GPREG_SP_EL0);
cpu_info->ErrCtxEl1Reg[9] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
CTX_SP_EL1);
cpu_info->ErrCtxEl1Reg[10] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
CTX_SPSR_EL1);
- cpu_info->ErrCtxEl1Reg[11] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
- CTX_TCR_EL1);
+#if (ERRATA_SPECULATIVE_AT)
+ cpu_info->ErrCtxEl1Reg[11] = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_TCR_EL1);
+#else
+ cpu_info->ErrCtxEl1Reg[11] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
+ CTX_TCR_EL1);
+#endif /* ERRATA_SPECULATIVE_AT */
cpu_info->ErrCtxEl1Reg[12] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
CTX_TPIDR_EL0);
cpu_info->ErrCtxEl1Reg[13] = read_ctx_reg(get_el1_sysregs_ctx(ctx),
diff --git a/services/std_svc/spm/el3_spmc/spmc_setup.c b/services/std_svc/spm/el3_spmc/spmc_setup.c
index 609d968..9eb6d9a 100644
--- a/services/std_svc/spm/el3_spmc/spmc_setup.c
+++ b/services/std_svc/spm/el3_spmc/spmc_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2022-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -322,8 +322,14 @@
write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1,
mmu_cfg_params[MMU_CFG_MAIR]);
+ /* Store the initialised SCTLR_EL1 value in the cpu_context */
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_TCR_EL1, mmu_cfg_params[MMU_CFG_TCR]);
+#else
write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1,
mmu_cfg_params[MMU_CFG_TCR]);
+#endif /* ERRATA_SPECULATIVE_AT */
write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1,
mmu_cfg_params[MMU_CFG_TTBR0]);
@@ -334,7 +340,12 @@
u_register_t sctlr_el1;
/* Setup SCTLR_EL1 */
+#if (ERRATA_SPECULATIVE_AT)
+ sctlr_el1 = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1);
+#else
sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
+#endif /* ERRATA_SPECULATIVE_AT */
sctlr_el1 |=
/*SCTLR_EL1_RES1 |*/
@@ -369,7 +380,13 @@
SCTLR_UMA_BIT
);
+ /* Store the initialised SCTLR_EL1 value in the cpu_context */
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1, sctlr_el1);
+#else
write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
+#endif /* ERRATA_SPECULATIVE_AT */
}
static void spmc_el0_sp_setup_system_registers(struct secure_partition_desc *sp,
diff --git a/services/std_svc/spm/spm_mm/spm_mm_setup.c b/services/std_svc/spm/spm_mm/spm_mm_setup.c
index 4e65c9c..c96286f 100644
--- a/services/std_svc/spm/spm_mm/spm_mm_setup.c
+++ b/services/std_svc/spm/spm_mm/spm_mm_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
@@ -27,7 +27,7 @@
void spm_sp_setup(sp_context_t *sp_ctx)
{
cpu_context_t *ctx = &(sp_ctx->cpu_ctx);
-
+ u_register_t sctlr_el1;
/* Pointer to the MP information from the platform port. */
const spm_mm_boot_info_t *sp_boot_info =
plat_get_secure_partition_boot_info(NULL);
@@ -125,14 +125,25 @@
write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1,
mmu_cfg_params[MMU_CFG_MAIR]);
+ /* Store the initialised SCTLR_EL1 value in the cpu_context */
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_TCR_EL1, mmu_cfg_params[MMU_CFG_TCR]);
+#else
write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1,
mmu_cfg_params[MMU_CFG_TCR]);
+#endif /* ERRATA_SPECULATIVE_AT */
write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1,
mmu_cfg_params[MMU_CFG_TTBR0]);
/* Setup SCTLR_EL1 */
- u_register_t sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
+#if (ERRATA_SPECULATIVE_AT)
+ sctlr_el1 = read_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1);
+#else
+ sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
+#endif /* ERRATA_SPECULATIVE_AT */
sctlr_el1 |=
/*SCTLR_EL1_RES1 |*/
@@ -168,7 +179,13 @@
SCTLR_UMA_BIT
);
+ /* Store the initialised SCTLR_EL1 value in the cpu_context */
+#if (ERRATA_SPECULATIVE_AT)
+ write_ctx_reg(get_errata_speculative_at_ctx(ctx),
+ CTX_ERRATA_SPEC_AT_SCTLR_EL1, sctlr_el1);
+#else
write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
+#endif /* ERRATA_SPECULATIVE_AT */
/*
* Setup other system registers