refactor(trf): enable FEAT_TRF for FEAT_STATE_CHECKED

At the moment we only support FEAT_TRF to be either unconditionally
compiled in, or to be not supported at all.

Add support for runtime detection (ENABLE_TRF_FOR_NS=2), by splitting
is_feat_trf_present() into an ID register reading function and a second
function to report the support status. That function considers both
build time settings and runtime information (if needed), and is used
before we access TRF related registers.
Also move the context saving code from assembly to C, and use the new
is_feat_trf_supported() function to guard its execution.

The FVP platform decided to compile in support unconditionally (=1),
even though FEAT_TRF is an ARMv8.4 feature, so is not available with the
FVP model's default command line.
Change that to the now supported dynamic option (=2), so the right
decision can be made by the code at runtime.

Change-Id: Ia97b01adbe24970a4d837afd463dc5506b7295a3
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
This commit is contained in:
Andre Przywara 2022-11-17 17:30:43 +00:00
parent ff49103660
commit fc8d2d3980
13 changed files with 71 additions and 96 deletions

View file

@ -124,7 +124,7 @@ ifeq (${ENABLE_SYS_REG_TRACE_FOR_NS},1)
BL31_SOURCES += lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c BL31_SOURCES += lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c
endif endif
ifeq (${ENABLE_TRF_FOR_NS},1) ifneq (${ENABLE_TRF_FOR_NS},0)
BL31_SOURCES += lib/extensions/trf/aarch64/trf.c BL31_SOURCES += lib/extensions/trf/aarch64/trf.c
endif endif

View file

@ -50,7 +50,7 @@ ifeq (${ENABLE_SYS_REG_TRACE_FOR_NS},1)
BL32_SOURCES += lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c BL32_SOURCES += lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c
endif endif
ifeq (${ENABLE_TRF_FOR_NS},1) ifneq (${ENABLE_TRF_FOR_NS},0)
BL32_SOURCES += lib/extensions/trf/aarch32/trf.c BL32_SOURCES += lib/extensions/trf/aarch32/trf.c
endif endif

View file

@ -162,16 +162,6 @@ static void read_feat_sel2(void)
#endif #endif
} }
/****************************************************
* Feature : FEAT_TRF (Self-hosted Trace Extensions)
***************************************************/
static void read_feat_trf(void)
{
#if (ENABLE_TRF_FOR_NS == FEAT_STATE_ALWAYS)
feat_detect_panic(is_arm8_4_feat_trf_present(), "TRF");
#endif
}
/************************************************ /************************************************
* Feature : FEAT_MTE (Memory Tagging Extension) * Feature : FEAT_MTE (Memory Tagging Extension)
***********************************************/ ***********************************************/
@ -306,7 +296,8 @@ void detect_arch_features(void)
read_feat_mpam(); read_feat_mpam();
read_feat_nv2(); read_feat_nv2();
read_feat_sel2(); read_feat_sel2();
read_feat_trf(); check_feature(ENABLE_TRF_FOR_NS, read_feat_trf_id_field(),
"TRF", 1, 1);
/* v8.5 features */ /* v8.5 features */
read_feat_mte(); read_feat_mte();

View file

@ -10,6 +10,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <arch_helpers.h> #include <arch_helpers.h>
#include <common/feat_detect.h>
#define ISOLATE_FIELD(reg, feat) \ #define ISOLATE_FIELD(reg, feat) \
((unsigned int)(((reg) >> (feat ## _SHIFT)) & (feat ## _MASK))) ((unsigned int)(((reg) >> (feat ## _SHIFT)) & (feat ## _MASK)))
@ -24,4 +25,22 @@ static inline bool is_armv8_2_ttcnp_present(void)
return ISOLATE_FIELD(read_id_mmfr4(), ID_MMFR4_CNP) != 0U; return ISOLATE_FIELD(read_id_mmfr4(), ID_MMFR4_CNP) != 0U;
} }
static inline unsigned int read_feat_trf_id_field(void)
{
return ISOLATE_FIELD(read_id_dfr0(), ID_DFR0_TRACEFILT);
}
static inline bool is_feat_trf_supported(void)
{
if (ENABLE_TRF_FOR_NS == FEAT_STATE_DISABLED) {
return false;
}
if (ENABLE_TRF_FOR_NS == FEAT_STATE_ALWAYS) {
return true;
}
return read_feat_trf_id_field() != 0U;
}
#endif /* ARCH_FEATURES_H */ #endif /* ARCH_FEATURES_H */

View file

@ -268,10 +268,22 @@ static inline bool is_armv8_4_feat_dit_present(void)
/************************************************************************* /*************************************************************************
* Function to identify the presence of FEAT_TRF (TraceLift) * Function to identify the presence of FEAT_TRF (TraceLift)
************************************************************************/ ************************************************************************/
static inline bool is_arm8_4_feat_trf_present(void) static inline unsigned int read_feat_trf_id_field(void)
{ {
return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEFILT_SHIFT) & return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_TRACEFILT);
ID_AA64DFR0_TRACEFILT_MASK) == ID_AA64DFR0_TRACEFILT_SUPPORTED); }
static inline bool is_feat_trf_supported(void)
{
if (ENABLE_TRF_FOR_NS == FEAT_STATE_DISABLED) {
return false;
}
if (ENABLE_TRF_FOR_NS == FEAT_STATE_ALWAYS) {
return true;
}
return read_feat_trf_id_field() != 0U;
} }
/******************************************************************************** /********************************************************************************

View file

@ -555,6 +555,9 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeylo_el1, APIAKeyLo_EL1)
/* Armv8.4 Data Independent Timing Register */ /* Armv8.4 Data Independent Timing Register */
DEFINE_RENAME_SYSREG_RW_FUNCS(dit, DIT) DEFINE_RENAME_SYSREG_RW_FUNCS(dit, DIT)
/* Armv8.4 FEAT_TRF Register */
DEFINE_RENAME_SYSREG_RW_FUNCS(trfcr_el2, TRFCR_EL2)
/* Armv8.5 MTE Registers */ /* Armv8.5 MTE Registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(tfsre0_el1, TFSRE0_EL1) DEFINE_RENAME_SYSREG_RW_FUNCS(tfsre0_el1, TFSRE0_EL1)
DEFINE_RENAME_SYSREG_RW_FUNCS(tfsr_el1, TFSR_EL1) DEFINE_RENAME_SYSREG_RW_FUNCS(tfsr_el1, TFSR_EL1)

View file

@ -539,10 +539,6 @@ void el2_sysregs_context_restore_ras(el2_sysregs_t *regs);
void el2_sysregs_context_save_nv2(el2_sysregs_t *regs); void el2_sysregs_context_save_nv2(el2_sysregs_t *regs);
void el2_sysregs_context_restore_nv2(el2_sysregs_t *regs); void el2_sysregs_context_restore_nv2(el2_sysregs_t *regs);
#endif /* CTX_INCLUDE_NEVE_REGS */ #endif /* CTX_INCLUDE_NEVE_REGS */
#if ENABLE_TRF_FOR_NS
void el2_sysregs_context_save_trf(el2_sysregs_t *regs);
void el2_sysregs_context_restore_trf(el2_sysregs_t *regs);
#endif /* ENABLE_TRF_FOR_NS */
#if ENABLE_FEAT_CSV2_2 #if ENABLE_FEAT_CSV2_2
void el2_sysregs_context_save_csv2(el2_sysregs_t *regs); void el2_sysregs_context_save_csv2(el2_sysregs_t *regs);
void el2_sysregs_context_restore_csv2(el2_sysregs_t *regs); void el2_sysregs_context_restore_csv2(el2_sysregs_t *regs);

View file

@ -11,6 +11,7 @@
#include <platform_def.h> #include <platform_def.h>
#include <arch.h> #include <arch.h>
#include <arch_features.h>
#include <arch_helpers.h> #include <arch_helpers.h>
#include <common/bl_common.h> #include <common/bl_common.h>
#include <context.h> #include <context.h>
@ -143,9 +144,9 @@ static void enable_extensions_nonsecure(bool el2_unused)
sys_reg_trace_enable(); sys_reg_trace_enable();
#endif /* ENABLE_SYS_REG_TRACE_FOR_NS */ #endif /* ENABLE_SYS_REG_TRACE_FOR_NS */
#if ENABLE_TRF_FOR_NS if (is_feat_trf_supported()) {
trf_enable(); trf_enable();
#endif /* ENABLE_TRF_FOR_NS */ }
#endif #endif
} }

View file

@ -41,10 +41,6 @@
.global el2_sysregs_context_save_nv2 .global el2_sysregs_context_save_nv2
.global el2_sysregs_context_restore_nv2 .global el2_sysregs_context_restore_nv2
#endif /* CTX_INCLUDE_NEVE_REGS */ #endif /* CTX_INCLUDE_NEVE_REGS */
#if ENABLE_TRF_FOR_NS
.global el2_sysregs_context_save_trf
.global el2_sysregs_context_restore_trf
#endif /* ENABLE_TRF_FOR_NS */
#if ENABLE_FEAT_CSV2_2 #if ENABLE_FEAT_CSV2_2
.global el2_sysregs_context_save_csv2 .global el2_sysregs_context_save_csv2
.global el2_sysregs_context_restore_csv2 .global el2_sysregs_context_restore_csv2
@ -536,26 +532,6 @@ func el2_sysregs_context_restore_nv2
endfunc el2_sysregs_context_restore_nv2 endfunc el2_sysregs_context_restore_nv2
#endif /* CTX_INCLUDE_NEVE_REGS */ #endif /* CTX_INCLUDE_NEVE_REGS */
#if ENABLE_TRF_FOR_NS
func el2_sysregs_context_save_trf
/*
* TRFCR_EL2 register is saved only when FEAT_TRF is supported.
*/
mrs x12, TRFCR_EL2
str x12, [x0, #CTX_TRFCR_EL2]
ret
endfunc el2_sysregs_context_save_trf
func el2_sysregs_context_restore_trf
/*
* TRFCR_EL2 register is restored only when FEAT_TRF is supported.
*/
ldr x12, [x0, #CTX_TRFCR_EL2]
msr TRFCR_EL2, x12
ret
endfunc el2_sysregs_context_restore_trf
#endif /* ENABLE_TRF_FOR_NS */
#if ENABLE_FEAT_CSV2_2 #if ENABLE_FEAT_CSV2_2
func el2_sysregs_context_save_csv2 func el2_sysregs_context_save_csv2
/* /*

View file

@ -507,9 +507,9 @@ static void manage_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx)
sys_reg_trace_enable(ctx); sys_reg_trace_enable(ctx);
#endif /* ENABLE_SYS_REG_TRACE_FOR_NS */ #endif /* ENABLE_SYS_REG_TRACE_FOR_NS */
#if ENABLE_TRF_FOR_NS if (is_feat_trf_supported()) {
trf_enable(); trf_enable();
#endif /* ENABLE_TRF_FOR_NS */ }
#endif #endif
} }
@ -875,9 +875,9 @@ void cm_el2_sysregs_context_save(uint32_t security_state)
#if CTX_INCLUDE_NEVE_REGS #if CTX_INCLUDE_NEVE_REGS
el2_sysregs_context_save_nv2(el2_sysregs_ctx); el2_sysregs_context_save_nv2(el2_sysregs_ctx);
#endif #endif
#if ENABLE_TRF_FOR_NS if (is_feat_trf_supported()) {
el2_sysregs_context_save_trf(el2_sysregs_ctx); write_ctx_reg(el2_sysregs_ctx, CTX_TRFCR_EL2, read_trfcr_el2());
#endif }
#if ENABLE_FEAT_CSV2_2 #if ENABLE_FEAT_CSV2_2
el2_sysregs_context_save_csv2(el2_sysregs_ctx); el2_sysregs_context_save_csv2(el2_sysregs_ctx);
#endif #endif
@ -935,9 +935,9 @@ void cm_el2_sysregs_context_restore(uint32_t security_state)
#if CTX_INCLUDE_NEVE_REGS #if CTX_INCLUDE_NEVE_REGS
el2_sysregs_context_restore_nv2(el2_sysregs_ctx); el2_sysregs_context_restore_nv2(el2_sysregs_ctx);
#endif #endif
#if ENABLE_TRF_FOR_NS if (is_feat_trf_supported()) {
el2_sysregs_context_restore_trf(el2_sysregs_ctx); write_trfcr_el2(read_ctx_reg(el2_sysregs_ctx, CTX_TRFCR_EL2));
#endif }
#if ENABLE_FEAT_CSV2_2 #if ENABLE_FEAT_CSV2_2
el2_sysregs_context_restore_csv2(el2_sysregs_ctx); el2_sysregs_context_restore_csv2(el2_sysregs_ctx);
#endif #endif

View file

@ -10,20 +10,10 @@
#include <arch_helpers.h> #include <arch_helpers.h>
#include <lib/extensions/trf.h> #include <lib/extensions/trf.h>
static bool trf_supported(void)
{
uint32_t features;
features = read_id_dfr0() >> ID_DFR0_TRACEFILT_SHIFT;
return ((features & ID_DFR0_TRACEFILT_MASK) ==
ID_DFR0_TRACEFILT_SUPPORTED);
}
void trf_enable(void) void trf_enable(void)
{ {
uint32_t val; uint32_t val;
if (trf_supported()) {
/* /*
* Allow access of trace filter control registers from * Allow access of trace filter control registers from
* non-monitor mode * non-monitor mode
@ -31,5 +21,4 @@ void trf_enable(void)
val = read_sdcr(); val = read_sdcr();
val &= ~SDCR_TTRF_BIT; val &= ~SDCR_TTRF_BIT;
write_sdcr(val); write_sdcr(val);
}
} }

View file

@ -4,26 +4,15 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
#include <stdbool.h>
#include <arch.h> #include <arch.h>
#include <arch_features.h>
#include <arch_helpers.h> #include <arch_helpers.h>
#include <lib/extensions/trf.h> #include <lib/extensions/trf.h>
static bool trf_supported(void)
{
uint64_t features;
features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEFILT_SHIFT;
return ((features & ID_AA64DFR0_TRACEFILT_MASK) ==
ID_AA64DFR0_TRACEFILT_SUPPORTED);
}
void trf_enable(void) void trf_enable(void)
{ {
uint64_t val; uint64_t val;
if (trf_supported()) {
/* /*
* MDCR_EL3.TTRF = b0 * MDCR_EL3.TTRF = b0
* Allow access of trace filter control registers from NS-EL2 * Allow access of trace filter control registers from NS-EL2
@ -32,5 +21,4 @@ void trf_enable(void)
val = read_mdcr_el3(); val = read_mdcr_el3();
val &= ~MDCR_TTRF_BIT; val &= ~MDCR_TTRF_BIT;
write_mdcr_el3(val); write_mdcr_el3(val);
}
} }

View file

@ -461,7 +461,7 @@ endif
ENABLE_SYS_REG_TRACE_FOR_NS := 1 ENABLE_SYS_REG_TRACE_FOR_NS := 1
# enable trace filter control registers access to NS by default # enable trace filter control registers access to NS by default
ENABLE_TRF_FOR_NS := 1 ENABLE_TRF_FOR_NS := 2
# Linux relies on EL3 enablement if those features are present # Linux relies on EL3 enablement if those features are present
ENABLE_FEAT_FGT := 2 ENABLE_FEAT_FGT := 2