blob: 716cd649daa89dc681b0f500d7f2b63e5b15cdb6 [file] [log] [blame]
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +01001/*
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +00002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +01003 *
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
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000017int spe_supported(void)
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010018{
19 uint64_t features;
20
21 features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000022 return (features & ID_AA64DFR0_PMS_MASK) == 1;
23}
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010024
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000025void spe_enable(int el2_unused)
26{
27 uint64_t v;
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010028
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000029 if (!spe_supported())
30 return;
31
32 if (el2_unused) {
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010033 /*
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000034 * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
35 * profiling controls to EL2.
36 *
37 * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
38 * state. Accesses to profiling buffer controls at
39 * Non-secure EL1 are not trapped to EL2.
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010040 */
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000041 v = read_mdcr_el2();
42 v &= ~MDCR_EL2_TPMS;
43 v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
44 write_mdcr_el2(v);
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010045 }
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000046
47 /*
48 * MDCR_EL2.NSPB (ARM v8.2): SPE enabled in Non-secure state
49 * and disabled in secure state. Accesses to SPE registers at
50 * S-EL1 generate trap exceptions to EL3.
51 */
52 v = read_mdcr_el3();
53 v |= MDCR_NSPB(MDCR_NSPB_EL1);
54 write_mdcr_el3(v);
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010055}
56
57void spe_disable(void)
58{
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000059 uint64_t v;
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010060
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000061 if (!spe_supported())
62 return;
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010063
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000064 /* Drain buffered data */
65 psb_csync();
66 dsbnsh();
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010067
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000068 /* Disable profiling buffer */
69 v = read_pmblimitr_el1();
70 v &= ~(1ULL << 0);
71 write_pmblimitr_el1(v);
72 isb();
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010073}
74
75static void *spe_drain_buffers_hook(const void *arg)
76{
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000077 if (!spe_supported())
78 return (void *)-1;
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010079
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000080 /* Drain buffered data */
81 psb_csync();
82 dsbnsh();
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010083 return 0;
84}
85
86SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook);