From 4de07b4be77ad695e3f57080a1f89cff24b1abad Mon Sep 17 00:00:00 2001 From: Manish Pandey Date: Thu, 18 Jul 2024 16:07:21 +0100 Subject: [PATCH 1/3] chore(spe): rename spe_disable() to spe_stop() During CPU power down, we stop the profiling by calling spe_disable() function. From TF-A point of view, enable/disable means the avaibility of the feature for lower EL. In this case we are not actully disabling the feautre but stoping it before power down. Signed-off-by: Manish Pandey Change-Id: I6e3b39c5c35d330c51e7ac715446a8b36bf9531f --- include/lib/extensions/spe.h | 4 ++-- lib/extensions/spe/spe.c | 2 +- lib/psci/psci_common.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/lib/extensions/spe.h b/include/lib/extensions/spe.h index c6e44f96b..bbfbd1983 100644 --- a/include/lib/extensions/spe.h +++ b/include/lib/extensions/spe.h @@ -13,7 +13,7 @@ #if ENABLE_SPE_FOR_NS void spe_enable(cpu_context_t *ctx); void spe_init_el2_unused(void); -void spe_disable(void); +void spe_stop(void); #else static inline void spe_enable(cpu_context_t *ctx) { @@ -21,7 +21,7 @@ static inline void spe_enable(cpu_context_t *ctx) static inline void spe_init_el2_unused(void) { } -static inline void spe_disable(void) +static inline void spe_stop(void) { } #endif /* ENABLE_SPE_FOR_NS */ diff --git a/lib/extensions/spe/spe.c b/lib/extensions/spe/spe.c index c6076fe1e..750a8cb93 100644 --- a/lib/extensions/spe/spe.c +++ b/lib/extensions/spe/spe.c @@ -70,7 +70,7 @@ void spe_init_el2_unused(void) write_mdcr_el2(v); } -void spe_disable(void) +void spe_stop(void) { uint64_t v; diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c index 60449f646..9f0b19089 100644 --- a/lib/psci/psci_common.c +++ b/lib/psci/psci_common.c @@ -1303,7 +1303,7 @@ void psci_do_manage_extensions(void) * before exiting coherency. */ if (is_feat_spe_supported()) { - spe_disable(); + spe_stop(); } } From 651fe5073c790647305363a4de05cf050e0851de Mon Sep 17 00:00:00 2001 From: Manish Pandey Date: Thu, 18 Jul 2024 16:17:45 +0100 Subject: [PATCH 2/3] feat(spe): introduce spe_disable() function Introduce a function to disable SPE feature for Non-secure state and do the default setting of making Secure state the owner of profiling buffers and trap access of profiling and profiling buffer control registers from lower ELs to EL3. This functionality is required to handle asymmetric cores where SPE has to disabled at runtime. Signed-off-by: Manish Pandey Change-Id: I2f99e922e8df06bfc900c153137aef7c9dcfd759 --- include/lib/extensions/spe.h | 4 ++++ lib/extensions/spe/spe.c | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/lib/extensions/spe.h b/include/lib/extensions/spe.h index bbfbd1983..4801a2206 100644 --- a/include/lib/extensions/spe.h +++ b/include/lib/extensions/spe.h @@ -12,12 +12,16 @@ #if ENABLE_SPE_FOR_NS 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) { } +static inline void spe_disable(cpu_context_t *ctx) +{ +} static inline void spe_init_el2_unused(void) { } diff --git a/lib/extensions/spe/spe.c b/lib/extensions/spe/spe.c index 750a8cb93..d6532224a 100644 --- a/lib/extensions/spe/spe.c +++ b/lib/extensions/spe/spe.c @@ -52,6 +52,27 @@ void spe_enable(cpu_context_t *ctx) write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val); } +void spe_disable(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: Clear these bits to disable SPE feature, as it was enabled + * for Non-secure state only. After clearing these bits Secure state owns + * the Profiling Buffer and accesses to Statistical Profiling and Profiling + * Buffer control registers at EL2 and EL1 generate Trap exceptions to EL3 + * + * MDCR_EL3.NSPBE: Don't care as it was cleared during spe_enable and setting + * this to 1 does not make sense as NSPBE{1} and NSPB{0b0x} is RESERVED. + * + * MDCR_EL3.EnPMSN (ARM v8.7): Clear the bit to trap access of PMSNEVFR_EL1 + * from EL2/EL1 to EL3. + */ + mdcr_el3_val &= ~(MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT); + write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val); +} + void spe_init_el2_unused(void) { uint64_t v; From b36e975ea374589270fc4010aa247e1e56432bda Mon Sep 17 00:00:00 2001 From: Arvind Ram Prakash Date: Fri, 19 Jul 2024 11:39:49 -0500 Subject: [PATCH 3/3] feat(trbe): introduce trbe_disable() function This patch adds trbe_disable() which disables Trace buffer access from lower ELs in all security state. This function makes Secure state the owner of Trace buffer and access from EL2/EL1 generate trap exceptions to EL3. Signed-off-by: Arvind Ram Prakash Change-Id: If3e3bd621684b3c28f44c3ed2fe3df30b143f8cd --- include/lib/extensions/trbe.h | 4 ++++ lib/extensions/trbe/trbe.c | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/lib/extensions/trbe.h b/include/lib/extensions/trbe.h index 5db331672..2c488e097 100644 --- a/include/lib/extensions/trbe.h +++ b/include/lib/extensions/trbe.h @@ -10,9 +10,13 @@ #include #if ENABLE_TRBE_FOR_NS +void trbe_disable(cpu_context_t *ctx); void trbe_enable(cpu_context_t *ctx); void trbe_init_el2_unused(void); #else +static inline void trbe_disable(cpu_context_t *ctx) +{ +} static inline void trbe_enable(cpu_context_t *ctx) { } diff --git a/lib/extensions/trbe/trbe.c b/lib/extensions/trbe/trbe.c index 915773420..8c1c42180 100644 --- a/lib/extensions/trbe/trbe.c +++ b/lib/extensions/trbe/trbe.c @@ -39,6 +39,25 @@ void trbe_enable(cpu_context_t *ctx) write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val); } +void trbe_disable(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.NSTBE = 0b0 + * Trace Buffer owning Security state is secure state. If FEAT_RME + * is not implemented, this field is RES0. + * + * MDCR_EL3.NSTB = 0b00 + * Clear these bits to disable access of trace buffer control registers + * from lower ELs in any security state. + */ + mdcr_el3_val &= ~(MDCR_NSTB(MDCR_NSTB_EL1)); + mdcr_el3_val &= ~(MDCR_NSTBE_BIT); + write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val); +} + void trbe_init_el2_unused(void) { /*