Browse Source

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>
pull/1996/merge
Jayanth Dodderi Chidanand 5 months ago
parent
commit
59b7c0a03f
  1. 2
      include/arch/aarch64/el2_common_macros.S
  2. 2
      include/arch/aarch64/el3_common_macros.S
  3. 69
      include/lib/el3_runtime/aarch64/context.h
  4. 19
      lib/el3_runtime/aarch64/context.S
  5. 9
      lib/el3_runtime/aarch64/context_mgmt.c
  6. 14
      plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c
  7. 19
      services/std_svc/spm/el3_spmc/spmc_setup.c
  8. 23
      services/std_svc/spm/spm_mm/spm_mm_setup.c

2
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

2
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

69
include/lib/el3_runtime/aarch64/context.h

@ -279,10 +279,54 @@
#define CTX_CVE_2018_3639_DISABLE U(0)
#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 @@ DEFINE_REG_STRUCT(el3_state, CTX_EL3STATE_ALL);
/* 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 @@ typedef struct cpu_context {
#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 @@ extern per_world_context_t per_world_context[CPU_DATA_CONTEXT_NUM];
#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_FPREGS_OFFSET == __builtin_offsetof(cpu_context_t, fpregs_ctx),
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);

19
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 @@ func restore_gp_pmcr_pauth_regs
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 @@ func save_and_update_ptw_el1_sys_regs
* ----------------------------------------------------------
*/
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 @@ func save_and_update_ptw_el1_sys_regs
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.

9
lib/el3_runtime/aarch64/context_mgmt.c

@ -92,8 +92,13 @@ static void setup_el1_context(cpu_context_t *ctx, const struct entry_point_info
*/
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 @@ 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
#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 @@ 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
#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) */

14
plat/arm/board/neoverse_rd/common/ras/nrd_ras_cpu.c

@ -73,16 +73,26 @@ static void populate_cpu_err_data(cpu_err_info *cpu_info,
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),

19
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 @@ static void spmc_el0_sp_setup_mmu(struct secure_partition_desc *sp,
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 @@ static void spmc_el0_sp_setup_sctlr_el1(cpu_context_t *ctx)
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 @@ static void spmc_el0_sp_setup_sctlr_el1(cpu_context_t *ctx)
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,

23
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 @@ void spm_sp_setup(sp_context_t *sp_ctx)
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 @@ void spm_sp_setup(sp_context_t *sp_ctx)
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

Loading…
Cancel
Save