xref: /rk3399_ARM-atf/lib/extensions/spe/spe.c (revision 4fd9814f4865efdffca17b7bbfc8d4bd244866f3)
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 
16123002f9SJayanth Dodderi Chidanand void spe_enable(cpu_context_t *ctx)
172ff8fbf3SDimitris Papastamos {
18123002f9SJayanth Dodderi Chidanand 	el3_state_t *state = get_el3state_ctx(ctx);
19123002f9SJayanth Dodderi Chidanand 	u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
20281a08ccSDimitris Papastamos 
21281a08ccSDimitris Papastamos 	/*
2299506facSBoyan Karatotev 	 * MDCR_EL3.NSPB (ARM v8.2): SPE enabled in Non-secure state
23281a08ccSDimitris Papastamos 	 * and disabled in secure state. Accesses to SPE registers at
24281a08ccSDimitris Papastamos 	 * S-EL1 generate trap exceptions to EL3.
25f20eb893SManish V Badarkhe 	 *
2699506facSBoyan Karatotev 	 * MDCR_EL3.NSPBE: Profiling Buffer uses Non-secure Virtual Addresses.
2799506facSBoyan Karatotev 	 * When FEAT_RME is not implemented, this field is RES0.
2899506facSBoyan Karatotev 	 *
29*4fd9814fSJames Clark 	 * MDCR_EL3.EnPMSN (ARM v8.7) and MDCR_EL3.EnPMS3: Do not trap access to
30*4fd9814fSJames Clark 	 * PMSNEVFR_EL1 or PMSDSFR_EL1 register at NS-EL1 or NS-EL2 to EL3 if FEAT_SPEv1p2
31*4fd9814fSJames Clark 	 * or FEAT_SPE_FDS are implemented. Setting these bits to 1 doesn't have any
32*4fd9814fSJames Clark 	 * effect on it when the features aren't implemented.
33281a08ccSDimitris Papastamos 	 */
34*4fd9814fSJames Clark 	mdcr_el3_val |= MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT | MDCR_EnPMS3_BIT;
35123002f9SJayanth Dodderi Chidanand 	mdcr_el3_val &= ~(MDCR_NSPBE_BIT);
36123002f9SJayanth Dodderi Chidanand 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
37281a08ccSDimitris Papastamos }
38281a08ccSDimitris Papastamos 
39651fe507SManish Pandey void spe_disable(cpu_context_t *ctx)
40651fe507SManish Pandey {
41651fe507SManish Pandey 	el3_state_t *state = get_el3state_ctx(ctx);
42651fe507SManish Pandey 	u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
43651fe507SManish Pandey 
44651fe507SManish Pandey 	/*
4513f4a252SBoyan Karatotev 	 * MDCR_EL3.{NSPB,NSPBE} = 0b00, 0b0
4613f4a252SBoyan Karatotev 	 *  Disable access of profiling buffer control registers from lower ELs
4713f4a252SBoyan Karatotev 	 *  in any security state. Secure state owns the buffer.
48651fe507SManish Pandey 	 *
49*4fd9814fSJames Clark 	 * MDCR_EL3.EnPMSN (ARM v8.7) and MDCR_EL3.EnPMS3: Clear the bits to trap access
50*4fd9814fSJames Clark 	 * of PMSNEVFR_EL1 and PMSDSFR_EL1 from EL2/EL1 to EL3.
51651fe507SManish Pandey 	 */
52*4fd9814fSJames Clark 	mdcr_el3_val &= ~(MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_NSPBE_BIT | MDCR_EnPMSN_BIT |
53*4fd9814fSJames Clark 			  MDCR_EnPMS3_BIT);
54651fe507SManish Pandey 	write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
55651fe507SManish Pandey }
56651fe507SManish Pandey 
5760d330dcSBoyan Karatotev void spe_init_el2_unused(void)
5860d330dcSBoyan Karatotev {
5960d330dcSBoyan Karatotev 	uint64_t v;
6060d330dcSBoyan Karatotev 
6160d330dcSBoyan Karatotev 	/*
6260d330dcSBoyan Karatotev 	 * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
6360d330dcSBoyan Karatotev 	 * profiling controls to EL2.
6460d330dcSBoyan Karatotev 	 *
6560d330dcSBoyan Karatotev 	 * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
6660d330dcSBoyan Karatotev 	 * state. Accesses to profiling buffer controls at
6760d330dcSBoyan Karatotev 	 * Non-secure EL1 are not trapped to EL2.
6860d330dcSBoyan Karatotev 	 */
6960d330dcSBoyan Karatotev 	v = read_mdcr_el2();
7060d330dcSBoyan Karatotev 	v &= ~MDCR_EL2_TPMS;
7160d330dcSBoyan Karatotev 	v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
7260d330dcSBoyan Karatotev 	write_mdcr_el2(v);
7360d330dcSBoyan Karatotev }
74