feat(trbe): enable access to trace buffer control registers from lower NS EL

Introduced a build flag 'ENABLE_TRBE_FOR_NS' to enable trace buffer
control registers access in NS-EL2, or NS-EL1 (when NS-EL2 is
implemented but unused).

Change-Id: I285a672ccd395eebd377714c992bb21062a729cc
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
This commit is contained in:
Manish V Badarkhe 2021-07-02 09:10:56 +01:00
parent 40ff907470
commit 813524ea9d
8 changed files with 109 additions and 0 deletions

View File

@ -964,6 +964,7 @@ $(eval $(call assert_booleans,\
ENABLE_FEAT_RNG \ ENABLE_FEAT_RNG \
ENABLE_FEAT_SB \ ENABLE_FEAT_SB \
PSA_FWU_SUPPORT \ PSA_FWU_SUPPORT \
ENABLE_TRBE_FOR_NS \
))) )))
$(eval $(call assert_numerics,\ $(eval $(call assert_numerics,\
@ -1064,6 +1065,7 @@ $(eval $(call add_defines,\
NR_OF_FW_BANKS \ NR_OF_FW_BANKS \
NR_OF_IMAGES_IN_FW_BANK \ NR_OF_IMAGES_IN_FW_BANK \
PSA_FWU_SUPPORT \ PSA_FWU_SUPPORT \
ENABLE_TRBE_FOR_NS \
))) )))
ifeq (${SANITIZE_UB},trap) ifeq (${SANITIZE_UB},trap)

View File

@ -90,6 +90,10 @@ ifeq (${ENABLE_MPAM_FOR_LOWER_ELS},1)
BL31_SOURCES += lib/extensions/mpam/mpam.c BL31_SOURCES += lib/extensions/mpam/mpam.c
endif endif
ifeq (${ENABLE_TRBE_FOR_NS},1)
BL31_SOURCES += lib/extensions/trbe/trbe.c
endif
ifeq (${WORKAROUND_CVE_2017_5715},1) ifeq (${WORKAROUND_CVE_2017_5715},1)
BL31_SOURCES += lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S \ BL31_SOURCES += lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S \
lib/cpus/aarch64/wa_cve_2017_5715_mmu.S lib/cpus/aarch64/wa_cve_2017_5715_mmu.S

View File

@ -775,6 +775,12 @@ Common build options
functions that wait for an arbitrary time length (udelay and mdelay). The functions that wait for an arbitrary time length (udelay and mdelay). The
default value is 0. default value is 0.
- ``ENABLE_TRBE_FOR_NS``: This flag is used to enable access of trace buffer
control registers from NS ELs, NS-EL2 or NS-EL1(when NS-EL2 is implemented
but unused) when FEAT_TRBE is implemented. TRBE is an optional architectural
feature for AArch64. The default is 0 and it is automatically disabled when
the target architecture is AArch32.
GICv3 driver options GICv3 driver options
-------------------- --------------------

View File

@ -192,6 +192,11 @@
#define ID_AA64DFR0_PMS_SHIFT U(32) #define ID_AA64DFR0_PMS_SHIFT U(32)
#define ID_AA64DFR0_PMS_MASK ULL(0xf) #define ID_AA64DFR0_PMS_MASK ULL(0xf)
/* ID_AA64DFR0_EL1.TraceBuffer definitions */
#define ID_AA64DFR0_TRACEBUFFER_SHIFT U(44)
#define ID_AA64DFR0_TRACEBUFFER_MASK ULL(0xf)
#define ID_AA64DFR0_TRACEBUFFER_SUPPORTED ULL(1)
/* ID_AA64DFR0_EL1.MTPMU definitions (for ARMv8.6+) */ /* ID_AA64DFR0_EL1.MTPMU definitions (for ARMv8.6+) */
#define ID_AA64DFR0_MTPMU_SHIFT U(48) #define ID_AA64DFR0_MTPMU_SHIFT U(48)
#define ID_AA64DFR0_MTPMU_MASK ULL(0xf) #define ID_AA64DFR0_MTPMU_MASK ULL(0xf)

View File

@ -0,0 +1,12 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef TRBE_H
#define TRBE_H
void trbe_enable(void);
#endif /* TRBE_H */

View File

@ -22,6 +22,7 @@
#include <lib/extensions/mpam.h> #include <lib/extensions/mpam.h>
#include <lib/extensions/spe.h> #include <lib/extensions/spe.h>
#include <lib/extensions/sve.h> #include <lib/extensions/sve.h>
#include <lib/extensions/trbe.h>
#include <lib/extensions/twed.h> #include <lib/extensions/twed.h>
#include <lib/utils.h> #include <lib/utils.h>
@ -348,6 +349,11 @@ static void enable_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx)
#if ENABLE_MPAM_FOR_LOWER_ELS #if ENABLE_MPAM_FOR_LOWER_ELS
mpam_enable(el2_unused); mpam_enable(el2_unused);
#endif #endif
#if ENABLE_TRBE_FOR_NS
trbe_enable();
#endif /* ENABLE_TRBE_FOR_NS */
#endif #endif
} }

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <arch_helpers.h>
#include <lib/el3_runtime/pubsub.h>
#include <lib/extensions/trbe.h>
static void tsb_csync(void)
{
/*
* The assembler does not yet understand the tsb csync mnemonic
* so use the equivalent hint instruction.
*/
__asm__ volatile("hint #18");
}
static bool trbe_supported(void)
{
uint64_t features;
features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEBUFFER_SHIFT;
return ((features & ID_AA64DFR0_TRACEBUFFER_MASK) ==
ID_AA64DFR0_TRACEBUFFER_SUPPORTED);
}
void trbe_enable(void)
{
uint64_t val;
if (trbe_supported()) {
/*
* MDCR_EL3.NSTB = 0b11
* Allow access of trace buffer control registers from NS-EL1
* and NS-EL2, tracing is prohibited in Secure and Realm state
* (if implemented).
*/
val = read_mdcr_el3();
val |= MDCR_NSTB(MDCR_NSTB_EL1);
write_mdcr_el3(val);
}
}
static void *trbe_drain_trace_buffers_hook(const void *arg __unused)
{
if (trbe_supported()) {
/*
* Before switching from normal world to secure world
* the trace buffers need to be drained out to memory. This is
* required to avoid an invalid memory access when TTBR is switched
* for entry to S-EL1.
*/
tsb_csync();
dsbnsh();
}
return (void *)0;
}
SUBSCRIBE_TO_EVENT(cm_entering_secure_world, trbe_drain_trace_buffers_hook);

View File

@ -355,3 +355,14 @@ NR_OF_IMAGES_IN_FW_BANK := 1
# Disable Firmware update support by default # Disable Firmware update support by default
PSA_FWU_SUPPORT := 0 PSA_FWU_SUPPORT := 0
# By default, disable access of trace buffer control registers from NS
# lower ELs i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused
# if FEAT_TRBE is implemented.
# Note FEAT_TRBE is only supported on AArch64 - therefore do not enable in
# AArch32.
ifneq (${ARCH},aarch32)
ENABLE_TRBE_FOR_NS := 0
else
override ENABLE_TRBE_FOR_NS := 0
endif