mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-17 01:54:22 +00:00

Currently MDCR_EL3 register value is same for all the worlds(Non-secure, Secure, Realm and Root). With this approach, features enable/disable settings remain same across all the worlds. This is not ideal as there must be flexibility in controlling feature as per the requirements for individual world. The patch addresses this by providing MDCR_EL3 a per world value. Features with identical values for all the worlds are grouped under ``manage_extensions_common`` API. Change-Id: Ibc068d985fe165d8cb6d0ffb84119bffd743b3d1 Signed-off-by: Jayanth Dodderi Chidanand <jayanthdodderi.chidanand@arm.com>
131 lines
2.9 KiB
C
131 lines
2.9 KiB
C
/*
|
|
* Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <arch.h>
|
|
#include <arch_features.h>
|
|
#include <arch_helpers.h>
|
|
#include <lib/el3_runtime/pubsub.h>
|
|
#include <lib/extensions/spe.h>
|
|
|
|
#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);
|
|
u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
|
|
|
|
/*
|
|
* MDCR_EL3.NSPB (ARM v8.2): SPE enabled in Non-secure state
|
|
* and disabled in secure state. Accesses to SPE registers at
|
|
* S-EL1 generate trap exceptions to EL3.
|
|
*
|
|
* MDCR_EL3.NSPBE: Profiling Buffer uses Non-secure Virtual Addresses.
|
|
* When FEAT_RME is not implemented, this field is RES0.
|
|
*
|
|
* MDCR_EL3.EnPMSN (ARM v8.7): Do not trap access to PMSNEVFR_EL1
|
|
* register at NS-EL1 or NS-EL2 to EL3 if FEAT_SPEv1p2 is implemented.
|
|
* Setting this bit to 1 doesn't have any effect on it when
|
|
* FEAT_SPEv1p2 not implemented.
|
|
*/
|
|
mdcr_el3_val |= MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT;
|
|
mdcr_el3_val &= ~(MDCR_NSPBE_BIT);
|
|
write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
|
|
}
|
|
|
|
void spe_init_el2_unused(void)
|
|
{
|
|
uint64_t v;
|
|
|
|
/*
|
|
* MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
|
|
* profiling controls to EL2.
|
|
*
|
|
* MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
|
|
* state. Accesses to profiling buffer controls at
|
|
* Non-secure EL1 are not trapped to EL2.
|
|
*/
|
|
v = read_mdcr_el2();
|
|
v &= ~MDCR_EL2_TPMS;
|
|
v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
|
|
write_mdcr_el2(v);
|
|
}
|
|
|
|
void spe_disable(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);
|