feat(runtime/rmi): report number of breakpoints and watchpoints

This patch sets NUM_BPS and NUM_WPS fields in RmiFeatureRegister0
as number of implemented breakpoints and watchpoints, minus 1,
as per RMM Specification 1.0-rel0-rc2.
This patch also removes setting DebugVer, BRPs and WRPs fields
of ID_AA64DFR0_EL1 register value returned by handle_id_sysreg_trap()
function.

Change-Id: I1e3ea542a75a324af9438a46c4876aad41072f6b
Signed-off-by: AlexeiFedorov <Alexei.Fedorov@arm.com>
diff --git a/lib/arch/include/arch.h b/lib/arch/include/arch.h
index 75a1424..c84fc40 100644
--- a/lib/arch/include/arch.h
+++ b/lib/arch/include/arch.h
@@ -457,10 +457,11 @@
 
 /* Debug architecture version */
 #define ID_AA64DFR0_EL1_Debugv8			UL(6)
-#define ID_AA64DFR0_EL1_DebugVHE		UL(7)
+#define ID_AA64DFR0_EL1_Debugv8p1		UL(7)
 #define ID_AA64DFR0_EL1_Debugv8p2		UL(8)
 #define ID_AA64DFR0_EL1_Debugv8p4		UL(9)
 #define ID_AA64DFR0_EL1_Debugv8p8		UL(10)
+#define ID_AA64DFR0_EL1_Debugv8p9		UL(11)
 
 /* ID_AA64DFR1_EL1 definitions */
 #define ID_AA64DFR1_EL1_EBEP_SHIFT		UL(48)
@@ -469,6 +470,12 @@
 #define ID_AA64DFR1_EL1_ICNTR_SHIFT		UL(36)
 #define ID_AA64DFR1_EL1_ICNTR_WIDTH		UL(4)
 
+#define ID_AA64DFR1_EL1_WRPs_SHIFT		UL(16)
+#define ID_AA64DFR1_EL1_WRPs_WIDTH		UL(8)
+
+#define ID_AA64DFR1_EL1_BRPs_SHIFT		UL(8)
+#define ID_AA64DFR1_EL1_BRPs_WIDTH		UL(8)
+
 /* ID_AA64PFR0_EL1 definitions */
 #define ID_AA64PFR0_EL1_SVE_SHIFT	UL(32)
 #define ID_AA64PFR0_EL1_SVE_WIDTH	UL(4)
diff --git a/runtime/core/sysregs.c b/runtime/core/sysregs.c
index f069749..6bcbfdd 100644
--- a/runtime/core/sysregs.c
+++ b/runtime/core/sysregs.c
@@ -35,14 +35,8 @@
  * ID_AA64DFR0_EL1:
  *
  * Cleared fields:
- * - Debug architecture version:
- *   set in ID_AA64DFR0_EL1_SET
  * - Trace unit System registers not implemented
- * - Number of breakpoints:
- *   set in ID_AA64DFR0_EL1_SET
  * - PMU Snapshot extension not implemented
- * - Number of watchpoints:
- *   set in ID_AA64DFR0_EL1_SET
  * - Synchronous-exception-based event profiling not implemented
  * - Number of breakpoints that are context-aware
  * - Statistical Profiling Extension not implemented
@@ -52,11 +46,8 @@
  * - Trace Buffer External Mode not implemented
  */
 #define ID_AA64DFR0_EL1_CLEAR			  \
-	MASK(ID_AA64DFR0_EL1_DebugVer)		| \
 	MASK(ID_AA64DFR0_EL1_TraceVer)		| \
-	MASK(ID_AA64DFR0_EL1_BRPs)		| \
 	MASK(ID_AA64DFR0_EL1_PMSS)		| \
-	MASK(ID_AA64DFR0_EL1_WRPs)		| \
 	MASK(ID_AA64DFR0_EL1_SEBEP)		| \
 	MASK(ID_AA64DFR0_EL1_CTX_CMPS)		| \
 	MASK(ID_AA64DFR0_EL1_PMSVer)		| \
@@ -66,17 +57,6 @@
 	MASK(ID_AA64DFR0_EL1_ExtTrcBuff)
 
 /*
- * Set fields:
- * - Armv8 debug architecture
- * - Number of breakpoints: 2
- * - Number of watchpoints: 2
- */
-#define ID_AA64DFR0_EL1_SET						  \
-	INPLACE(ID_AA64DFR0_EL1_DebugVer, ID_AA64DFR0_EL1_Debugv8)	| \
-	INPLACE(ID_AA64DFR0_EL1_BRPs, 1UL)				| \
-	INPLACE(ID_AA64DFR0_EL1_WRPs, 1UL)
-
-/*
  * ID_AA64DFR1_EL1:
  *
  * Cleared fields:
@@ -147,7 +127,7 @@
 		value = SYSREG_READ(AFR1);
 		break;
 	SYSREG_CASE(DFR0)
-		value = SYSREG_READ_CLEAR_SET(DFR0);
+		value = SYSREG_READ_CLEAR(DFR0);
 		break;
 	SYSREG_CASE(DFR1)
 		value = SYSREG_READ_CLEAR(DFR1);
diff --git a/runtime/rmi/feature.c b/runtime/rmi/feature.c
index da4a915..049cd31 100644
--- a/runtime/rmi/feature.c
+++ b/runtime/rmi/feature.c
@@ -18,6 +18,8 @@
 	/* Set S2SZ field */
 	unsigned long s2sz = arch_feat_get_pa_width();
 	unsigned long feat_reg0 = INPLACE(RMI_FEATURE_REGISTER_0_S2SZ, s2sz);
+	unsigned long num_bps = EXTRACT(ID_AA64DFR0_EL1_BRPs, read_id_aa64dfr0_el1());
+	unsigned long num_wps = EXTRACT(ID_AA64DFR0_EL1_WRPs, read_id_aa64dfr0_el1());
 	struct simd_config simd_cfg = { 0 };
 
 	/* Set LPA2 field. RMM needs both Stage 1 and Stage 2 to support LPA2 */
@@ -43,9 +45,29 @@
 	feat_reg0 |= INPLACE(RMI_FEATURE_REGISTER_0_PMU_NUM_CTRS,
 				EXTRACT(PMCR_EL0_N, read_pmcr_el0()));
 
-	/* The architecture requires at least two breakpoints and watchpoints */
-	feat_reg0 |= INPLACE(RMI_FEATURE_REGISTER_0_NUM_BPS, 2U);
-	feat_reg0 |= INPLACE(RMI_FEATURE_REGISTER_0_NUM_WPS, 2U);
+	/*
+	 * If FEAT_Debugv8p9 is implemented and 16 or more breakpoints or
+	 * watchpoints are implemented, then BRPs and WRPs fields read as
+	 * 0b1111 and ID_AA64DFR1_EL1 indicates the number of breakpoints
+	 * and watchpoints.
+	 */
+	if (num_bps == 15UL) {
+		num_bps = EXTRACT(ID_AA64DFR1_EL1_BRPs, read_id_aa64dfr1_el1());
+		if (num_bps == 0UL) {
+			num_bps = 15UL;
+		}
+	}
+
+	if (num_wps == 15UL) {
+		num_wps = EXTRACT(ID_AA64DFR1_EL1_WRPs, read_id_aa64dfr1_el1());
+		if (num_wps == 0UL) {
+			num_wps = 15UL;
+		}
+	}
+
+	/* Set number of breakpoints and watchpoints supported, minus 1 */
+	feat_reg0 |= (INPLACE(RMI_FEATURE_REGISTER_0_NUM_BPS, num_bps) |
+			INPLACE(RMI_FEATURE_REGISTER_0_NUM_WPS, num_wps));
 
 	/* Get CPU simd configuration and set SVE fields if SVE is present */
 	(void)simd_get_cpu_config(&simd_cfg);
@@ -56,7 +78,7 @@
 				     simd_cfg.sve_vq);
 	}
 
-	/* Set number of List registers implemented, minus one */
+	/* Set number of List registers implemented, minus 1 */
 	feat_reg0 |= INPLACE(RMI_FEATURE_REGISTER_0_GICV3_NUM_LRS,
 				gic_vgic_get_num_lrs());
 
diff --git a/runtime/rmi/realm.c b/runtime/rmi/realm.c
index f131789..df55369 100644
--- a/runtime/rmi/realm.c
+++ b/runtime/rmi/realm.c
@@ -248,10 +248,13 @@
 		return false;
 	}
 
-	/* Validate number of breakpoints */
-	if ((p->num_bps >
+	/*
+	 * Validate number of breakpoints and watchpoins.
+	 * The values 0 are reserved.
+	 */
+	if ((p->num_bps == 0U) || (p->num_bps >
 		EXTRACT(RMI_FEATURE_REGISTER_0_NUM_BPS, feat_reg0)) ||
-	    (p->num_wps >
+		(p->num_wps == 0U) || (p->num_wps >
 		EXTRACT(RMI_FEATURE_REGISTER_0_NUM_WPS, feat_reg0))) {
 		return false;
 	}