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;
}