1281a08ccSDimitris Papastamos /* 2*777f1f68SJayanth 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 15*777f1f68SJayanth Dodderi Chidanand #include <plat/common/platform.h> 16*777f1f68SJayanth Dodderi Chidanand 17*777f1f68SJayanth Dodderi Chidanand typedef struct spe_ctx { 18*777f1f68SJayanth Dodderi Chidanand u_register_t pmblimitr_el1; 19*777f1f68SJayanth Dodderi Chidanand } spe_ctx_t; 20*777f1f68SJayanth Dodderi Chidanand 21*777f1f68SJayanth Dodderi Chidanand static struct spe_ctx spe_ctxs[PLATFORM_CORE_COUNT]; 22*777f1f68SJayanth 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 3260d330dcSBoyan Karatotev void spe_init_el3(void) 332ff8fbf3SDimitris Papastamos { 34281a08ccSDimitris Papastamos uint64_t v; 35281a08ccSDimitris Papastamos 36281a08ccSDimitris Papastamos /* 3799506facSBoyan Karatotev * MDCR_EL3.NSPB (ARM v8.2): SPE enabled in Non-secure state 38281a08ccSDimitris Papastamos * and disabled in secure state. Accesses to SPE registers at 39281a08ccSDimitris Papastamos * S-EL1 generate trap exceptions to EL3. 40f20eb893SManish V Badarkhe * 4199506facSBoyan Karatotev * MDCR_EL3.NSPBE: Profiling Buffer uses Non-secure Virtual Addresses. 4299506facSBoyan Karatotev * When FEAT_RME is not implemented, this field is RES0. 4399506facSBoyan Karatotev * 44f20eb893SManish V Badarkhe * MDCR_EL3.EnPMSN (ARM v8.7): Do not trap access to PMSNEVFR_EL1 45f20eb893SManish V Badarkhe * register at NS-EL1 or NS-EL2 to EL3 if FEAT_SPEv1p2 is implemented. 46f20eb893SManish V Badarkhe * Setting this bit to 1 doesn't have any effect on it when 47f20eb893SManish V Badarkhe * FEAT_SPEv1p2 not implemented. 48281a08ccSDimitris Papastamos */ 49281a08ccSDimitris Papastamos v = read_mdcr_el3(); 50f20eb893SManish V Badarkhe v |= MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT; 5199506facSBoyan Karatotev v &= ~(MDCR_NSPBE_BIT); 52281a08ccSDimitris Papastamos write_mdcr_el3(v); 53281a08ccSDimitris Papastamos } 54281a08ccSDimitris Papastamos 5560d330dcSBoyan Karatotev void spe_init_el2_unused(void) 5660d330dcSBoyan Karatotev { 5760d330dcSBoyan Karatotev uint64_t v; 5860d330dcSBoyan Karatotev 5960d330dcSBoyan Karatotev /* 6060d330dcSBoyan Karatotev * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical 6160d330dcSBoyan Karatotev * profiling controls to EL2. 6260d330dcSBoyan Karatotev * 6360d330dcSBoyan Karatotev * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure 6460d330dcSBoyan Karatotev * state. Accesses to profiling buffer controls at 6560d330dcSBoyan Karatotev * Non-secure EL1 are not trapped to EL2. 6660d330dcSBoyan Karatotev */ 6760d330dcSBoyan Karatotev v = read_mdcr_el2(); 6860d330dcSBoyan Karatotev v &= ~MDCR_EL2_TPMS; 6960d330dcSBoyan Karatotev v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1); 7060d330dcSBoyan Karatotev write_mdcr_el2(v); 7160d330dcSBoyan Karatotev } 7260d330dcSBoyan Karatotev 73281a08ccSDimitris Papastamos void spe_disable(void) 74281a08ccSDimitris Papastamos { 75281a08ccSDimitris Papastamos uint64_t v; 76281a08ccSDimitris Papastamos 77281a08ccSDimitris Papastamos /* Drain buffered data */ 78281a08ccSDimitris Papastamos psb_csync(); 79281a08ccSDimitris Papastamos dsbnsh(); 80281a08ccSDimitris Papastamos 81281a08ccSDimitris Papastamos /* Disable profiling buffer */ 82281a08ccSDimitris Papastamos v = read_pmblimitr_el1(); 83281a08ccSDimitris Papastamos v &= ~(1ULL << 0); 84281a08ccSDimitris Papastamos write_pmblimitr_el1(v); 85281a08ccSDimitris Papastamos isb(); 86281a08ccSDimitris Papastamos } 87281a08ccSDimitris Papastamos 88281a08ccSDimitris Papastamos static void *spe_drain_buffers_hook(const void *arg) 89281a08ccSDimitris Papastamos { 906437a09aSAndre Przywara if (!is_feat_spe_supported()) 912ff8fbf3SDimitris Papastamos return (void *)-1; 92281a08ccSDimitris Papastamos 93281a08ccSDimitris Papastamos /* Drain buffered data */ 94281a08ccSDimitris Papastamos psb_csync(); 95281a08ccSDimitris Papastamos dsbnsh(); 9640daecc1SAntonio Nino Diaz 9740daecc1SAntonio Nino Diaz return (void *)0; 98281a08ccSDimitris Papastamos } 99281a08ccSDimitris Papastamos 100*777f1f68SJayanth Dodderi Chidanand static void *spe_context_save(const void *arg) 101*777f1f68SJayanth Dodderi Chidanand { 102*777f1f68SJayanth Dodderi Chidanand unsigned int core_pos; 103*777f1f68SJayanth Dodderi Chidanand struct spe_ctx *ctx; 104*777f1f68SJayanth Dodderi Chidanand 105*777f1f68SJayanth Dodderi Chidanand if (is_feat_spe_supported()) { 106*777f1f68SJayanth Dodderi Chidanand core_pos = plat_my_core_pos(); 107*777f1f68SJayanth Dodderi Chidanand ctx = &spe_ctxs[core_pos]; 108*777f1f68SJayanth Dodderi Chidanand ctx->pmblimitr_el1 = read_pmblimitr_el1(); 109*777f1f68SJayanth Dodderi Chidanand } 110*777f1f68SJayanth Dodderi Chidanand 111*777f1f68SJayanth Dodderi Chidanand return NULL; 112*777f1f68SJayanth Dodderi Chidanand } 113*777f1f68SJayanth Dodderi Chidanand 114*777f1f68SJayanth Dodderi Chidanand static void *spe_context_restore(const void *arg) 115*777f1f68SJayanth Dodderi Chidanand { 116*777f1f68SJayanth Dodderi Chidanand unsigned int core_pos; 117*777f1f68SJayanth Dodderi Chidanand struct spe_ctx *ctx; 118*777f1f68SJayanth Dodderi Chidanand 119*777f1f68SJayanth Dodderi Chidanand if (is_feat_spe_supported()) { 120*777f1f68SJayanth Dodderi Chidanand core_pos = plat_my_core_pos(); 121*777f1f68SJayanth Dodderi Chidanand ctx = &spe_ctxs[core_pos]; 122*777f1f68SJayanth Dodderi Chidanand write_pmblimitr_el1(ctx->pmblimitr_el1); 123*777f1f68SJayanth Dodderi Chidanand } 124*777f1f68SJayanth Dodderi Chidanand 125*777f1f68SJayanth Dodderi Chidanand return NULL; 126*777f1f68SJayanth Dodderi Chidanand } 127*777f1f68SJayanth Dodderi Chidanand 128281a08ccSDimitris Papastamos SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook); 129*777f1f68SJayanth Dodderi Chidanand 130*777f1f68SJayanth Dodderi Chidanand SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, spe_context_save); 131*777f1f68SJayanth Dodderi Chidanand SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, spe_context_restore); 132