1 /*
2  * Copyright (c) 2021, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch.h>
8 #include <arch_helpers.h>
9 #include <lib/el3_runtime/pubsub.h>
10 #include <lib/extensions/trbe.h>
11 
tsb_csync(void)12 static void tsb_csync(void)
13 {
14 	/*
15 	 * The assembler does not yet understand the tsb csync mnemonic
16 	 * so use the equivalent hint instruction.
17 	 */
18 	__asm__ volatile("hint #18");
19 }
20 
trbe_supported(void)21 static bool trbe_supported(void)
22 {
23 	uint64_t features;
24 
25 	features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEBUFFER_SHIFT;
26 	return ((features & ID_AA64DFR0_TRACEBUFFER_MASK) ==
27 		ID_AA64DFR0_TRACEBUFFER_SUPPORTED);
28 }
29 
trbe_enable(void)30 void trbe_enable(void)
31 {
32 	uint64_t val;
33 
34 	if (trbe_supported()) {
35 		/*
36 		 * MDCR_EL3.NSTB = 0b11
37 		 * Allow access of trace buffer control registers from NS-EL1
38 		 * and NS-EL2, tracing is prohibited in Secure and Realm state
39 		 * (if implemented).
40 		 */
41 		val = read_mdcr_el3();
42 		val |= MDCR_NSTB(MDCR_NSTB_EL1);
43 		write_mdcr_el3(val);
44 	}
45 }
46 
trbe_drain_trace_buffers_hook(const void * arg __unused)47 static void *trbe_drain_trace_buffers_hook(const void *arg __unused)
48 {
49 	if (trbe_supported()) {
50 		/*
51 		 * Before switching from normal world to secure world
52 		 * the trace buffers need to be drained out to memory. This is
53 		 * required to avoid an invalid memory access when TTBR is switched
54 		 * for entry to S-EL1.
55 		 */
56 		tsb_csync();
57 		dsbnsh();
58 	}
59 
60 	return (void *)0;
61 }
62 
63 SUBSCRIBE_TO_EVENT(cm_entering_secure_world, trbe_drain_trace_buffers_hook);
64