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