xref: /rk3399_ARM-atf/lib/extensions/spe/spe.c (revision 7fabe1a89903cab4919304faa085ee6eaaec5c9d)
1281a08ccSDimitris Papastamos /*
2*7fabe1a8SRoberto Vargas  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
3281a08ccSDimitris Papastamos  *
4281a08ccSDimitris Papastamos  * SPDX-License-Identifier: BSD-3-Clause
5281a08ccSDimitris Papastamos  */
6281a08ccSDimitris Papastamos 
7281a08ccSDimitris Papastamos #include <arch.h>
8281a08ccSDimitris Papastamos #include <arch_helpers.h>
9281a08ccSDimitris Papastamos #include <pubsub.h>
10*7fabe1a8SRoberto Vargas #include <spe.h>
11281a08ccSDimitris Papastamos 
12281a08ccSDimitris Papastamos /*
13281a08ccSDimitris Papastamos  * The assembler does not yet understand the psb csync mnemonic
14281a08ccSDimitris Papastamos  * so use the equivalent hint instruction.
15281a08ccSDimitris Papastamos  */
16281a08ccSDimitris Papastamos #define psb_csync()	asm volatile("hint #17")
17281a08ccSDimitris Papastamos 
18281a08ccSDimitris Papastamos void spe_enable(int el2_unused)
19281a08ccSDimitris Papastamos {
20281a08ccSDimitris Papastamos 	uint64_t features;
21281a08ccSDimitris Papastamos 
22281a08ccSDimitris Papastamos 	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
23281a08ccSDimitris Papastamos 	if ((features & ID_AA64DFR0_PMS_MASK) == 1) {
24281a08ccSDimitris Papastamos 		uint64_t v;
25281a08ccSDimitris Papastamos 
26281a08ccSDimitris Papastamos 		if (el2_unused) {
27281a08ccSDimitris Papastamos 			/*
28281a08ccSDimitris Papastamos 			 * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical
29281a08ccSDimitris Papastamos 			 * profiling controls to EL2.
30281a08ccSDimitris Papastamos 			 *
31281a08ccSDimitris Papastamos 			 * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure
32281a08ccSDimitris Papastamos 			 * state. Accesses to profiling buffer controls at
33281a08ccSDimitris Papastamos 			 * Non-secure EL1 are not trapped to EL2.
34281a08ccSDimitris Papastamos 			 */
35281a08ccSDimitris Papastamos 			v = read_mdcr_el2();
36281a08ccSDimitris Papastamos 			v &= ~MDCR_EL2_TPMS;
37281a08ccSDimitris Papastamos 			v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1);
38281a08ccSDimitris Papastamos 			write_mdcr_el2(v);
39281a08ccSDimitris Papastamos 		}
40281a08ccSDimitris Papastamos 
41281a08ccSDimitris Papastamos 		/*
42281a08ccSDimitris Papastamos 		 * MDCR_EL2.NSPB (ARM v8.2): SPE enabled in Non-secure state
43281a08ccSDimitris Papastamos 		 * and disabled in secure state. Accesses to SPE registers at
44281a08ccSDimitris Papastamos 		 * S-EL1 generate trap exceptions to EL3.
45281a08ccSDimitris Papastamos 		 */
46281a08ccSDimitris Papastamos 		v = read_mdcr_el3();
47281a08ccSDimitris Papastamos 		v |= MDCR_NSPB(MDCR_NSPB_EL1);
48281a08ccSDimitris Papastamos 		write_mdcr_el3(v);
49281a08ccSDimitris Papastamos 	}
50281a08ccSDimitris Papastamos }
51281a08ccSDimitris Papastamos 
52281a08ccSDimitris Papastamos void spe_disable(void)
53281a08ccSDimitris Papastamos {
54281a08ccSDimitris Papastamos 	uint64_t features;
55281a08ccSDimitris Papastamos 
56281a08ccSDimitris Papastamos 	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
57281a08ccSDimitris Papastamos 	if ((features & ID_AA64DFR0_PMS_MASK) == 1) {
58281a08ccSDimitris Papastamos 		uint64_t v;
59281a08ccSDimitris Papastamos 
60281a08ccSDimitris Papastamos 		/* Drain buffered data */
61281a08ccSDimitris Papastamos 		psb_csync();
62281a08ccSDimitris Papastamos 		dsbnsh();
63281a08ccSDimitris Papastamos 
64281a08ccSDimitris Papastamos 		/* Disable profiling buffer */
65281a08ccSDimitris Papastamos 		v = read_pmblimitr_el1();
66281a08ccSDimitris Papastamos 		v &= ~(1ULL << 0);
67281a08ccSDimitris Papastamos 		write_pmblimitr_el1(v);
68281a08ccSDimitris Papastamos 		isb();
69281a08ccSDimitris Papastamos 	}
70281a08ccSDimitris Papastamos }
71281a08ccSDimitris Papastamos 
72281a08ccSDimitris Papastamos static void *spe_drain_buffers_hook(const void *arg)
73281a08ccSDimitris Papastamos {
74281a08ccSDimitris Papastamos 	uint64_t features;
75281a08ccSDimitris Papastamos 
76281a08ccSDimitris Papastamos 	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT;
77281a08ccSDimitris Papastamos 	if ((features & ID_AA64DFR0_PMS_MASK) == 1) {
78281a08ccSDimitris Papastamos 		/* Drain buffered data */
79281a08ccSDimitris Papastamos 		psb_csync();
80281a08ccSDimitris Papastamos 		dsbnsh();
81281a08ccSDimitris Papastamos 	}
82281a08ccSDimitris Papastamos 
83281a08ccSDimitris Papastamos 	return 0;
84281a08ccSDimitris Papastamos }
85281a08ccSDimitris Papastamos 
86281a08ccSDimitris Papastamos SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook);
87