feat(rmm): report PMU not supported

This patch reports for PMU not being supported by RMM
and adds relevant definitions for Feature Register 0
in accordance with Beta 0 RMM Specification.
It also masks PMUVer field when ID_AA64DFR0_EL1
register is read by Realm.
ID_AA64DFR0_EL1 register mask and set values are
modified to report minimum Debug features supported
by ARM architecture.

Signed-off-by: AlexeiFedorov <Alexei.Fedorov@arm.com>
Change-Id: I9974dac476df270f309f6bb30d3485ba0af5986e
diff --git a/runtime/core/sysregs.c b/runtime/core/sysregs.c
index b2f7a66..7b8ab09 100644
--- a/runtime/core/sysregs.c
+++ b/runtime/core/sysregs.c
@@ -12,33 +12,92 @@
 #include <rec.h>
 #include <smc-rmi.h>
 
-#define SYSREG_READ_CASE(reg) \
-	case ESR_EL2_SYSREG_##reg: return read_##reg()
+#define SYSREG_CASE(reg) \
+	case ESR_EL2_SYSREG_##ID_AA64##reg##_EL1:
 
-static unsigned long read_idreg(unsigned int idreg)
-{
-	switch (idreg) {
-	SYSREG_READ_CASE(ID_AA64PFR0_EL1);
-	SYSREG_READ_CASE(ID_AA64PFR1_EL1);
-	/*
-	 * TODO: not supported without SVE:
-	 * SYSREG_READ_CASE(ID_AA64ZFR0_EL1);
-	 */
-	SYSREG_READ_CASE(ID_AA64DFR0_EL1);
-	SYSREG_READ_CASE(ID_AA64DFR1_EL1);
-	SYSREG_READ_CASE(ID_AA64AFR0_EL1);
-	SYSREG_READ_CASE(ID_AA64AFR1_EL1);
-	SYSREG_READ_CASE(ID_AA64ISAR0_EL1);
-	SYSREG_READ_CASE(ID_AA64ISAR1_EL1);
-	SYSREG_READ_CASE(ID_AA64MMFR0_EL1);
-	SYSREG_READ_CASE(ID_AA64MMFR1_EL1);
-	SYSREG_READ_CASE(ID_AA64MMFR2_EL1);
+#define SYSREG_READ(reg)		\
+	read_ID_AA64##reg##_EL1()
 
-	default:
-		/* All other encodings are in the RES0 space */
-		return 0UL;
-	}
-}
+#define SYSREG_READ_CLEAR(reg)		\
+	(read_ID_AA64##reg##_EL1() &	\
+	~(ID_AA64##reg##_EL1_CLEAR))
+
+#define SYSREG_READ_CLEAR_SET(reg)	\
+	((read_ID_AA64##reg##_EL1()  &	\
+	~(ID_AA64##reg##_EL1_CLEAR)) |	\
+	 (ID_AA64##reg##_EL1_SET))
+
+/* System registers ID_AA64xxx_EL1 feature clear masks and set values */
+
+/*
+ * ID_AA64DFR0_EL1:
+ *
+ * Cleared fields:
+ * - Debug architecture version:
+ *   set in ID_AA64DFR0_EL1_SET
+ * - Trace unit System registers not implemented
+ * - PMU is not implemented
+ * - Number of breakpoints:
+ *   set in ID_AA64DFR0_EL1_SET
+ * - Number of watchpoints:
+ *   set in ID_AA64DFR0_EL1_SET
+ * - Number of breakpoints that are context-aware
+ * - Statistical Profiling Extension not implemented
+ * - Armv8.4 Self-hosted Trace Extension not implemented
+ * - Trace Buffer Extension not implemented
+ * - FEAT_MTPMU not implemented
+ * - Branch Record Buffer Extension not implemented
+ */
+#define ID_AA64DFR0_EL1_CLEAR			  \
+	ID_AA64DFR0_EL1_DebugVer_MASK		| \
+	ID_AA64DFR0_EL1_TraceVer_MASK		| \
+	ID_AA64DFR0_EL1_PMUVer_MASK		| \
+	ID_AA64DFR0_EL1_BRPs_MASK		| \
+	ID_AA64DFR0_EL1_WRPs_MASK		| \
+	ID_AA64DFR0_EL1_CTX_CMPS_MASK		| \
+	ID_AA64DFR0_EL1_PMSVer_MASK		| \
+	ID_AA64DFR0_EL1_TraceFilt_MASK		| \
+	ID_AA64DFR0_EL1_TraceBuffer_MASK	| \
+	ID_AA64DFR0_EL1_MTPMU_MASK		| \
+	ID_AA64DFR0_EL1_BRBE_MASK
+
+/*
+ * Set fields:
+ * - Armv8 debug architecture
+ * - Number of breakpoints: 2
+ * - Number of watchpoints: 2
+ */
+#define ID_AA64DFR0_EL1_SET			  \
+	ID_AA64DFR0_EL1_DebugVer_8		| \
+	INPLACE(ID_AA64DFR0_EL1_BRPs, 1UL)	| \
+	INPLACE(ID_AA64DFR0_EL1_WRPs, 1UL)
+
+/*
+ * ID_AA64ISAR1_EL1:
+ *
+ * Cleared fields:
+ * - Address and Generic Authentication are not implemented
+ */
+#define ID_AA64ISAR1_EL1_CLEAR		  \
+	ID_AA64ISAR1_EL1_APA_MASK	| \
+	ID_AA64ISAR1_EL1_API_MASK	| \
+	ID_AA64ISAR1_EL1_GPA_MASK	| \
+	ID_AA64ISAR1_EL1_GPI_MASK
+
+/*
+ * ID_AA64PFR0_EL1:
+ *
+ * Cleared fields:
+ * - Activity Monitors Extension not implemented
+ * - Scalable Vector Extension not implemented.
+ *   This is a temporary fix until RMM completely supports SVE.
+ *
+ * TODO: use and define:
+ * ID_AA64PFR0_EL1_AMU_MASK & ID_AA64PFR0_EL1_SVE_MASK
+ */
+#define ID_AA64PFR0_EL1_CLEAR		  \
+	MASK(ID_AA64PFR0_EL1_AMU)	| \
+	MASK(ID_AA64PFR0_EL1_SVE)
 
 /*
  * Handle ID_AA64XXX<n>_EL1 instructions
@@ -48,7 +107,7 @@
 				  unsigned long esr)
 {
 	unsigned int rt;
-	unsigned long idreg, mask;
+	unsigned long idreg, value;
 
 	/*
 	 * We only set HCR_EL2.TID3 to trap ID registers at the moment and
@@ -71,30 +130,54 @@
 
 	idreg = esr & ESR_EL2_SYSREG_MASK;
 
-	if (idreg == ESR_EL2_SYSREG_ID_AA64ISAR1_EL1) {
-		/* Clear Address and Generic Authentication bits */
-		mask = (0xfUL << ESR_EL2_SYSREG_ID_AA64ISAR1_APA_SHIFT) |
-		       (0xfUL << ESR_EL2_SYSREG_ID_AA64ISAR1_API_SHIFT) |
-		       (0xfUL << ESR_EL2_SYSREG_ID_AA64ISAR1_GPA_SHIFT) |
-		       (0xfUL << ESR_EL2_SYSREG_ID_AA64ISAR1_GPI_SHIFT);
-	/*
-	 * Workaround for TF-A trapping AMU registers access
-	 * to EL3 in Realm state
-	 */
-	} else if (idreg == ESR_EL2_SYSREG_ID_AA64PFR0_EL1) {
-		/* Clear support for Activity Monitors Extension */
-		mask = MASK(ID_AA64PFR0_EL1_AMU);
-
+	switch (idreg) {
+	SYSREG_CASE(AFR0)
+		value = SYSREG_READ(AFR0);
+		break;
+	SYSREG_CASE(AFR1)
+		value = SYSREG_READ(AFR1);
+		break;
+	SYSREG_CASE(DFR0)
+		value = SYSREG_READ_CLEAR_SET(DFR0);
+		break;
+	SYSREG_CASE(DFR1)
+		value = SYSREG_READ(DFR1);
+		break;
+	SYSREG_CASE(ISAR0)
+		value = SYSREG_READ(ISAR0);
+		break;
+	SYSREG_CASE(ISAR1)
+		value = SYSREG_READ_CLEAR(ISAR1);
+		break;
+	SYSREG_CASE(MMFR0)
+		value = SYSREG_READ(MMFR0);
+		break;
+	SYSREG_CASE(MMFR1)
+		value = SYSREG_READ(MMFR1);
+		break;
+	SYSREG_CASE(MMFR2)
+		value = SYSREG_READ(MMFR2);
+		break;
+	SYSREG_CASE(PFR0)
 		/*
-		 * Clear support for SVE. This is a temporary fix until RMM
-		 * completely supports SVE.
+		 * Workaround for TF-A trapping AMU registers access
+		 * to EL3 in Realm state.
 		 */
-		mask |= MASK(ID_AA64PFR0_EL1_SVE);
-	} else {
-		mask = 0UL;
+		value = SYSREG_READ_CLEAR(PFR0);
+		break;
+	SYSREG_CASE(PFR1)
+		value = SYSREG_READ(PFR1);
+		break;
+	/*
+	 * TODO: not supported without SVE:
+	 * SYSREG_CASE(ZFR0)
+	 */
+	default:
+		/* All other encodings are in the RES0 space */
+		value = 0UL;
 	}
 
-	rec->regs[rt] = read_idreg(idreg) & ~mask;
+	rec->regs[rt] = value;
 	return true;
 }