xref: /rk3399_ARM-atf/lib/extensions/spe/spe.c (revision 2ff8fbf3b0d1403afab9b5316fd7ea40859c889c)
1 /*
2  * Copyright (c) 2017-2018, 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 int spe_supported(void)
18 {
19 	uint64_t features;
20 
21 	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
22 	return (features & ID_AA64DFR0_PMS_MASK) == 1;
23 }
24 
25 void spe_enable(int el2_unused)
26 {
27 	uint64_t v;
28 
29 	if (!spe_supported())
30 		return;
31 
32 	if (el2_unused) {
33 		/*
34 		 * 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.
40 		 */
41 		v = read_mdcr_el2();
42 		v &= ~MDCR_EL2_TPMS;
43 		v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
44 		write_mdcr_el2(v);
45 	}
46 
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);
55 }
56 
57 void spe_disable(void)
58 {
59 	uint64_t v;
60 
61 	if (!spe_supported())
62 		return;
63 
64 	/* Drain buffered data */
65 	psb_csync();
66 	dsbnsh();
67 
68 	/* Disable profiling buffer */
69 	v = read_pmblimitr_el1();
70 	v &= ~(1ULL << 0);
71 	write_pmblimitr_el1(v);
72 	isb();
73 }
74 
75 static void *spe_drain_buffers_hook(const void *arg)
76 {
77 	if (!spe_supported())
78 		return (void *)-1;
79 
80 	/* Drain buffered data */
81 	psb_csync();
82 	dsbnsh();
83 	return 0;
84 }
85 
86 SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook);
87