1281a08ccSDimitris Papastamos /* 2*60d330dcSBoyan Karatotev * Copyright (c) 2017-2023, 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 1540daecc1SAntonio Nino Diaz static inline void psb_csync(void) 1640daecc1SAntonio Nino Diaz { 17281a08ccSDimitris Papastamos /* 18281a08ccSDimitris Papastamos * The assembler does not yet understand the psb csync mnemonic 19281a08ccSDimitris Papastamos * so use the equivalent hint instruction. 20281a08ccSDimitris Papastamos */ 2140daecc1SAntonio Nino Diaz __asm__ volatile("hint #17"); 2240daecc1SAntonio Nino Diaz } 23281a08ccSDimitris Papastamos 24*60d330dcSBoyan Karatotev void spe_init_el3(void) 252ff8fbf3SDimitris Papastamos { 26281a08ccSDimitris Papastamos uint64_t v; 27281a08ccSDimitris Papastamos 28281a08ccSDimitris Papastamos /* 29281a08ccSDimitris Papastamos * MDCR_EL2.NSPB (ARM v8.2): SPE enabled in Non-secure state 30281a08ccSDimitris Papastamos * and disabled in secure state. Accesses to SPE registers at 31281a08ccSDimitris Papastamos * S-EL1 generate trap exceptions to EL3. 32f20eb893SManish V Badarkhe * 33f20eb893SManish V Badarkhe * MDCR_EL3.EnPMSN (ARM v8.7): Do not trap access to PMSNEVFR_EL1 34f20eb893SManish V Badarkhe * register at NS-EL1 or NS-EL2 to EL3 if FEAT_SPEv1p2 is implemented. 35f20eb893SManish V Badarkhe * Setting this bit to 1 doesn't have any effect on it when 36f20eb893SManish V Badarkhe * FEAT_SPEv1p2 not implemented. 37281a08ccSDimitris Papastamos */ 38281a08ccSDimitris Papastamos v = read_mdcr_el3(); 39f20eb893SManish V Badarkhe v |= MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT; 40281a08ccSDimitris Papastamos write_mdcr_el3(v); 41281a08ccSDimitris Papastamos } 42281a08ccSDimitris Papastamos 43*60d330dcSBoyan Karatotev void spe_init_el2_unused(void) 44*60d330dcSBoyan Karatotev { 45*60d330dcSBoyan Karatotev uint64_t v; 46*60d330dcSBoyan Karatotev 47*60d330dcSBoyan Karatotev /* 48*60d330dcSBoyan Karatotev * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical 49*60d330dcSBoyan Karatotev * profiling controls to EL2. 50*60d330dcSBoyan Karatotev * 51*60d330dcSBoyan Karatotev * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure 52*60d330dcSBoyan Karatotev * state. Accesses to profiling buffer controls at 53*60d330dcSBoyan Karatotev * Non-secure EL1 are not trapped to EL2. 54*60d330dcSBoyan Karatotev */ 55*60d330dcSBoyan Karatotev v = read_mdcr_el2(); 56*60d330dcSBoyan Karatotev v &= ~MDCR_EL2_TPMS; 57*60d330dcSBoyan Karatotev v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1); 58*60d330dcSBoyan Karatotev write_mdcr_el2(v); 59*60d330dcSBoyan Karatotev } 60*60d330dcSBoyan Karatotev 61281a08ccSDimitris Papastamos void spe_disable(void) 62281a08ccSDimitris Papastamos { 63281a08ccSDimitris Papastamos uint64_t v; 64281a08ccSDimitris Papastamos 65281a08ccSDimitris Papastamos /* Drain buffered data */ 66281a08ccSDimitris Papastamos psb_csync(); 67281a08ccSDimitris Papastamos dsbnsh(); 68281a08ccSDimitris Papastamos 69281a08ccSDimitris Papastamos /* Disable profiling buffer */ 70281a08ccSDimitris Papastamos v = read_pmblimitr_el1(); 71281a08ccSDimitris Papastamos v &= ~(1ULL << 0); 72281a08ccSDimitris Papastamos write_pmblimitr_el1(v); 73281a08ccSDimitris Papastamos isb(); 74281a08ccSDimitris Papastamos } 75281a08ccSDimitris Papastamos 76281a08ccSDimitris Papastamos static void *spe_drain_buffers_hook(const void *arg) 77281a08ccSDimitris Papastamos { 786437a09aSAndre Przywara if (!is_feat_spe_supported()) 792ff8fbf3SDimitris Papastamos return (void *)-1; 80281a08ccSDimitris Papastamos 81281a08ccSDimitris Papastamos /* Drain buffered data */ 82281a08ccSDimitris Papastamos psb_csync(); 83281a08ccSDimitris Papastamos dsbnsh(); 8440daecc1SAntonio Nino Diaz 8540daecc1SAntonio Nino Diaz return (void *)0; 86281a08ccSDimitris Papastamos } 87281a08ccSDimitris Papastamos 88281a08ccSDimitris Papastamos SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook); 89