arm-trusted-firmware/lib/cpus/aarch64/cortex_gelas.S
Boyan Karatotev 45c7328c0b fix(cpus): avoid SME related loss of context on powerdown
Travis' and Gelas' TRMs tell us to disable SME (set PSTATE.{ZA, SM} to
0) when we're attempting to power down. What they don't tell us is that
if this isn't done, the powerdown request will be rejected. On the
CPU_OFF path that's not a problem - we can force SVCR to 0 and be
certain the core will power off.

On the suspend to powerdown path, however, we cannot do this. The TRM
also tells us that the sequence could also be aborted on eg. GIC
interrupts. If this were to happen when we have overwritten SVCR to 0,
upon a return to the caller they would experience a loss of context. We
know that at least Linux may call into PSCI with SVCR != 0. One option
is to save the entire SME context which would be quite expensive just to
work around. Another option is to downgrade the request to a normal
suspend when SME was left on. This option is better as this is expected
to happen rarely enough to ignore the wasted power and we don't want to
burden the generic (correct) path with needless context management.

Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
Change-Id: I698fa8490ebf51461f6aa8bba84f9827c5c46ad4
2025-02-03 14:29:47 +00:00

77 lines
2.2 KiB
ArmAsm

/*
* Copyright (c) 2023-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <asm_macros.S>
#include <common/bl_common.h>
#include <cortex_gelas.h>
#include <cpu_macros.S>
#include <plat_macros.S>
/* Hardware handled coherency */
#if HW_ASSISTED_COHERENCY == 0
#error "Gelas must be compiled with HW_ASSISTED_COHERENCY enabled"
#endif
/* 64-bit only core */
#if CTX_INCLUDE_AARCH32_REGS == 1
#error "Gelas supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0"
#endif
#if FEAT_PABANDON == 0
#error "Gelas must be compiled with FEAT_PABANDON enabled"
#endif
#if ERRATA_SME_POWER_DOWN == 0
#error "Gelas needs ERRATA_SME_POWER_DOWN=1 to powerdown correctly"
#endif
cpu_reset_func_start cortex_gelas
/* ----------------------------------------------------
* Disable speculative loads
* ----------------------------------------------------
*/
msr SSBS, xzr
cpu_reset_func_end cortex_gelas
/* ----------------------------------------------------
* HW will do the cache maintenance while powering down
* ----------------------------------------------------
*/
func cortex_gelas_core_pwr_dwn
/* ---------------------------------------------------
* Flip CPU power down bit in power control register.
* It will be set on powerdown and cleared on wakeup
* ---------------------------------------------------
*/
sysreg_bit_toggle CORTEX_GELAS_CPUPWRCTLR_EL1, \
CORTEX_GELAS_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
isb
ret
endfunc cortex_gelas_core_pwr_dwn
/* ---------------------------------------------
* This function provides Gelas specific
* register information for crash reporting.
* It needs to return with x6 pointing to
* a list of register names in ascii and
* x8 - x15 having values of registers to be
* reported.
* ---------------------------------------------
*/
.section .rodata.cortex_gelas_regs, "aS"
cortex_gelas_regs: /* The ASCII list of register names to be reported */
.asciz "imp_cpuectlr_el1", ""
func cortex_gelas_cpu_reg_dump
adr x6, cortex_gelas_regs
mrs x8, CORTEX_GELAS_IMP_CPUECTLR_EL1
ret
endfunc cortex_gelas_cpu_reg_dump
declare_cpu_ops cortex_gelas, CORTEX_GELAS_MIDR, \
cortex_gelas_reset_func, \
cortex_gelas_core_pwr_dwn