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