1 /* 2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch.h> 8 #include <arch_helpers.h> 9 #include <pubsub.h> 10 11 /* 12 * The assembler does not yet understand the psb csync mnemonic 13 * so use the equivalent hint instruction. 14 */ 15 #define psb_csync() asm volatile("hint #17") 16 17 void spe_enable(int el2_unused) 18 { 19 uint64_t features; 20 21 features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT; 22 if ((features & ID_AA64DFR0_PMS_MASK) == 1) { 23 uint64_t v; 24 25 if (el2_unused) { 26 /* 27 * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical 28 * profiling controls to EL2. 29 * 30 * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure 31 * state. Accesses to profiling buffer controls at 32 * Non-secure EL1 are not trapped to EL2. 33 */ 34 v = read_mdcr_el2(); 35 v &= ~MDCR_EL2_TPMS; 36 v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1); 37 write_mdcr_el2(v); 38 } 39 40 /* 41 * MDCR_EL2.NSPB (ARM v8.2): SPE enabled in Non-secure state 42 * and disabled in secure state. Accesses to SPE registers at 43 * S-EL1 generate trap exceptions to EL3. 44 */ 45 v = read_mdcr_el3(); 46 v |= MDCR_NSPB(MDCR_NSPB_EL1); 47 write_mdcr_el3(v); 48 } 49 } 50 51 void spe_disable(void) 52 { 53 uint64_t features; 54 55 features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT; 56 if ((features & ID_AA64DFR0_PMS_MASK) == 1) { 57 uint64_t v; 58 59 /* Drain buffered data */ 60 psb_csync(); 61 dsbnsh(); 62 63 /* Disable profiling buffer */ 64 v = read_pmblimitr_el1(); 65 v &= ~(1ULL << 0); 66 write_pmblimitr_el1(v); 67 isb(); 68 } 69 } 70 71 static void *spe_drain_buffers_hook(const void *arg) 72 { 73 uint64_t features; 74 75 features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT; 76 if ((features & ID_AA64DFR0_PMS_MASK) == 1) { 77 /* Drain buffered data */ 78 psb_csync(); 79 dsbnsh(); 80 } 81 82 return 0; 83 } 84 85 SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook); 86