refactor(brbe): enable FEAT_BRBE for FEAT_STATE_CHECKED

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

Add support for runtime detection (ENABLE_BRBE_FOR_NS=2), by splitting
is_feat_brbe_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 BRBE related registers.

The FVP platform decided to compile in support unconditionally (=1),
even though FEAT_BRBE is an ARMv9 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: I5f2e2c9648300f65f0fa9a5f8e2f34e73529d053
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 4d2fc87..ebb664e 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -116,7 +116,7 @@
 BL31_SOURCES		+=	lib/extensions/trbe/trbe.c
 endif
 
-ifeq (${ENABLE_BRBE_FOR_NS},1)
+ifneq (${ENABLE_BRBE_FOR_NS},0)
 BL31_SOURCES		+=	lib/extensions/brbe/brbe.c
 endif
 
diff --git a/common/feat_detect.c b/common/feat_detect.c
index 3012c8b..4c54cb5 100644
--- a/common/feat_detect.c
+++ b/common/feat_detect.c
@@ -248,16 +248,6 @@
 #endif
 }
 
-/******************************************************
- * Feature : FEAT_BRBE (Branch Record Buffer Extension)
- *****************************************************/
-static void read_feat_brbe(void)
-{
-#if (ENABLE_BRBE_FOR_NS == FEAT_STATE_ALWAYS)
-	feat_detect_panic(is_feat_brbe_present(), "BRBE");
-#endif
-}
-
 /******************************************************************
  * Feature : FEAT_RNG_TRAP (Trapping support for RNDR/RNDRRS)
  *****************************************************************/
@@ -334,7 +324,8 @@
 	check_feature(ENABLE_FEAT_HCX, read_feat_hcx_id_field(), "HCX", 1, 1);
 
 	/* v9.0 features */
-	read_feat_brbe();
+	check_feature(ENABLE_BRBE_FOR_NS, read_feat_brbe_id_field(),
+		      "BRBE", 1, 2);
 	check_feature(ENABLE_TRBE_FOR_NS, read_feat_trbe_id_field(),
 		      "TRBE", 1, 1);
 
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index ded42d4..9f6af39 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -288,10 +288,22 @@
  * Function to identify the presence of FEAT_BRBE (Branch Record Buffer
  * Extension)
  ******************************************************************************/
-static inline bool is_feat_brbe_present(void)
+static inline unsigned int read_feat_brbe_id_field(void)
+{
+	return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_BRBE);
+}
+
+static inline bool is_feat_brbe_supported(void)
 {
-	return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_BRBE_SHIFT) &
-		ID_AA64DFR0_BRBE_MASK) == ID_AA64DFR0_BRBE_SUPPORTED);
+	if (ENABLE_BRBE_FOR_NS == FEAT_STATE_DISABLED) {
+		return false;
+	}
+
+	if (ENABLE_BRBE_FOR_NS == FEAT_STATE_ALWAYS) {
+		return true;
+	}
+
+	return read_feat_brbe_id_field() != 0U;
 }
 
 /*******************************************************************************
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index 1dfb71f..54e257b 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -499,9 +499,9 @@
 		trbe_enable();
 	}
 
-#if ENABLE_BRBE_FOR_NS
-	brbe_enable();
-#endif /* ENABLE_BRBE_FOR_NS */
+	if (is_feat_brbe_supported()) {
+		brbe_enable();
+	}
 
 #if ENABLE_SYS_REG_TRACE_FOR_NS
 	sys_reg_trace_enable(ctx);
diff --git a/lib/extensions/brbe/brbe.c b/lib/extensions/brbe/brbe.c
index 1982619..329cf98 100644
--- a/lib/extensions/brbe/brbe.c
+++ b/lib/extensions/brbe/brbe.c
@@ -12,16 +12,14 @@
 {
 	uint64_t val;
 
-	if (is_feat_brbe_present()) {
-		/*
-		 * MDCR_EL3.SBRBE = 0b01
-		 *
-		 * Allows BRBE usage in non-secure world and prohibited in
-		 * secure world.
-		 */
-		val = read_mdcr_el3();
-		val &= ~(MDCR_SBRBE_MASK << MDCR_SBRBE_SHIFT);
-		val |= (0x1UL << MDCR_SBRBE_SHIFT);
-		write_mdcr_el3(val);
-	}
+	/*
+	 * MDCR_EL3.SBRBE = 0b01
+	 *
+	 * Allows BRBE usage in non-secure world and prohibited in
+	 * secure world.
+	 */
+	val = read_mdcr_el3();
+	val &= ~(MDCR_SBRBE_MASK << MDCR_SBRBE_SHIFT);
+	val |= (0x1UL << MDCR_SBRBE_SHIFT);
+	write_mdcr_el3(val);
 }
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index 7991c14..dda7e6c 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -453,7 +453,7 @@
 # do not enable when ENABLE_RME=1
 ifeq (${ARCH}, aarch64)
 ifeq (${ENABLE_RME},0)
-	ENABLE_BRBE_FOR_NS		:= 1
+	ENABLE_BRBE_FOR_NS		:= 2
 endif
 endif