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