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 <manish.pandey2@arm.com>
Change-Id: I2f99e922e8df06bfc900c153137aef7c9dcfd759
diff --git a/include/lib/extensions/spe.h b/include/lib/extensions/spe.h
index bbfbd19..4801a22 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 750a8cb..d653222 100644
--- a/lib/extensions/spe/spe.c
+++ b/lib/extensions/spe/spe.c
@@ -52,6 +52,27 @@
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;