1 /*
2  * Copyright (c) 2021-2023, 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_init_el3(void)22 void trbe_init_el3(void)
23 {
24 	u_register_t val;
25 
26 	/*
27 	 * MDCR_EL3.NSTBE = 0b0
28 	 *  Trace Buffer owning Security state is Non-secure state. If FEAT_RME
29 	 *  is not implemented, this field is RES0.
30 	 *
31 	 * MDCR_EL3.NSTB = 0b11
32 	 *  Allow access of trace buffer control registers from NS-EL1 and
33 	 *  NS-EL2, tracing is prohibited in Secure and Realm state (if
34 	 *  implemented).
35 	 */
36 	val = read_mdcr_el3();
37 	val |= MDCR_NSTB(MDCR_NSTB_EL1);
38 	val &= ~(MDCR_NSTBE_BIT);
39 	write_mdcr_el3(val);
40 }
41 
trbe_init_el2_unused(void)42 void trbe_init_el2_unused(void)
43 {
44 	/*
45 	 * MDCR_EL2.E2TB: Set to zero so that the trace Buffer
46 	 *  owning exception level is NS-EL1 and, tracing is
47 	 *  prohibited at NS-EL2. These bits are RES0 when
48 	 *  FEAT_TRBE is not implemented.
49 	 */
50 	write_mdcr_el2(read_mdcr_el2() & ~MDCR_EL2_E2TB(MDCR_EL2_E2TB_EL1));
51 }
52 
trbe_drain_trace_buffers_hook(const void * arg __unused)53 static void *trbe_drain_trace_buffers_hook(const void *arg __unused)
54 {
55 	if (is_feat_trbe_supported()) {
56 		/*
57 		 * Before switching from normal world to secure world
58 		 * the trace buffers need to be drained out to memory. This is
59 		 * required to avoid an invalid memory access when TTBR is switched
60 		 * for entry to S-EL1.
61 		 */
62 		tsb_csync();
63 		dsbnsh();
64 	}
65 
66 	return (void *)0;
67 }
68 
69 SUBSCRIBE_TO_EVENT(cm_entering_secure_world, trbe_drain_trace_buffers_hook);
70