blob: eeae0a718202b023f971c2c41343208fed041edf [file] [log] [blame]
Manish V Badarkhe813524e2021-07-02 09:10:56 +01001/*
Boyan Karatotevfc7dca72024-12-16 16:23:26 +00002 * Copyright (c) 2021-2025, Arm Limited. All rights reserved.
Manish V Badarkhe813524e2021-07-02 09:10:56 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch.h>
Jayanth Dodderi Chidanand47c681b2022-05-19 14:08:28 +01008#include <arch_features.h>
Manish V Badarkhe813524e2021-07-02 09:10:56 +01009#include <arch_helpers.h>
Manish V Badarkhe813524e2021-07-02 09:10:56 +010010#include <lib/extensions/trbe.h>
11
Boyan Karatotev985b6a62025-07-17 09:38:19 +010012
13/*
14 * TRBE is an unusual feature. Its enable is split into two:
15 * - (NSTBE, NSTB[0]) - the security state bits - determines which security
16 * state owns the trace buffer.
17 * - NSTB[1] - the enable bit - determines if the security state that owns the
18 * buffer may access TRBE registers.
19 *
20 * There is a secondary id register TRBIDR_EL1 that is more granular than
21 * ID_AA64DFR0_EL1. When a security state owns the buffer, TRBIDR_EL1.P will
22 * report that TRBE programming is allowed. This means that the usual assumption
23 * that leaving all bits to a default of zero will disable the feature may not
24 * work correctly. To correctly disable TRBE, the current security state must NOT
25 * own the buffer, irrespective of the enable bit. Then, to play nicely with
26 * SMCCC_ARCH_FEATURE_AVAILABILITY, the enable bit should correspond to the
27 * enable status. The feature is architected this way to allow for lazy context
28 * switching of the buffer - a world can be made owner of the buffer (with
29 * TRBIDR_EL1.P reporting full access) without giving it access to the registers
30 * (by trapping to EL3). Then context switching can be deferred until a world
31 * tries to use TRBE at which point access can be given and the trapping
32 * instruction repeated.
33 *
34 * This can be simplified to the following rules:
35 * 1. To enable TRBE for world X:
36 * * world X owns the buffer ((NSTBE, NSTB[0]) == SCR_EL3.{NSE, NS})
37 * * trapping disabled (NSTB[0] == 1)
38 * 2. To disable TRBE for world X:
39 * * world X does not own the buffer ((NSTBE, NSTB[0]) != SCR_EL3.{NSE, NS})
40 * * trapping enabled (NSTB[0] == 0)
41 */
42void trbe_enable_ns(cpu_context_t *ctx)
Manish V Badarkhe813524e2021-07-02 09:10:56 +010043{
Jayanth Dodderi Chidanand123002f2024-06-18 15:22:54 +010044 el3_state_t *state = get_el3state_ctx(ctx);
45 u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
Manish V Badarkhe813524e2021-07-02 09:10:56 +010046
Boyan Karatotev985b6a62025-07-17 09:38:19 +010047 mdcr_el3_val |= MDCR_NSTB_EN_BIT | MDCR_NSTB_SS_BIT;
Jayanth Dodderi Chidanand123002f2024-06-18 15:22:54 +010048 mdcr_el3_val &= ~(MDCR_NSTBE_BIT);
Boyan Karatotev985b6a62025-07-17 09:38:19 +010049
Jayanth Dodderi Chidanand123002f2024-06-18 15:22:54 +010050 write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
Manish V Badarkhe813524e2021-07-02 09:10:56 +010051}
52
Boyan Karatotev985b6a62025-07-17 09:38:19 +010053static void trbe_disable_all(cpu_context_t *ctx, bool ns)
Arvind Ram Prakashb36e9752024-07-19 11:39:49 -050054{
55 el3_state_t *state = get_el3state_ctx(ctx);
56 u_register_t mdcr_el3_val = read_ctx_reg(state, CTX_MDCR_EL3);
57
Boyan Karatotev985b6a62025-07-17 09:38:19 +010058 mdcr_el3_val &= ~MDCR_NSTB_EN_BIT;
59 mdcr_el3_val &= ~MDCR_NSTBE_BIT;
60
61 /* make NS owner, except when NS is running */
62 if (ns) {
63 mdcr_el3_val &= ~MDCR_NSTB_SS_BIT;
64 } else {
65 mdcr_el3_val |= MDCR_NSTB_SS_BIT;
66 }
67
Arvind Ram Prakashb36e9752024-07-19 11:39:49 -050068 write_ctx_reg(state, CTX_MDCR_EL3, mdcr_el3_val);
69}
70
Boyan Karatotev985b6a62025-07-17 09:38:19 +010071
72void trbe_disable_ns(cpu_context_t *ctx)
73{
74 trbe_disable_all(ctx, true);
75}
76
77void trbe_disable_secure(cpu_context_t *ctx)
78{
79 trbe_disable_all(ctx, false);
80}
81
82void trbe_disable_realm(cpu_context_t *ctx)
83{
84 trbe_disable_all(ctx, false);
85}
86
87
Boyan Karatotev60d330d2023-02-16 15:12:45 +000088void trbe_init_el2_unused(void)
89{
90 /*
91 * MDCR_EL2.E2TB: Set to zero so that the trace Buffer
92 * owning exception level is NS-EL1 and, tracing is
93 * prohibited at NS-EL2. These bits are RES0 when
94 * FEAT_TRBE is not implemented.
95 */
96 write_mdcr_el2(read_mdcr_el2() & ~MDCR_EL2_E2TB(MDCR_EL2_E2TB_EL1));
97}