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