xref: /rk3399_ARM-atf/lib/extensions/spe/spe.c (revision 985b6a6bc84745f1423f851c86037a15fe1ac39c)
1281a08ccSDimitris Papastamos /*
2fc7dca72SBoyan Karatotev  * Copyright (c) 2017-2025, 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/extensions/spe.h>
13281a08ccSDimitris Papastamos 
14777f1f68SJayanth Dodderi Chidanand #include <plat/common/platform.h>
15777f1f68SJayanth Dodderi Chidanand 
16*985b6a6bSBoyan Karatotev /*
17*985b6a6bSBoyan Karatotev  * SPE is an unusual feature. Its enable is split into two:
18*985b6a6bSBoyan Karatotev  *  - (NSPBE, NSPB[0]) - the security state bits - determines which security
19*985b6a6bSBoyan Karatotev  *    state owns the profiling buffer.
20*985b6a6bSBoyan Karatotev  *  - NSPB[1] - the enable bit - determines if the security state that owns the
21*985b6a6bSBoyan Karatotev  *    buffer may access SPE registers.
22*985b6a6bSBoyan Karatotev  *
23*985b6a6bSBoyan Karatotev  * There is a secondary id register PMBIDR_EL1 that is more granular than
24*985b6a6bSBoyan Karatotev  * ID_AA64DFR0_EL1. When a security state owns the buffer, PMBIDR_EL1.P will
25*985b6a6bSBoyan Karatotev  * report that SPE programming is allowed. This means that the usual assumption
26*985b6a6bSBoyan Karatotev  * that leaving all bits to a default of zero will disable the feature may not
27*985b6a6bSBoyan Karatotev  * work correctly. To correctly disable SPE, the current security state must NOT
28*985b6a6bSBoyan Karatotev  * own the buffer, irrespective of the enable bit. Then, to play nicely with
29*985b6a6bSBoyan Karatotev  * SMCCC_ARCH_FEATURE_AVAILABILITY, the enable bit should correspond to the
30*985b6a6bSBoyan Karatotev  * enable status. The feature is architected this way to allow for lazy context
31*985b6a6bSBoyan Karatotev  * switching of the buffer - a world can be made owner of the buffer (with
32*985b6a6bSBoyan Karatotev  * PMBIDR_EL1.P reporting full access) without giving it access to the registers
33*985b6a6bSBoyan Karatotev  * (by trapping to EL3). Then context switching can be deferred until a world
34*985b6a6bSBoyan Karatotev  * tries to use SPE at which point access can be given and the trapping
35*985b6a6bSBoyan Karatotev  * instruction repeated.
36*985b6a6bSBoyan Karatotev  *
37*985b6a6bSBoyan Karatotev  * This can be simplified to the following rules:
38*985b6a6bSBoyan Karatotev  * 1. To enable SPE for world X:
39*985b6a6bSBoyan Karatotev  *    * world X owns the buffer ((NSPBE, NSPB[0]) == SCR_EL3.{NSE, NS})
40*985b6a6bSBoyan Karatotev  *    * trapping disabled (NSPB[0] == 1)
41*985b6a6bSBoyan Karatotev  * 2. To disable SPE for world X:
42*985b6a6bSBoyan Karatotev  *    * world X does not own the buffer ((NSPBE, NSPB[0]) != SCR_EL3.{NSE, NS})
43*985b6a6bSBoyan Karatotev  *    * trapping enabled (NSPB[0] == 0)
44*985b6a6bSBoyan Karatotev  */
45*985b6a6bSBoyan Karatotev 
46*985b6a6bSBoyan Karatotev /*
47*985b6a6bSBoyan Karatotev  * MDCR_EL3.EnPMSN (ARM v8.7) and MDCR_EL3.EnPMS3: Do not trap access to
48*985b6a6bSBoyan Karatotev  * PMSNEVFR_EL1 or PMSDSFR_EL1 register at NS-EL1 or NS-EL2 to EL3 if
49*985b6a6bSBoyan Karatotev  * FEAT_SPEv1p2 or FEAT_SPE_FDS are implemented. Setting these bits to 1 doesn't
50*985b6a6bSBoyan Karatotev  * have any effect on it when the features aren't implemented.
51*985b6a6bSBoyan Karatotev  */
52*985b6a6bSBoyan Karatotev void spe_enable_ns(cpu_context_t *ctx)
532ff8fbf3SDimitris Papastamos {
54123002f9SJayanth Dodderi Chidanand 	el3_state_t *state = get_el3state_ctx(ctx);
55123002f9SJayanth Dodderi Chidanand 	u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
56281a08ccSDimitris Papastamos 
57*985b6a6bSBoyan Karatotev 	mdcr_el3_val |= MDCR_NSPB_EN_BIT | MDCR_NSPB_SS_BIT | MDCR_EnPMSN_BIT | MDCR_EnPMS3_BIT;
58123002f9SJayanth Dodderi Chidanand 	mdcr_el3_val &= ~(MDCR_NSPBE_BIT);
59*985b6a6bSBoyan Karatotev 
60123002f9SJayanth Dodderi Chidanand 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
61281a08ccSDimitris Papastamos }
62281a08ccSDimitris Papastamos 
63*985b6a6bSBoyan Karatotev /*
64*985b6a6bSBoyan Karatotev  * MDCR_EL3.EnPMSN (ARM v8.7) and MDCR_EL3.EnPMS3: Clear the bits to trap access
65*985b6a6bSBoyan Karatotev  * of PMSNEVFR_EL1 and PMSDSFR_EL1 from EL2/EL1 to EL3.
66*985b6a6bSBoyan Karatotev  */
67*985b6a6bSBoyan Karatotev static void spe_disable_others(cpu_context_t *ctx)
68651fe507SManish Pandey {
69651fe507SManish Pandey 	el3_state_t *state = get_el3state_ctx(ctx);
70651fe507SManish Pandey 	u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
71651fe507SManish Pandey 
72*985b6a6bSBoyan Karatotev 	mdcr_el3_val |= MDCR_NSPB_SS_BIT;
73*985b6a6bSBoyan Karatotev 	mdcr_el3_val &= ~(MDCR_NSPB_EN_BIT | MDCR_NSPBE_BIT | MDCR_EnPMSN_BIT |
744fd9814fSJames Clark 			  MDCR_EnPMS3_BIT);
75651fe507SManish Pandey 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
76651fe507SManish Pandey }
77651fe507SManish Pandey 
78*985b6a6bSBoyan Karatotev void spe_disable_secure(cpu_context_t *ctx)
79*985b6a6bSBoyan Karatotev {
80*985b6a6bSBoyan Karatotev 	spe_disable_others(ctx);
81*985b6a6bSBoyan Karatotev }
82*985b6a6bSBoyan Karatotev 
83*985b6a6bSBoyan Karatotev void spe_disable_realm(cpu_context_t *ctx)
84*985b6a6bSBoyan Karatotev {
85*985b6a6bSBoyan Karatotev 	spe_disable_others(ctx);
86*985b6a6bSBoyan Karatotev }
87*985b6a6bSBoyan Karatotev 
8860d330dcSBoyan Karatotev void spe_init_el2_unused(void)
8960d330dcSBoyan Karatotev {
9060d330dcSBoyan Karatotev 	uint64_t v;
9160d330dcSBoyan Karatotev 
9260d330dcSBoyan Karatotev 	/*
9360d330dcSBoyan Karatotev 	 * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
9460d330dcSBoyan Karatotev 	 * profiling controls to EL2.
9560d330dcSBoyan Karatotev 	 *
9660d330dcSBoyan Karatotev 	 * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
9760d330dcSBoyan Karatotev 	 * state. Accesses to profiling buffer controls at
9860d330dcSBoyan Karatotev 	 * Non-secure EL1 are not trapped to EL2.
9960d330dcSBoyan Karatotev 	 */
10060d330dcSBoyan Karatotev 	v = read_mdcr_el2();
10160d330dcSBoyan Karatotev 	v &= ~MDCR_EL2_TPMS;
10260d330dcSBoyan Karatotev 	v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
10360d330dcSBoyan Karatotev 	write_mdcr_el2(v);
10460d330dcSBoyan Karatotev }
105