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/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) */