feat(cpufeat): add feat detection helpers

This patch adds multiple feature detection helpers, useful for
tests that need to check for the presence of those features.

Signed-off-by: Juan Pablo Conde <juanpablo.conde@arm.com>
Change-Id: Ie6d39b9e9c8d28d0a4cd9d02350e2bedd016e45e
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index a37e230..9c0cbcd 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -128,35 +128,50 @@
 #define DCCSW			U(0x2)
 
 /* ID_AA64PFR0_EL1 definitions */
-#define ID_AA64PFR0_EL0_SHIFT	U(0)
-#define ID_AA64PFR0_EL1_SHIFT	U(4)
-#define ID_AA64PFR0_EL2_SHIFT	U(8)
-#define ID_AA64PFR0_EL3_SHIFT	U(12)
-#define ID_AA64PFR0_AMU_SHIFT	U(44)
-#define ID_AA64PFR0_AMU_LENGTH	U(4)
-#define ID_AA64PFR0_AMU_MASK	ULL(0xf)
-#define ID_AA64PFR0_AMU_NOT_SUPPORTED	U(0x0)
-#define ID_AA64PFR0_AMU_V1	U(0x1)
-#define ID_AA64PFR0_AMU_V1P1	U(0x2)
-#define ID_AA64PFR0_ELX_MASK	ULL(0xf)
-#define ID_AA64PFR0_SVE_SHIFT	U(32)
-#define ID_AA64PFR0_SVE_WIDTH	U(4)
-#define ID_AA64PFR0_SVE_MASK	ULL(0xf)
-#define ID_AA64PFR0_SVE_LENGTH	U(4)
-#define ID_AA64PFR0_MPAM_SHIFT	U(40)
-#define ID_AA64PFR0_MPAM_MASK	ULL(0xf)
-#define ID_AA64PFR0_DIT_SHIFT	U(48)
-#define ID_AA64PFR0_DIT_MASK	ULL(0xf)
-#define ID_AA64PFR0_DIT_LENGTH	U(4)
-#define ID_AA64PFR0_DIT_SUPPORTED	U(1)
-#define ID_AA64PFR0_CSV2_SHIFT	U(56)
-#define ID_AA64PFR0_CSV2_MASK	ULL(0xf)
-#define ID_AA64PFR0_CSV2_LENGTH	U(4)
+#define ID_AA64PFR0_EL0_SHIFT			U(0)
+#define ID_AA64PFR0_EL1_SHIFT			U(4)
+#define ID_AA64PFR0_EL2_SHIFT			U(8)
+#define ID_AA64PFR0_EL3_SHIFT			U(12)
+#define ID_AA64PFR0_AMU_SHIFT			U(44)
+#define ID_AA64PFR0_AMU_LENGTH			U(4)
+#define ID_AA64PFR0_AMU_MASK			ULL(0xf)
+#define ID_AA64PFR0_AMU_NOT_SUPPORTED		U(0x0)
+#define ID_AA64PFR0_AMU_V1			U(0x1)
+#define ID_AA64PFR0_AMU_V1P1			U(0x2)
+#define ID_AA64PFR0_ELX_MASK			ULL(0xf)
+#define ID_AA64PFR0_SVE_SHIFT			U(32)
+#define ID_AA64PFR0_SVE_WIDTH			U(4)
+#define ID_AA64PFR0_SVE_MASK			ULL(0xf)
+#define ID_AA64PFR0_SVE_LENGTH			U(4)
+#define ID_AA64PFR0_MPAM_SHIFT			U(40)
+#define ID_AA64PFR0_MPAM_MASK			ULL(0xf)
+#define ID_AA64PFR0_DIT_SHIFT			U(48)
+#define ID_AA64PFR0_DIT_MASK			ULL(0xf)
+#define ID_AA64PFR0_DIT_LENGTH			U(4)
+#define ID_AA64PFR0_DIT_SUPPORTED		U(1)
+#define ID_AA64PFR0_CSV2_SHIFT			U(56)
+#define ID_AA64PFR0_CSV2_MASK			ULL(0xf)
+#define ID_AA64PFR0_CSV2_WIDTH			U(4)
+#define ID_AA64PFR0_CSV2_NOT_SUPPORTED		ULL(0x0)
+#define ID_AA64PFR0_CSV2_SUPPORTED		ULL(0x1)
+#define ID_AA64PFR0_CSV2_2_SUPPORTED		ULL(0x2)
 #define ID_AA64PFR0_FEAT_RME_SHIFT		U(52)
 #define ID_AA64PFR0_FEAT_RME_MASK		ULL(0xf)
 #define ID_AA64PFR0_FEAT_RME_LENGTH		U(4)
 #define ID_AA64PFR0_FEAT_RME_NOT_SUPPORTED	U(0)
 #define ID_AA64PFR0_FEAT_RME_V1			U(1)
+#define ID_AA64PFR0_RAS_MASK			ULL(0xf)
+#define ID_AA64PFR0_RAS_SHIFT			U(28)
+#define ID_AA64PFR0_RAS_WIDTH			U(4)
+#define ID_AA64PFR0_RAS_NOT_SUPPORTED		ULL(0x0)
+#define ID_AA64PFR0_RAS_SUPPORTED		ULL(0x1)
+#define ID_AA64PFR0_RASV1P1_SUPPORTED		ULL(0x2)
+#define ID_AA64PFR0_GIC_SHIFT			U(24)
+#define ID_AA64PFR0_GIC_WIDTH			U(4)
+#define ID_AA64PFR0_GIC_MASK			ULL(0xf)
+#define ID_AA64PFR0_GIC_NOT_SUPPORTED		ULL(0x0)
+#define ID_AA64PFR0_GICV3_GICV4_SUPPORTED	ULL(0x1)
+#define ID_AA64PFR0_GICV4_1_SUPPORTED		ULL(0x2)
 
 /* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
 #define ID_AA64DFR0_PMS_SHIFT		U(32)
@@ -214,24 +229,46 @@
 #define EL_IMPL_A64ONLY		ULL(1)
 #define EL_IMPL_A64_A32		ULL(2)
 
-#define ID_AA64PFR0_GIC_SHIFT	U(24)
-#define ID_AA64PFR0_GIC_WIDTH	U(4)
-#define ID_AA64PFR0_GIC_MASK	ULL(0xf)
+/* ID_AA64ISAR0_EL1 definitions */
+#define ID_AA64ISAR0_EL1			S3_0_C0_C6_0
+#define ID_AA64ISAR0_TLB_MASK			ULL(0xf)
+#define ID_AA64ISAR0_TLB_SHIFT			U(56)
+#define ID_AA64ISAR0_TLB_WIDTH			U(4)
+#define ID_AA64ISAR0_TLBIRANGE_SUPPORTED	ULL(0x2)
+#define ID_AA64ISAR0_TLB_NOT_SUPPORTED		ULL(0)
 
 /* ID_AA64ISAR1_EL1 definitions */
-#define ID_AA64ISAR1_EL1	S3_0_C0_C6_1
-#define ID_AA64ISAR1_GPI_SHIFT	U(28)
-#define ID_AA64ISAR1_GPI_WIDTH	U(4)
-#define ID_AA64ISAR1_GPI_MASK	ULL(0xf)
-#define ID_AA64ISAR1_GPA_SHIFT	U(24)
-#define ID_AA64ISAR1_GPA_WIDTH	U(4)
-#define ID_AA64ISAR1_GPA_MASK	ULL(0xf)
-#define ID_AA64ISAR1_API_SHIFT	U(8)
-#define ID_AA64ISAR1_API_WIDTH	U(4)
-#define ID_AA64ISAR1_API_MASK	ULL(0xf)
-#define ID_AA64ISAR1_APA_SHIFT	U(4)
-#define ID_AA64ISAR1_APA_WIDTH	U(4)
-#define ID_AA64ISAR1_APA_MASK	ULL(0xf)
+#define ID_AA64ISAR1_EL1			S3_0_C0_C6_1
+#define ID_AA64ISAR1_GPI_SHIFT			U(28)
+#define ID_AA64ISAR1_GPI_WIDTH			U(4)
+#define ID_AA64ISAR1_GPI_MASK			ULL(0xf)
+#define ID_AA64ISAR1_GPA_SHIFT			U(24)
+#define ID_AA64ISAR1_GPA_WIDTH			U(4)
+#define ID_AA64ISAR1_GPA_MASK			ULL(0xf)
+#define ID_AA64ISAR1_API_SHIFT			U(8)
+#define ID_AA64ISAR1_API_WIDTH			U(4)
+#define ID_AA64ISAR1_API_MASK			ULL(0xf)
+#define ID_AA64ISAR1_APA_SHIFT			U(4)
+#define ID_AA64ISAR1_APA_WIDTH			U(4)
+#define ID_AA64ISAR1_APA_MASK			ULL(0xf)
+#define ID_AA64ISAR1_SPECRES_MASK		ULL(0xf)
+#define ID_AA64ISAR1_SPECRES_SHIFT		U(40)
+#define ID_AA64ISAR1_SPECRES_WIDTH		U(4)
+#define ID_AA64ISAR1_SPECRES_NOT_SUPPORTED	ULL(0x0)
+#define ID_AA64ISAR1_SPECRES_SUPPORTED		ULL(0x1)
+#define ID_AA64ISAR1_DPB_MASK			ULL(0xf)
+#define ID_AA64ISAR1_DPB_SHIFT			U(0)
+#define ID_AA64ISAR1_DPB_WIDTH			U(4)
+#define ID_AA64ISAR1_DPB_NOT_SUPPORTED		ULL(0x0)
+#define ID_AA64ISAR1_DPB_SUPPORTED		ULL(0x1)
+#define ID_AA64ISAR1_DPB2_SUPPORTED		ULL(0x2)
+#define ID_AA64ISAR1_LS64_MASK			ULL(0xf)
+#define ID_AA64ISAR1_LS64_SHIFT			U(60)
+#define ID_AA64ISAR1_LS64_WIDTH			U(4)
+#define ID_AA64ISAR1_LS64_NOT_SUPPORTED		ULL(0x0)
+#define ID_AA64ISAR1_LS64_SUPPORTED		ULL(0x1)
+#define ID_AA64ISAR1_LS64_V_SUPPORTED		ULL(0x2)
+#define ID_AA64ISAR1_LS64_ACCDATA_SUPPORTED	ULL(0x3)
 
 /* ID_AA64ISAR2_EL1 definitions */
 #define ID_AA64ISAR2_EL1		S3_0_C0_C6_2
@@ -312,7 +349,7 @@
 /* ID_AA64MMFR1_EL1 definitions */
 #define ID_AA64MMFR1_EL1_PAN_SHIFT		U(20)
 #define ID_AA64MMFR1_EL1_PAN_MASK		ULL(0xf)
-#define ID_AA64MMFR1_EL1_PAN_NOT_SUPPORTED	ULL(0x0)
+#define ID_AA64MMFR1_EL1_PAN_WIDTH		U(4)
 #define ID_AA64MMFR1_EL1_PAN_SUPPORTED		ULL(0x1)
 #define ID_AA64MMFR1_EL1_PAN2_SUPPORTED		ULL(0x2)
 #define ID_AA64MMFR1_EL1_PAN3_SUPPORTED		ULL(0x3)
@@ -323,6 +360,12 @@
 #define ID_AA64MMFR1_EL1_AFP_SHIFT		U(44)
 #define ID_AA64MMFR1_EL1_AFP_MASK		ULL(0xf)
 #define ID_AA64MMFR1_EL1_AFP_SUPPORTED		ULL(0x1)
+#define ID_AA64MMFR1_EL1_LO_SHIFT		U(16)
+#define ID_AA64MMFR1_EL1_LO_MASK		ULL(0xf)
+#define ID_AA64MMFR1_EL1_LO_WIDTH		U(4)
+#define ID_AA64MMFR1_EL1_LOR_NOT_SUPPORTED	ULL(0x0)
+#define ID_AA64MMFR1_EL1_LOR_SUPPORTED		ULL(0x1)
+
 
 /* ID_AA64MMFR2_EL1 definitions */
 #define ID_AA64MMFR2_EL1		S3_0_C0_C7_2
@@ -353,6 +396,12 @@
 #define ID_AA64PFR1_EL1_RNG_TRAP_SUPPORTED	ULL(0x1)
 #define ID_AA64PFR1_EL1_RNG_TRAP_NOT_SUPPORTED	ULL(0x0)
 
+#define ID_AA64PFR1_CSV2_FRAC_MASK		ULL(0xf)
+#define ID_AA64PFR1_CSV2_FRAC_SHIFT		U(32)
+#define ID_AA64PFR1_CSV2_FRAC_WIDTH		U(4)
+#define ID_AA64PFR1_CSV2_1P1_SUPPORTED		ULL(0x1)
+#define ID_AA64PFR1_CSV2_1P2_SUPPORTED		ULL(0x2)
+
 #define MTE_UNIMPLEMENTED	ULL(0)
 #define MTE_IMPLEMENTED_EL0	ULL(1)	/* MTE is only implemented at EL0 */
 #define MTE_IMPLEMENTED_ELX	ULL(2)	/* MTE is implemented at all ELs */
@@ -363,6 +412,11 @@
 #define ID_AA64PFR1_EL1_SME_SUPPORTED		ULL(0x1)
 #define ID_AA64PFR1_EL1_SME2_SUPPORTED		ULL(0x2)
 
+#define ID_AA64PFR1_RAS_FRAC_MASK		ULL(0xf)
+#define ID_AA64PFR1_RAS_FRAC_SHIFT		U(12)
+#define ID_AA64PFR1_RAS_FRAC_WIDTH		U(4)
+#define ID_AA64PFR1_RASV1P1_SUPPORTED		ULL(0x1)
+
 /* ID_PFR1_EL1 definitions */
 #define ID_PFR1_VIRTEXT_SHIFT	U(12)
 #define ID_PFR1_VIRTEXT_MASK	U(0xf)
@@ -1269,4 +1323,23 @@
 #define HCRX_EL2_EnAS0_BIT	(UL(1) << 0)
 #define HCRX_EL2_INIT_VAL	ULL(0x0)
 
+/*******************************************************************************
+ * PFR0_EL1 - Definitions for AArch32 Processor Feature Register 0
+ ******************************************************************************/
+#define ID_PFR0_EL1				S3_0_C0_C1_0
+#define ID_PFR0_EL1_RAS_MASK			ULL(0xf)
+#define ID_PFR0_EL1_RAS_SHIFT			U(28)
+#define ID_PFR0_EL1_RAS_WIDTH			U(4)
+#define ID_PFR0_EL1_RAS_SUPPORTED		ULL(0x1)
+#define ID_PFR0_EL1_RASV1P1_SUPPORTED		ULL(0x2)
+
+/*******************************************************************************
+ * PFR2_EL1 - Definitions for AArch32 Processor Feature Register 2
+ ******************************************************************************/
+#define ID_PFR2_EL1				S3_0_C0_C3_4
+#define ID_PFR2_EL1_RAS_FRAC_MASK		ULL(0xf)
+#define ID_PFR2_EL1_RAS_FRAC_SHIFT		U(8)
+#define ID_PFR2_EL1_RAS_FRAC_WIDTH		U(4)
+#define ID_PFR2_EL1_RASV1P1_SUPPORTED		ULL(0x1)
+
 #endif /* ARCH_H */
diff --git a/include/lib/aarch64/arch_features.h b/include/lib/aarch64/arch_features.h
index ee14d67..85f8952 100644
--- a/include/lib/aarch64/arch_features.h
+++ b/include/lib/aarch64/arch_features.h
@@ -22,8 +22,18 @@
 
 static inline bool is_armv8_1_pan_present(void)
 {
-	return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_PAN_SHIFT) &
-		ID_AA64MMFR1_EL1_PAN_MASK) != 0U;
+	u_register_t id_aa64mmfr1_pan =
+		EXTRACT(ID_AA64MMFR1_EL1_PAN, read_id_aa64mmfr1_el1());
+	return (id_aa64mmfr1_pan >= ID_AA64MMFR1_EL1_PAN_SUPPORTED) &&
+		(id_aa64mmfr1_pan <= ID_AA64MMFR1_EL1_PAN3_SUPPORTED);
+}
+
+static inline bool is_armv8_2_pan2_present(void)
+{
+	u_register_t id_aa64mmfr1_pan =
+		EXTRACT(ID_AA64MMFR1_EL1_PAN, read_id_aa64mmfr1_el1());
+	return (id_aa64mmfr1_pan >= ID_AA64MMFR1_EL1_PAN2_SUPPORTED) &&
+		(id_aa64mmfr1_pan <= ID_AA64MMFR1_EL1_PAN3_SUPPORTED);
 }
 
 static inline bool is_armv8_2_sve_present(void)
@@ -289,4 +299,111 @@
 			&& (is_feat_52b_on_4k_supported() == true)));
 }
 
+static inline bool is_feat_specres_present(void)
+{
+	return EXTRACT(ID_AA64ISAR1_SPECRES, read_id_aa64isar1_el1())
+		== ID_AA64ISAR1_SPECRES_SUPPORTED;
+}
+
+static inline bool is_feat_tlbirange_present(void)
+{
+	return EXTRACT(ID_AA64ISAR0_TLB, read_id_aa64isar0_el1())
+		== ID_AA64ISAR0_TLBIRANGE_SUPPORTED;
+}
+
+static inline bool is_feat_tlbios_present(void)
+{
+	return EXTRACT(ID_AA64ISAR0_TLB, read_id_aa64isar0_el1())
+		!= ID_AA64ISAR0_TLB_NOT_SUPPORTED;
+}
+
+static inline bool is_feat_dpb_present(void)
+{
+	return EXTRACT(ID_AA64ISAR1_DPB, read_id_aa64isar1_el1())
+		>= ID_AA64ISAR1_DPB_SUPPORTED;
+}
+
+static inline bool is_feat_dpb2_present(void)
+{
+	return EXTRACT(ID_AA64ISAR1_DPB, read_id_aa64isar1_el1())
+		>= ID_AA64ISAR1_DPB2_SUPPORTED;
+}
+
+static inline bool is_feat_ls64_present(void)
+{
+	return EXTRACT(ID_AA64ISAR1_LS64, read_id_aa64isar1_el1())
+		>= ID_AA64ISAR1_LS64_SUPPORTED;
+}
+
+static inline bool is_feat_ls64_v_present(void)
+{
+	return EXTRACT(ID_AA64ISAR1_LS64, read_id_aa64isar1_el1())
+		>= ID_AA64ISAR1_LS64_V_SUPPORTED;
+}
+
+static inline bool is_feat_ls64_accdata_present(void)
+{
+	return EXTRACT(ID_AA64ISAR1_LS64, read_id_aa64isar1_el1())
+		>= ID_AA64ISAR1_LS64_ACCDATA_SUPPORTED;
+}
+
+static inline bool is_feat_ras_present(void)
+{
+	return EXTRACT(ID_AA64PFR0_RAS, read_id_aa64pfr0_el1())
+		== ID_AA64PFR0_RAS_SUPPORTED;
+}
+
+static inline bool is_feat_rasv1p1_present(void)
+{
+	return (EXTRACT(ID_AA64PFR0_RAS, read_id_aa64pfr0_el1())
+		== ID_AA64PFR0_RASV1P1_SUPPORTED)
+		|| (is_feat_ras_present() &&
+			(EXTRACT(ID_AA64PFR1_RAS_FRAC, read_id_aa64pfr1_el1())
+				== ID_AA64PFR1_RASV1P1_SUPPORTED))
+		|| (EXTRACT(ID_PFR0_EL1_RAS, read_id_pfr0_el1())
+			== ID_PFR0_EL1_RASV1P1_SUPPORTED)
+		|| ((EXTRACT(ID_PFR0_EL1_RAS, read_id_pfr0_el1())
+			== ID_PFR0_EL1_RAS_SUPPORTED) &&
+			(EXTRACT(ID_PFR2_EL1_RAS_FRAC, read_id_pfr2_el1())
+				== ID_PFR2_EL1_RASV1P1_SUPPORTED));
+}
+
+static inline bool is_feat_gicv3_gicv4_present(void)
+{
+	return EXTRACT(ID_AA64PFR0_GIC, read_id_aa64pfr0_el1())
+		== ID_AA64PFR0_GICV3_GICV4_SUPPORTED;
+}
+
+static inline bool is_feat_csv2_present(void)
+{
+	return EXTRACT(ID_AA64PFR0_CSV2, read_id_aa64pfr0_el1())
+		== ID_AA64PFR0_CSV2_SUPPORTED;
+}
+
+static inline bool is_feat_csv2_2_present(void)
+{
+	return EXTRACT(ID_AA64PFR0_CSV2, read_id_aa64pfr0_el1())
+		== ID_AA64PFR0_CSV2_2_SUPPORTED;
+}
+
+static inline bool is_feat_csv2_1p1_present(void)
+{
+	return is_feat_csv2_present() &&
+		(EXTRACT(ID_AA64PFR1_CSV2_FRAC, read_id_aa64pfr1_el1())
+			== ID_AA64PFR1_CSV2_1P1_SUPPORTED);
+}
+
+static inline bool is_feat_csv2_1p2_present(void)
+{
+	return is_feat_csv2_present() &&
+		(EXTRACT(ID_AA64PFR1_CSV2_FRAC, read_id_aa64pfr1_el1())
+			== ID_AA64PFR1_CSV2_1P2_SUPPORTED);
+}
+
+static inline bool is_feat_lor_present(void)
+{
+	return EXTRACT(ID_AA64MMFR1_EL1_LO, read_id_aa64mmfr1_el1())
+		!= ID_AA64MMFR1_EL1_LOR_NOT_SUPPORTED;
+}
+
 #endif /* ARCH_FEATURES_H */
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 77dc881..39461d5 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -186,11 +186,13 @@
 
 DEFINE_SYSREG_RW_FUNCS(par_el1)
 DEFINE_SYSREG_READ_FUNC(id_pfr1_el1)
+DEFINE_SYSREG_READ_FUNC(id_aa64isar0_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64isar1_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64pfr1_el1)
 DEFINE_SYSREG_READ_FUNC(id_aa64dfr0_el1)
 DEFINE_SYSREG_READ_FUNC(id_afr0_el1)
+DEFINE_SYSREG_READ_FUNC(id_pfr0_el1)
 DEFINE_SYSREG_READ_FUNC(CurrentEl)
 DEFINE_SYSREG_READ_FUNC(ctr_el0)
 DEFINE_SYSREG_RW_FUNCS(daif)
@@ -618,6 +620,9 @@
 /* ID_AA64ISAR2_EL1 */
 DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64isar2_el1, ID_AA64ISAR2_EL1)
 
+/* ID_PFR2_EL1 */
+DEFINE_RENAME_SYSREG_READ_FUNC(id_pfr2_el1, ID_PFR2_EL1)
+
 #define IS_IN_EL(x) \
 	(GET_EL(read_CurrentEl()) == MODE_EL##x)