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