blob: dc35840374da9798fc6780f7fb78ee7246db03f6 [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>
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
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000018int spe_supported(void)
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010019{
20 uint64_t features;
21
22 features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000023 return (features & ID_AA64DFR0_PMS_MASK) == 1;
24}
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010025
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000026void spe_enable(int el2_unused)
27{
28 uint64_t v;
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010029
Dimitris Papastamosaaa19852018-02-26 17:56:31 +000030 if (spe_supported() == 0)
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000031 return;
32
33 if (el2_unused) {
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010034 /*
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000035 * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
36 * profiling controls to EL2.
37 *
38 * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
39 * state. Accesses to profiling buffer controls at
40 * Non-secure EL1 are not trapped to EL2.
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010041 */
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000042 v = read_mdcr_el2();
43 v &= ~MDCR_EL2_TPMS;
44 v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
45 write_mdcr_el2(v);
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010046 }
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000047
48 /*
49 * MDCR_EL2.NSPB (ARM v8.2): SPE enabled in Non-secure state
50 * and disabled in secure state. Accesses to SPE registers at
51 * S-EL1 generate trap exceptions to EL3.
52 */
53 v = read_mdcr_el3();
54 v |= MDCR_NSPB(MDCR_NSPB_EL1);
55 write_mdcr_el3(v);
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010056}
57
58void spe_disable(void)
59{
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000060 uint64_t v;
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010061
Dimitris Papastamosaaa19852018-02-26 17:56:31 +000062 if (spe_supported() == 0)
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000063 return;
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010064
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000065 /* Drain buffered data */
66 psb_csync();
67 dsbnsh();
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010068
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000069 /* Disable profiling buffer */
70 v = read_pmblimitr_el1();
71 v &= ~(1ULL << 0);
72 write_pmblimitr_el1(v);
73 isb();
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010074}
75
76static void *spe_drain_buffers_hook(const void *arg)
77{
Dimitris Papastamosaaa19852018-02-26 17:56:31 +000078 if (spe_supported() == 0)
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000079 return (void *)-1;
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010080
Dimitris Papastamos5e8cd792018-02-19 14:52:19 +000081 /* Drain buffered data */
82 psb_csync();
83 dsbnsh();
Dimitris Papastamos5bdbb472017-10-13 12:06:06 +010084 return 0;
85}
86
87SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook);