feat(trf): enable trace filter control register access from lower NS EL

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

Change-Id: If3f53b8173a5573424b9a405a4bd8c206ffdeb8c
Signed-off-by: Manish V Badarkhe <Manish.Badarkhe@arm.com>
diff --git a/Makefile b/Makefile
index 5de0e07..b9b3176 100644
--- a/Makefile
+++ b/Makefile
@@ -966,6 +966,7 @@
         PSA_FWU_SUPPORT \
         ENABLE_TRBE_FOR_NS \
         ENABLE_SYS_REG_TRACE_FOR_NS \
+        ENABLE_TRF_FOR_NS \
 )))
 
 $(eval $(call assert_numerics,\
@@ -1068,6 +1069,7 @@
         PSA_FWU_SUPPORT \
         ENABLE_TRBE_FOR_NS \
         ENABLE_SYS_REG_TRACE_FOR_NS \
+        ENABLE_TRF_FOR_NS \
 )))
 
 ifeq (${SANITIZE_UB},trap)
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index ccd54bb..7819141 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -98,6 +98,10 @@
 BL31_SOURCES		+=      lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c
 endif
 
+ifeq (${ENABLE_TRF_FOR_NS},1)
+BL31_SOURCES		+=	lib/extensions/trf/aarch64/trf.c
+endif
+
 ifeq (${WORKAROUND_CVE_2017_5715},1)
 BL31_SOURCES		+=	lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S	\
 				lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk
index 486d39d..6339cf8 100644
--- a/bl32/sp_min/sp_min.mk
+++ b/bl32/sp_min/sp_min.mk
@@ -46,6 +46,10 @@
 BL32_SOURCES		+=	lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c
 endif
 
+ifeq (${ENABLE_TRF_FOR_NS},1)
+BL32_SOURCES		+=	lib/extensions/trf/aarch32/trf.c
+endif
+
 BL32_LINKERFILE	:=	bl32/sp_min/sp_min.ld.S
 
 # Include the platform-specific SP_MIN Makefile
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 15535d4..a856dbb 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -786,6 +786,10 @@
   but unused). This feature is available if trace unit such as ETMv4.x, and
   ETE(extending ETM feature) is implemented. This flag is disabled by default.
 
+- ``ENABLE_TRF_FOR_NS``: Boolean option to enable trace filter control registers
+  access from NS ELs, NS-EL2 or NS-EL1 (when NS-EL2 is implemented but unused),
+  if FEAT_TRF is implemented. This flag is disabled by default.
+
 GICv3 driver options
 --------------------
 
diff --git a/include/arch/aarch32/arch_helpers.h b/include/arch/aarch32/arch_helpers.h
index 8d628c1..0330989 100644
--- a/include/arch/aarch32/arch_helpers.h
+++ b/include/arch/aarch32/arch_helpers.h
@@ -283,6 +283,7 @@
 DEFINE_COPROCR_RW_FUNCS_64(icc_sgi0r_el1, ICC_SGI0R_EL1_64)
 DEFINE_COPROCR_WRITE_FUNC_64(icc_sgi1r, ICC_SGI1R_EL1_64)
 
+DEFINE_COPROCR_RW_FUNCS(sdcr, SDCR)
 DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR)
 DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL)
 DEFINE_COPROCR_READ_FUNC(pmcr, PMCR)
diff --git a/include/lib/extensions/trf.h b/include/lib/extensions/trf.h
new file mode 100644
index 0000000..18f17f3
--- /dev/null
+++ b/include/lib/extensions/trf.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TRF_H
+#define TRF_H
+
+void trf_enable(void);
+
+#endif /* TRF_H */
diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c
index 2e5b38f..3ef378c 100644
--- a/lib/el3_runtime/aarch32/context_mgmt.c
+++ b/lib/el3_runtime/aarch32/context_mgmt.c
@@ -17,6 +17,7 @@
 #include <lib/el3_runtime/context_mgmt.h>
 #include <lib/extensions/amu.h>
 #include <lib/extensions/sys_reg_trace.h>
+#include <lib/extensions/trf.h>
 #include <lib/utils.h>
 
 /*******************************************************************************
@@ -141,6 +142,10 @@
 #if ENABLE_SYS_REG_TRACE_FOR_NS
 	sys_reg_trace_enable();
 #endif /* ENABLE_SYS_REG_TRACE_FOR_NS */
+
+#if ENABLE_TRF_FOR_NS
+	trf_enable();
+#endif /* ENABLE_TRF_FOR_NS */
 #endif
 }
 
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 0eb800a..52102dd 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -24,6 +24,7 @@
 #include <lib/extensions/sve.h>
 #include <lib/extensions/sys_reg_trace.h>
 #include <lib/extensions/trbe.h>
+#include <lib/extensions/trf.h>
 #include <lib/extensions/twed.h>
 #include <lib/utils.h>
 
@@ -359,6 +360,10 @@
 	sys_reg_trace_enable(ctx);
 #endif /* ENABLE_SYS_REG_TRACE_FOR_NS */
 
+#if ENABLE_TRF_FOR_NS
+	trf_enable();
+#endif /* ENABLE_TRF_FOR_NS */
+
 #endif
 }
 
diff --git a/lib/extensions/trf/aarch32/trf.c b/lib/extensions/trf/aarch32/trf.c
new file mode 100644
index 0000000..834092d
--- /dev/null
+++ b/lib/extensions/trf/aarch32/trf.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.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)
+{
+	uint32_t val;
+
+	if (trf_supported()) {
+		/*
+		 * Allow access of trace filter control registers from
+		 * non-monitor mode
+		 */
+		val = read_sdcr();
+		val &= ~SDCR_TTRF_BIT;
+		write_sdcr(val);
+	}
+}
diff --git a/lib/extensions/trf/aarch64/trf.c b/lib/extensions/trf/aarch64/trf.c
new file mode 100644
index 0000000..1da5dce
--- /dev/null
+++ b/lib/extensions/trf/aarch64/trf.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include <arch.h>
+#include <arch_helpers.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)
+{
+	uint64_t val;
+
+	if (trf_supported()) {
+		/*
+		 * MDCR_EL3.TTRF = b0
+		 * Allow access of trace filter control registers from NS-EL2
+		 * and NS-EL1 when NS-EL2 is implemented but not used
+		 */
+		val = read_mdcr_el3();
+		val &= ~MDCR_TTRF_BIT;
+		write_mdcr_el3(val);
+	}
+}
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 060bc38..c188621 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -371,3 +371,8 @@
 # ELs  i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused if
 # system register trace is implemented.
 ENABLE_SYS_REG_TRACE_FOR_NS	:= 0
+
+# By default, disable trace filter control registers access to NS
+# lower ELs, i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused
+# if FEAT_TRF is implemented.
+ENABLE_TRF_FOR_NS		:= 0