xref: /rk3399_ARM-atf/lib/extensions/spe/spe.c (revision 651fe5073c790647305363a4de05cf050e0851de)
1281a08ccSDimitris Papastamos /*
2777f1f68SJayanth Dodderi Chidanand  * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved.
3281a08ccSDimitris Papastamos  *
4281a08ccSDimitris Papastamos  * SPDX-License-Identifier: BSD-3-Clause
5281a08ccSDimitris Papastamos  */
6281a08ccSDimitris Papastamos 
709d40e0eSAntonio Nino Diaz #include <stdbool.h>
809d40e0eSAntonio Nino Diaz 
9281a08ccSDimitris Papastamos #include <arch.h>
106437a09aSAndre Przywara #include <arch_features.h>
11281a08ccSDimitris Papastamos #include <arch_helpers.h>
1209d40e0eSAntonio Nino Diaz #include <lib/el3_runtime/pubsub.h>
1309d40e0eSAntonio Nino Diaz #include <lib/extensions/spe.h>
14281a08ccSDimitris Papastamos 
15777f1f68SJayanth Dodderi Chidanand #include <plat/common/platform.h>
16777f1f68SJayanth Dodderi Chidanand 
17777f1f68SJayanth Dodderi Chidanand typedef struct spe_ctx {
18777f1f68SJayanth Dodderi Chidanand 	u_register_t pmblimitr_el1;
19777f1f68SJayanth Dodderi Chidanand } spe_ctx_t;
20777f1f68SJayanth Dodderi Chidanand 
21777f1f68SJayanth Dodderi Chidanand static struct spe_ctx spe_ctxs[PLATFORM_CORE_COUNT];
22777f1f68SJayanth Dodderi Chidanand 
2340daecc1SAntonio Nino Diaz static inline void psb_csync(void)
2440daecc1SAntonio Nino Diaz {
25281a08ccSDimitris Papastamos 	/*
26281a08ccSDimitris Papastamos 	 * The assembler does not yet understand the psb csync mnemonic
27281a08ccSDimitris Papastamos 	 * so use the equivalent hint instruction.
28281a08ccSDimitris Papastamos 	 */
2940daecc1SAntonio Nino Diaz 	__asm__ volatile("hint #17");
3040daecc1SAntonio Nino Diaz }
31281a08ccSDimitris Papastamos 
32123002f9SJayanth Dodderi Chidanand void spe_enable(cpu_context_t *ctx)
332ff8fbf3SDimitris Papastamos {
34123002f9SJayanth Dodderi Chidanand 	el3_state_t *state = get_el3state_ctx(ctx);
35123002f9SJayanth Dodderi Chidanand 	u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
36281a08ccSDimitris Papastamos 
37281a08ccSDimitris Papastamos 	/*
3899506facSBoyan Karatotev 	 * MDCR_EL3.NSPB (ARM v8.2): SPE enabled in Non-secure state
39281a08ccSDimitris Papastamos 	 * and disabled in secure state. Accesses to SPE registers at
40281a08ccSDimitris Papastamos 	 * S-EL1 generate trap exceptions to EL3.
41f20eb893SManish V Badarkhe 	 *
4299506facSBoyan Karatotev 	 * MDCR_EL3.NSPBE: Profiling Buffer uses Non-secure Virtual Addresses.
4399506facSBoyan Karatotev 	 * When FEAT_RME is not implemented, this field is RES0.
4499506facSBoyan Karatotev 	 *
45f20eb893SManish V Badarkhe 	 * MDCR_EL3.EnPMSN (ARM v8.7): Do not trap access to PMSNEVFR_EL1
46f20eb893SManish V Badarkhe 	 * register at NS-EL1 or NS-EL2 to EL3 if FEAT_SPEv1p2 is implemented.
47f20eb893SManish V Badarkhe 	 * Setting this bit to 1 doesn't have any effect on it when
48f20eb893SManish V Badarkhe 	 * FEAT_SPEv1p2 not implemented.
49281a08ccSDimitris Papastamos 	 */
50123002f9SJayanth Dodderi Chidanand 	mdcr_el3_val |= MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT;
51123002f9SJayanth Dodderi Chidanand 	mdcr_el3_val &= ~(MDCR_NSPBE_BIT);
52123002f9SJayanth Dodderi Chidanand 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
53281a08ccSDimitris Papastamos }
54281a08ccSDimitris Papastamos 
55*651fe507SManish Pandey void spe_disable(cpu_context_t *ctx)
56*651fe507SManish Pandey {
57*651fe507SManish Pandey 	el3_state_t *state = get_el3state_ctx(ctx);
58*651fe507SManish Pandey 	u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
59*651fe507SManish Pandey 
60*651fe507SManish Pandey 	/*
61*651fe507SManish Pandey 	 * MDCR_EL3.NSPB: Clear these bits to disable SPE feature, as it was enabled
62*651fe507SManish Pandey 	 * for Non-secure state only. After clearing these bits Secure state owns
63*651fe507SManish Pandey 	 * the Profiling Buffer and accesses to Statistical Profiling and Profiling
64*651fe507SManish Pandey 	 * Buffer control registers at EL2 and EL1 generate Trap exceptions to EL3
65*651fe507SManish Pandey 	 *
66*651fe507SManish Pandey 	 * MDCR_EL3.NSPBE: Don't care as it was cleared during spe_enable and setting
67*651fe507SManish Pandey 	 * this to 1 does not make sense as NSPBE{1} and NSPB{0b0x} is RESERVED.
68*651fe507SManish Pandey 	 *
69*651fe507SManish Pandey 	 * MDCR_EL3.EnPMSN (ARM v8.7): Clear the bit to trap access of PMSNEVFR_EL1
70*651fe507SManish Pandey 	 * from EL2/EL1 to EL3.
71*651fe507SManish Pandey 	 */
72*651fe507SManish Pandey 	mdcr_el3_val &= ~(MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT);
73*651fe507SManish Pandey 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
74*651fe507SManish Pandey }
75*651fe507SManish Pandey 
7660d330dcSBoyan Karatotev void spe_init_el2_unused(void)
7760d330dcSBoyan Karatotev {
7860d330dcSBoyan Karatotev 	uint64_t v;
7960d330dcSBoyan Karatotev 
8060d330dcSBoyan Karatotev 	/*
8160d330dcSBoyan Karatotev 	 * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
8260d330dcSBoyan Karatotev 	 * profiling controls to EL2.
8360d330dcSBoyan Karatotev 	 *
8460d330dcSBoyan Karatotev 	 * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
8560d330dcSBoyan Karatotev 	 * state. Accesses to profiling buffer controls at
8660d330dcSBoyan Karatotev 	 * Non-secure EL1 are not trapped to EL2.
8760d330dcSBoyan Karatotev 	 */
8860d330dcSBoyan Karatotev 	v = read_mdcr_el2();
8960d330dcSBoyan Karatotev 	v &= ~MDCR_EL2_TPMS;
9060d330dcSBoyan Karatotev 	v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
9160d330dcSBoyan Karatotev 	write_mdcr_el2(v);
9260d330dcSBoyan Karatotev }
9360d330dcSBoyan Karatotev 
944de07b4bSManish Pandey void spe_stop(void)
95281a08ccSDimitris Papastamos {
96281a08ccSDimitris Papastamos 	uint64_t v;
97281a08ccSDimitris Papastamos 
98281a08ccSDimitris Papastamos 	/* Drain buffered data */
99281a08ccSDimitris Papastamos 	psb_csync();
100281a08ccSDimitris Papastamos 	dsbnsh();
101281a08ccSDimitris Papastamos 
102281a08ccSDimitris Papastamos 	/* Disable profiling buffer */
103281a08ccSDimitris Papastamos 	v = read_pmblimitr_el1();
104281a08ccSDimitris Papastamos 	v &= ~(1ULL << 0);
105281a08ccSDimitris Papastamos 	write_pmblimitr_el1(v);
106281a08ccSDimitris Papastamos 	isb();
107281a08ccSDimitris Papastamos }
108281a08ccSDimitris Papastamos 
109281a08ccSDimitris Papastamos static void *spe_drain_buffers_hook(const void *arg)
110281a08ccSDimitris Papastamos {
1116437a09aSAndre Przywara 	if (!is_feat_spe_supported())
1122ff8fbf3SDimitris Papastamos 		return (void *)-1;
113281a08ccSDimitris Papastamos 
114281a08ccSDimitris Papastamos 	/* Drain buffered data */
115281a08ccSDimitris Papastamos 	psb_csync();
116281a08ccSDimitris Papastamos 	dsbnsh();
11740daecc1SAntonio Nino Diaz 
11840daecc1SAntonio Nino Diaz 	return (void *)0;
119281a08ccSDimitris Papastamos }
120281a08ccSDimitris Papastamos 
121777f1f68SJayanth Dodderi Chidanand static void *spe_context_save(const void *arg)
122777f1f68SJayanth Dodderi Chidanand {
123777f1f68SJayanth Dodderi Chidanand 	unsigned int core_pos;
124777f1f68SJayanth Dodderi Chidanand 	struct spe_ctx *ctx;
125777f1f68SJayanth Dodderi Chidanand 
126777f1f68SJayanth Dodderi Chidanand 	if (is_feat_spe_supported()) {
127777f1f68SJayanth Dodderi Chidanand 		core_pos = plat_my_core_pos();
128777f1f68SJayanth Dodderi Chidanand 		ctx = &spe_ctxs[core_pos];
129777f1f68SJayanth Dodderi Chidanand 		ctx->pmblimitr_el1 = read_pmblimitr_el1();
130777f1f68SJayanth Dodderi Chidanand 	}
131777f1f68SJayanth Dodderi Chidanand 
132777f1f68SJayanth Dodderi Chidanand 	return NULL;
133777f1f68SJayanth Dodderi Chidanand }
134777f1f68SJayanth Dodderi Chidanand 
135777f1f68SJayanth Dodderi Chidanand static void *spe_context_restore(const void *arg)
136777f1f68SJayanth Dodderi Chidanand {
137777f1f68SJayanth Dodderi Chidanand 	unsigned int core_pos;
138777f1f68SJayanth Dodderi Chidanand 	struct spe_ctx *ctx;
139777f1f68SJayanth Dodderi Chidanand 
140777f1f68SJayanth Dodderi Chidanand 	if (is_feat_spe_supported()) {
141777f1f68SJayanth Dodderi Chidanand 		core_pos = plat_my_core_pos();
142777f1f68SJayanth Dodderi Chidanand 		ctx = &spe_ctxs[core_pos];
143777f1f68SJayanth Dodderi Chidanand 		write_pmblimitr_el1(ctx->pmblimitr_el1);
144777f1f68SJayanth Dodderi Chidanand 	}
145777f1f68SJayanth Dodderi Chidanand 
146777f1f68SJayanth Dodderi Chidanand 	return NULL;
147777f1f68SJayanth Dodderi Chidanand }
148777f1f68SJayanth Dodderi Chidanand 
149281a08ccSDimitris Papastamos SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook);
150777f1f68SJayanth Dodderi Chidanand 
151777f1f68SJayanth Dodderi Chidanand SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, spe_context_save);
152777f1f68SJayanth Dodderi Chidanand SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, spe_context_restore);
153