mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-16 09:34:18 +00:00
fix(spe): add a psb before updating context and remove context saving
In the chapter about FEAT_SPE (D16.4 specifically) it is stated that "Sampling is always disabled at EL3". That means that disabling sampling (writing PMBLIMITR_EL1.E to 0) is redundant and can be removed. The only reason we save/restore SPE context is because of that disable, so those can be removed too. There's the issue of draining the profiling buffer though. No new samples will have been generated since entering EL3. However, old samples might still be in-flight. Unless synchronised by a psb csync, those might be affected by our extensive context mutation. Adding a psb in prepare_el3_entry should cater for that. Note that prior to the introduction of root context this was not a problem as context remained unchanged and the hooks took care of the rest. Then, the only time we care about the buffer actually making it to memory is when we exit coherency. On HW_ASSISTED_COHERENCY systems we don't have to do anything, it should be handled for us. Systems without it need a dsb to wait for them to complete. There should be one already in each cpu's powerdown hook which should work. While on the topic of barriers, the esb barrier is no longer used. Remove it. Change-Id: I9736fc7d109702c63e7d403dc9e2a4272828afb2 Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
This commit is contained in:
parent
3c72b2ab0b
commit
f808873372
5 changed files with 13 additions and 106 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -224,13 +224,6 @@
|
|||
.space SPINLOCK_ASM_SIZE
|
||||
.endm
|
||||
|
||||
/*
|
||||
* With RAS extension executes esb instruction, else NOP
|
||||
*/
|
||||
.macro esb
|
||||
.inst 0xd503221f
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Helper macro to read system register value into x0
|
||||
*/
|
||||
|
@ -265,6 +258,10 @@
|
|||
msr SYSREG_SB, xzr
|
||||
.endm
|
||||
|
||||
.macro psb_csync
|
||||
hint #17 /* use the hint synonym for compatibility */
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Macro for using speculation barrier instruction introduced by
|
||||
* FEAT_SB, if it's enabled.
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
void spe_enable(cpu_context_t *ctx);
|
||||
void spe_disable(cpu_context_t *ctx);
|
||||
void spe_init_el2_unused(void);
|
||||
void spe_stop(void);
|
||||
#else
|
||||
static inline void spe_enable(cpu_context_t *ctx)
|
||||
{
|
||||
|
@ -25,9 +24,6 @@ static inline void spe_disable(cpu_context_t *ctx)
|
|||
static inline void spe_init_el2_unused(void)
|
||||
{
|
||||
}
|
||||
static inline void spe_stop(void)
|
||||
{
|
||||
}
|
||||
#endif /* ENABLE_SPE_FOR_NS */
|
||||
|
||||
#endif /* SPE_H */
|
||||
|
|
|
@ -440,6 +440,14 @@ no_mpam:
|
|||
* -----------------------------------------------------------------
|
||||
*/
|
||||
func prepare_el3_entry
|
||||
/*
|
||||
* context is about to mutate, so make sure we don't affect any still
|
||||
* in-flight profiling operations. We don't care that they actually
|
||||
* finish, that can still be later. NOP if not present
|
||||
*/
|
||||
#if ENABLE_SPE_FOR_NS
|
||||
psb_csync
|
||||
#endif
|
||||
save_gp_pmcr_pauth_regs
|
||||
setup_el3_execution_context
|
||||
ret
|
||||
|
|
|
@ -14,21 +14,6 @@
|
|||
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
typedef struct spe_ctx {
|
||||
u_register_t pmblimitr_el1;
|
||||
} spe_ctx_t;
|
||||
|
||||
static struct spe_ctx spe_ctxs[PLATFORM_CORE_COUNT];
|
||||
|
||||
static inline void psb_csync(void)
|
||||
{
|
||||
/*
|
||||
* The assembler does not yet understand the psb csync mnemonic
|
||||
* so use the equivalent hint instruction.
|
||||
*/
|
||||
__asm__ volatile("hint #17");
|
||||
}
|
||||
|
||||
void spe_enable(cpu_context_t *ctx)
|
||||
{
|
||||
el3_state_t *state = get_el3state_ctx(ctx);
|
||||
|
@ -90,63 +75,3 @@ void spe_init_el2_unused(void)
|
|||
v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
|
||||
write_mdcr_el2(v);
|
||||
}
|
||||
|
||||
void spe_stop(void)
|
||||
{
|
||||
uint64_t v;
|
||||
|
||||
/* Drain buffered data */
|
||||
psb_csync();
|
||||
dsbnsh();
|
||||
|
||||
/* Disable profiling buffer */
|
||||
v = read_pmblimitr_el1();
|
||||
v &= ~(1ULL << 0);
|
||||
write_pmblimitr_el1(v);
|
||||
isb();
|
||||
}
|
||||
|
||||
static void *spe_drain_buffers_hook(const void *arg)
|
||||
{
|
||||
if (!is_feat_spe_supported())
|
||||
return (void *)-1;
|
||||
|
||||
/* Drain buffered data */
|
||||
psb_csync();
|
||||
dsbnsh();
|
||||
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
static void *spe_context_save(const void *arg)
|
||||
{
|
||||
unsigned int core_pos;
|
||||
struct spe_ctx *ctx;
|
||||
|
||||
if (is_feat_spe_supported()) {
|
||||
core_pos = plat_my_core_pos();
|
||||
ctx = &spe_ctxs[core_pos];
|
||||
ctx->pmblimitr_el1 = read_pmblimitr_el1();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *spe_context_restore(const void *arg)
|
||||
{
|
||||
unsigned int core_pos;
|
||||
struct spe_ctx *ctx;
|
||||
|
||||
if (is_feat_spe_supported()) {
|
||||
core_pos = plat_my_core_pos();
|
||||
ctx = &spe_ctxs[core_pos];
|
||||
write_pmblimitr_el1(ctx->pmblimitr_el1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook);
|
||||
|
||||
SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, spe_context_save);
|
||||
SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, spe_context_restore);
|
||||
|
|
|
@ -1169,8 +1169,6 @@ int psci_secondaries_brought_up(void)
|
|||
******************************************************************************/
|
||||
void psci_pwrdown_cpu(unsigned int power_level)
|
||||
{
|
||||
psci_do_manage_extensions();
|
||||
|
||||
#if HW_ASSISTED_COHERENCY
|
||||
/*
|
||||
* With hardware-assisted coherency, the CPU drivers only initiate the
|
||||
|
@ -1290,20 +1288,3 @@ bool psci_are_all_cpus_on_safe(void)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function performs architectural feature specific management.
|
||||
* It ensures the architectural features are disabled during cpu
|
||||
* power off/suspend operations.
|
||||
******************************************************************************/
|
||||
void psci_do_manage_extensions(void)
|
||||
{
|
||||
/*
|
||||
* On power down we need to disable statistical profiling extensions
|
||||
* before exiting coherency.
|
||||
*/
|
||||
if (is_feat_spe_supported()) {
|
||||
spe_stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue