git: a9f6cb43abc4 - stable/13 - Move setting arm64 HWCAP values to the ID tables

Andrew Turner andrew at FreeBSD.org
Mon Aug 30 12:43:19 UTC 2021


The branch stable/13 has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=a9f6cb43abc4da25ee154a77fe25838a4841cbc3

commit a9f6cb43abc4da25ee154a77fe25838a4841cbc3
Author:     Andrew Turner <andrew at FreeBSD.org>
AuthorDate: 2021-07-16 13:49:33 +0000
Commit:     Andrew Turner <andrew at FreeBSD.org>
CommitDate: 2021-08-30 11:22:22 +0000

    Move setting arm64 HWCAP values to the ID tables
    
    The HWCAPS values are based on the ID registers. Move setting these
    to the existing ID register parsing code.
    
    Previously we would need to handle all possible ID field values where
    a HWCAP is set, however as most ID fields follow a scheme where when
    the field increments it will only add new features meaning we only
    need to check if the field is greater than when the HWCAP feature
    was added.
    
    While here stop setting HWCAP value that need kernel support, but this
    support is missing.
    
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D31201
    
    (cherry picked from commit 1a78f44cd205b6f9ca11ef5cdb6e1f32c0134193)
---
 sys/arm64/arm64/identcpu.c | 595 +++++++++++++++++++++++++--------------------
 1 file changed, 325 insertions(+), 270 deletions(-)

diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index 40f56017b9fd..193ed6427b1d 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -48,11 +48,8 @@ __FBSDID("$FreeBSD$");
 #include <machine/undefined.h>
 
 static void print_cpu_features(u_int cpu);
-static u_long parse_cpu_features_hwcap(void);
-static u_long parse_cpu_features_hwcap2(void);
 #ifdef COMPAT_FREEBSD32
 static u_long parse_cpu_features_hwcap32(void);
-static u_long parse_cpu_features_hwcap32_2(void);
 #endif
 
 char machine[] = "arm64";
@@ -285,16 +282,32 @@ struct mrs_field_value {
 
 #define	MRS_FIELD_VALUE_END	{ .desc = NULL }
 
+struct mrs_field_hwcap {
+	u_long		*hwcap;
+	uint64_t	min;
+	u_long		hwcap_val;
+};
+
+#define	MRS_HWCAP(_hwcap, _val, _min)				\
+{								\
+	.hwcap = (_hwcap),					\
+	.hwcap_val = (_val),					\
+	.min = (_min),						\
+}
+
+#define	MRS_HWCAP_END		{ .hwcap = NULL }
+
 struct mrs_field {
 	const char	*name;
 	struct mrs_field_value *values;
+	struct mrs_field_hwcap *hwcaps;
 	uint64_t	mask;
 	bool		sign;
 	u_int		type;
 	u_int		shift;
 };
 
-#define	MRS_FIELD(_register, _name, _sign, _type, _values)		\
+#define	MRS_FIELD_HWCAP(_register, _name, _sign, _type, _values, _hwcap) \
 	{								\
 		.name = #_name,						\
 		.sign = (_sign),					\
@@ -302,8 +315,12 @@ struct mrs_field {
 		.shift = _register ## _ ## _name ## _SHIFT,		\
 		.mask = _register ## _ ## _name ## _MASK,		\
 		.values = (_values),					\
+		.hwcaps = (_hwcap),					\
 	}
 
+#define	MRS_FIELD(_register, _name, _sign, _type, _values)		\
+	MRS_FIELD_HWCAP(_register, _name, _sign, _type, _values, NULL)
+
 #define	MRS_FIELD_END	{ .type = MRS_INVALID, }
 
 /* ID_AA64AFR0_EL1 */
@@ -409,6 +426,11 @@ static struct mrs_field_value id_aa64isar0_rndr[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_rndr_caps[] = {
+	MRS_HWCAP(&elf_hwcap2, HWCAP2_RNG, ID_AA64ISAR0_RNDR_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_tlb[] = {
 	MRS_FIELD_VALUE(ID_AA64ISAR0_TLB_NONE, ""),
 	MRS_FIELD_VALUE(ID_AA64ISAR0_TLB_TLBIOS, "TLBI-OS"),
@@ -423,78 +445,154 @@ static struct mrs_field_value id_aa64isar0_ts[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_ts_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_FLAGM, ID_AA64ISAR0_TS_CondM_8_4),
+	MRS_HWCAP(&elf_hwcap2, HWCAP2_FLAGM2, ID_AA64ISAR0_TS_CondM_8_5),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_fhm[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, FHM, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_fhm_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDFHM, ID_AA64ISAR0_FHM_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_dp[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, DP, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_dp_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDDP, ID_AA64ISAR0_DP_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_sm4[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SM4, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_sm4_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_SM4, ID_AA64ISAR0_SM4_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_sm3[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SM3, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_sm3_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_SM3, ID_AA64ISAR0_SM3_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_sha3[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA3, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_sha3_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_SHA3, ID_AA64ISAR0_SHA3_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_rdm[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, RDM, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_rdm_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDRDM, ID_AA64ISAR0_RDM_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_atomic[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, Atomic, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_atomic_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_ATOMICS, ID_AA64ISAR0_Atomic_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_crc32[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, CRC32, NONE, BASE),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_crc32_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_CRC32, ID_AA64ISAR0_CRC32_BASE),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_sha2[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA2, NONE, BASE),
 	MRS_FIELD_VALUE(ID_AA64ISAR0_SHA2_512, "SHA2+SHA512"),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_sha2_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_SHA2, ID_AA64ISAR0_SHA2_BASE),
+	MRS_HWCAP(&elf_hwcap, HWCAP_SHA512, ID_AA64ISAR0_SHA2_512),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_sha1[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA1, NONE, BASE),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_sha1_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_SHA1, ID_AA64ISAR0_SHA1_BASE),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar0_aes[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, AES, NONE, BASE),
 	MRS_FIELD_VALUE(ID_AA64ISAR0_AES_PMULL, "AES+PMULL"),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar0_aes_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_AES, ID_AA64ISAR0_AES_BASE),
+	MRS_HWCAP(&elf_hwcap, HWCAP_PMULL, ID_AA64ISAR0_AES_PMULL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field id_aa64isar0_fields[] = {
-	MRS_FIELD(ID_AA64ISAR0, RNDR, false, MRS_LOWER, id_aa64isar0_rndr),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, RNDR, false, MRS_LOWER,
+	    id_aa64isar0_rndr, id_aa64isar0_rndr_caps),
 	MRS_FIELD(ID_AA64ISAR0, TLB, false, MRS_EXACT, id_aa64isar0_tlb),
-	MRS_FIELD(ID_AA64ISAR0, TS, false, MRS_LOWER, id_aa64isar0_ts),
-	MRS_FIELD(ID_AA64ISAR0, FHM, false, MRS_LOWER, id_aa64isar0_fhm),
-	MRS_FIELD(ID_AA64ISAR0, DP, false, MRS_LOWER, id_aa64isar0_dp),
-	MRS_FIELD(ID_AA64ISAR0, SM4, false, MRS_LOWER, id_aa64isar0_sm4),
-	MRS_FIELD(ID_AA64ISAR0, SM3, false, MRS_LOWER, id_aa64isar0_sm3),
-	MRS_FIELD(ID_AA64ISAR0, SHA3, false, MRS_LOWER, id_aa64isar0_sha3),
-	MRS_FIELD(ID_AA64ISAR0, RDM, false, MRS_LOWER, id_aa64isar0_rdm),
-	MRS_FIELD(ID_AA64ISAR0, Atomic, false, MRS_LOWER, id_aa64isar0_atomic),
-	MRS_FIELD(ID_AA64ISAR0, CRC32, false, MRS_LOWER, id_aa64isar0_crc32),
-	MRS_FIELD(ID_AA64ISAR0, SHA2, false, MRS_LOWER, id_aa64isar0_sha2),
-	MRS_FIELD(ID_AA64ISAR0, SHA1, false, MRS_LOWER, id_aa64isar0_sha1),
-	MRS_FIELD(ID_AA64ISAR0, AES, false, MRS_LOWER, id_aa64isar0_aes),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, TS, false, MRS_LOWER, id_aa64isar0_ts,
+	    id_aa64isar0_ts_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, FHM, false, MRS_LOWER, id_aa64isar0_fhm,
+	    id_aa64isar0_fhm_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, DP, false, MRS_LOWER, id_aa64isar0_dp,
+	    id_aa64isar0_dp_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, SM4, false, MRS_LOWER, id_aa64isar0_sm4,
+	    id_aa64isar0_sm4_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, SM3, false, MRS_LOWER, id_aa64isar0_sm3,
+	    id_aa64isar0_sm3_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, SHA3, false, MRS_LOWER, id_aa64isar0_sha3,
+	    id_aa64isar0_sha3_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, RDM, false, MRS_LOWER, id_aa64isar0_rdm,
+	    id_aa64isar0_rdm_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, Atomic, false, MRS_LOWER,
+	    id_aa64isar0_atomic, id_aa64isar0_atomic_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, CRC32, false, MRS_LOWER,
+	    id_aa64isar0_crc32, id_aa64isar0_crc32_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, SHA2, false, MRS_LOWER, id_aa64isar0_sha2,
+	    id_aa64isar0_sha2_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, SHA1, false, MRS_LOWER,
+	    id_aa64isar0_sha1, id_aa64isar0_sha1_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR0, AES, false, MRS_LOWER, id_aa64isar0_aes,
+	    id_aa64isar0_aes_caps),
 	MRS_FIELD_END,
 };
 
@@ -505,16 +603,31 @@ static struct mrs_field_value id_aa64isar1_i8mm[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar1_i8mm_caps[] = {
+	MRS_HWCAP(&elf_hwcap2, HWCAP2_I8MM, ID_AA64ISAR1_I8MM_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar1_dgh[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, DGH, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar1_dgh_caps[] = {
+	MRS_HWCAP(&elf_hwcap2, HWCAP2_DGH, ID_AA64ISAR1_DGH_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar1_bf16[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, BF16, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar1_bf16_caps[] = {
+	MRS_HWCAP(&elf_hwcap2, HWCAP2_BF16, ID_AA64ISAR1_BF16_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar1_specres[] = {
 	MRS_FIELD_VALUE(ID_AA64ISAR1_SPECRES_NONE, ""),
 	MRS_FIELD_VALUE(ID_AA64ISAR1_SPECRES_IMPL, "PredInv"),
@@ -526,11 +639,21 @@ static struct mrs_field_value id_aa64isar1_sb[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar1_sb_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_SB, ID_AA64ISAR1_SB_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar1_frintts[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, FRINTTS, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar1_frintts_caps[] = {
+	MRS_HWCAP(&elf_hwcap2, HWCAP2_FRINT, ID_AA64ISAR1_FRINTTS_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar1_gpi[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, GPI, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
@@ -548,16 +671,32 @@ static struct mrs_field_value id_aa64isar1_lrcpc[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar1_lrcpc_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_LRCPC, ID_AA64ISAR1_LRCPC_RCPC_8_3),
+	MRS_HWCAP(&elf_hwcap, HWCAP_ILRCPC, ID_AA64ISAR1_LRCPC_RCPC_8_4),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar1_fcma[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, FCMA, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar1_fcma_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_FCMA, ID_AA64ISAR1_FCMA_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar1_jscvt[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, JSCVT, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar1_jscvt_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_JSCVT, ID_AA64ISAR1_JSCVT_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64isar1_api[] = {
 	MRS_FIELD_VALUE(ID_AA64ISAR1_API_NONE, ""),
 	MRS_FIELD_VALUE(ID_AA64ISAR1_API_PAC, "API PAC"),
@@ -579,23 +718,37 @@ static struct mrs_field_value id_aa64isar1_dpb[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64isar1_dpb_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_DCPOP, ID_AA64ISAR1_DPB_DCCVAP),
+	MRS_HWCAP(&elf_hwcap2, HWCAP2_DCPODP, ID_AA64ISAR1_DPB_DCCVADP),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field id_aa64isar1_fields[] = {
-	MRS_FIELD(ID_AA64ISAR1, I8MM, false, MRS_LOWER, id_aa64isar1_i8mm),
-	MRS_FIELD(ID_AA64ISAR1, DGH, false, MRS_LOWER, id_aa64isar1_dgh),
-	MRS_FIELD(ID_AA64ISAR1, BF16, false, MRS_LOWER, id_aa64isar1_bf16),
+	MRS_FIELD_HWCAP(ID_AA64ISAR1, I8MM, false, MRS_LOWER,
+	    id_aa64isar1_i8mm, id_aa64isar1_i8mm_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR1, DGH, false, MRS_LOWER, id_aa64isar1_dgh,
+	    id_aa64isar1_dgh_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR1, BF16, false, MRS_LOWER,
+	    id_aa64isar1_bf16, id_aa64isar1_bf16_caps),
 	MRS_FIELD(ID_AA64ISAR1, SPECRES, false, MRS_EXACT,
 	    id_aa64isar1_specres),
-	MRS_FIELD(ID_AA64ISAR1, SB, false, MRS_LOWER, id_aa64isar1_sb),
-	MRS_FIELD(ID_AA64ISAR1, FRINTTS, false, MRS_LOWER,
-	    id_aa64isar1_frintts),
+	MRS_FIELD_HWCAP(ID_AA64ISAR1, SB, false, MRS_LOWER, id_aa64isar1_sb,
+	    id_aa64isar1_sb_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR1, FRINTTS, false, MRS_LOWER,
+	    id_aa64isar1_frintts, id_aa64isar1_frintts_caps),
 	MRS_FIELD(ID_AA64ISAR1, GPI, false, MRS_EXACT, id_aa64isar1_gpi),
 	MRS_FIELD(ID_AA64ISAR1, GPA, false, MRS_EXACT, id_aa64isar1_gpa),
-	MRS_FIELD(ID_AA64ISAR1, LRCPC, false, MRS_LOWER, id_aa64isar1_lrcpc),
-	MRS_FIELD(ID_AA64ISAR1, FCMA, false, MRS_LOWER, id_aa64isar1_fcma),
-	MRS_FIELD(ID_AA64ISAR1, JSCVT, false, MRS_LOWER, id_aa64isar1_jscvt),
+	MRS_FIELD_HWCAP(ID_AA64ISAR1, LRCPC, false, MRS_LOWER,
+	    id_aa64isar1_lrcpc, id_aa64isar1_lrcpc_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR1, FCMA, false, MRS_LOWER,
+	    id_aa64isar1_fcma, id_aa64isar1_fcma_caps),
+	MRS_FIELD_HWCAP(ID_AA64ISAR1, JSCVT, false, MRS_LOWER,
+	    id_aa64isar1_jscvt, id_aa64isar1_jscvt_caps),
 	MRS_FIELD(ID_AA64ISAR1, API, false, MRS_EXACT, id_aa64isar1_api),
 	MRS_FIELD(ID_AA64ISAR1, APA, false, MRS_EXACT, id_aa64isar1_apa),
-	MRS_FIELD(ID_AA64ISAR1, DPB, false, MRS_LOWER, id_aa64isar1_dpb),
+	MRS_FIELD_HWCAP(ID_AA64ISAR1, DPB, false, MRS_LOWER, id_aa64isar1_dpb,
+	    id_aa64isar1_dpb_caps),
 	MRS_FIELD_END,
 };
 
@@ -801,6 +954,11 @@ static struct mrs_field_value id_aa64mmfr2_at[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64mmfr2_at_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_USCAT, ID_AA64MMFR2_AT_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64mmfr2_st[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, ST, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
@@ -851,7 +1009,8 @@ static struct mrs_field id_aa64mmfr2_fields[] = {
 	MRS_FIELD(ID_AA64MMFR2, TTL, false, MRS_EXACT, id_aa64mmfr2_ttl),
 	MRS_FIELD(ID_AA64MMFR2, FWB, false, MRS_EXACT, id_aa64mmfr2_fwb),
 	MRS_FIELD(ID_AA64MMFR2, IDS, false, MRS_EXACT, id_aa64mmfr2_ids),
-	MRS_FIELD(ID_AA64MMFR2, AT, false, MRS_LOWER, id_aa64mmfr2_at),
+	MRS_FIELD_HWCAP(ID_AA64MMFR2, AT, false, MRS_LOWER, id_aa64mmfr2_at,
+	    id_aa64mmfr2_at_caps),
 	MRS_FIELD(ID_AA64MMFR2, ST, false, MRS_EXACT, id_aa64mmfr2_st),
 	MRS_FIELD(ID_AA64MMFR2, NV, false, MRS_EXACT, id_aa64mmfr2_nv),
 	MRS_FIELD(ID_AA64MMFR2, CCIDX, false, MRS_EXACT, id_aa64mmfr2_ccidx),
@@ -885,6 +1044,11 @@ static struct mrs_field_value id_aa64pfr0_dit[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64pfr0_dit_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_DIT, ID_AA64PFR0_DIT_PSTATE),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64pfr0_amu[] = {
 	MRS_FIELD_VALUE(ID_AA64PFR0_AMU_NONE, ""),
 	MRS_FIELD_VALUE(ID_AA64PFR0_AMU_V1, "AMUv1"),
@@ -906,6 +1070,14 @@ static struct mrs_field_value id_aa64pfr0_sve[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+#if 0
+/* Enable when we add SVE support */
+static struct mrs_field_hwcap id_aa64pfr0_sve_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_SVE, ID_AA64PFR0_SVE_IMPL),
+	MRS_HWCAP_END
+};
+#endif
+
 static struct mrs_field_value id_aa64pfr0_ras[] = {
 	MRS_FIELD_VALUE(ID_AA64PFR0_RAS_NONE, ""),
 	MRS_FIELD_VALUE(ID_AA64PFR0_RAS_IMPL, "RAS"),
@@ -924,12 +1096,24 @@ static struct mrs_field_value id_aa64pfr0_advsimd[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64pfr0_advsimd_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_ASIMD, ID_AA64PFR0_AdvSIMD_IMPL),
+	MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDHP, ID_AA64PFR0_AdvSIMD_HP),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64pfr0_fp[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, FP, NONE, IMPL),
 	MRS_FIELD_VALUE(ID_AA64PFR0_FP_HP, "FP+HP"),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64pfr0_fp_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_FP, ID_AA64PFR0_FP_IMPL),
+	MRS_HWCAP(&elf_hwcap, HWCAP_FPHP, ID_AA64PFR0_FP_HP),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64pfr0_el3[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, EL3, NONE, 64),
 	MRS_FIELD_VALUE(ID_AA64PFR0_EL3_64_32, "EL3 32"),
@@ -957,15 +1141,18 @@ static struct mrs_field_value id_aa64pfr0_el0[] = {
 static struct mrs_field id_aa64pfr0_fields[] = {
 	MRS_FIELD(ID_AA64PFR0, CSV3, false, MRS_EXACT, id_aa64pfr0_csv3),
 	MRS_FIELD(ID_AA64PFR0, CSV2, false, MRS_EXACT, id_aa64pfr0_csv2),
-	MRS_FIELD(ID_AA64PFR0, DIT, false, MRS_LOWER, id_aa64pfr0_dit),
+	MRS_FIELD_HWCAP(ID_AA64PFR0, DIT, false, MRS_LOWER, id_aa64pfr0_dit,
+	    id_aa64pfr0_dit_caps),
 	MRS_FIELD(ID_AA64PFR0, AMU, false, MRS_EXACT, id_aa64pfr0_amu),
 	MRS_FIELD(ID_AA64PFR0, MPAM, false, MRS_EXACT, id_aa64pfr0_mpam),
 	MRS_FIELD(ID_AA64PFR0, SEL2, false, MRS_EXACT, id_aa64pfr0_sel2),
 	MRS_FIELD(ID_AA64PFR0, SVE, false, MRS_EXACT, id_aa64pfr0_sve),
 	MRS_FIELD(ID_AA64PFR0, RAS, false, MRS_EXACT, id_aa64pfr0_ras),
 	MRS_FIELD(ID_AA64PFR0, GIC, false, MRS_EXACT, id_aa64pfr0_gic),
-	MRS_FIELD(ID_AA64PFR0, AdvSIMD, true, MRS_LOWER, id_aa64pfr0_advsimd),
-	MRS_FIELD(ID_AA64PFR0, FP, true,  MRS_LOWER, id_aa64pfr0_fp),
+	MRS_FIELD_HWCAP(ID_AA64PFR0, AdvSIMD, true, MRS_LOWER,
+	    id_aa64pfr0_advsimd, id_aa64pfr0_advsimd_caps),
+	MRS_FIELD_HWCAP(ID_AA64PFR0, FP, true,  MRS_LOWER, id_aa64pfr0_fp,
+	    id_aa64pfr0_fp_caps),
 	MRS_FIELD(ID_AA64PFR0, EL3, false, MRS_EXACT, id_aa64pfr0_el3),
 	MRS_FIELD(ID_AA64PFR0, EL2, false, MRS_EXACT, id_aa64pfr0_el2),
 	MRS_FIELD(ID_AA64PFR0, EL1, false, MRS_LOWER, id_aa64pfr0_el1),
@@ -989,15 +1176,29 @@ static struct mrs_field_value id_aa64pfr1_ssbs[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_aa64pfr1_ssbs_caps[] = {
+	MRS_HWCAP(&elf_hwcap, HWCAP_SSBS, ID_AA64PFR1_SSBS_PSTATE),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_aa64pfr1_bt[] = {
 	MRS_FIELD_VALUE(ID_AA64PFR1_BT_NONE, ""),
 	MRS_FIELD_VALUE(ID_AA64PFR1_BT_IMPL, "BTI"),
 	MRS_FIELD_VALUE_END,
 };
 
+#if 0
+/* Enable when we add BTI support */
+static struct mrs_field_hwcap id_aa64pfr1_bt_caps[] = {
+	MRS_HWCAP(&elf_hwcap2, HWCAP2_BTI, ID_AA64PFR1_BT_IMPL),
+	MRS_HWCAP_END
+};
+#endif
+
 static struct mrs_field id_aa64pfr1_fields[] = {
 	MRS_FIELD(ID_AA64PFR1, MTE, false, MRS_EXACT, id_aa64pfr1_mte),
-	MRS_FIELD(ID_AA64PFR1, SSBS, false, MRS_LOWER, id_aa64pfr1_ssbs),
+	MRS_FIELD_HWCAP(ID_AA64PFR1, SSBS, false, MRS_LOWER, id_aa64pfr1_ssbs,
+	    id_aa64pfr1_ssbs_caps),
 	MRS_FIELD(ID_AA64PFR1, BT, false, MRS_EXACT, id_aa64pfr1_bt),
 	MRS_FIELD_END,
 };
@@ -1019,22 +1220,43 @@ static struct mrs_field_value id_isar5_crc32[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_isar5_crc32_caps[] = {
+	MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_CRC32, ID_ISAR5_CRC32_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_isar5_sha2[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, SHA2, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_isar5_sha2_caps[] = {
+	MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_SHA2, ID_ISAR5_SHA2_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_isar5_sha1[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, SHA1, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_isar5_sha1_caps[] = {
+	MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_SHA1, ID_ISAR5_SHA1_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_isar5_aes[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, AES, NONE, BASE),
 	MRS_FIELD_VALUE(ID_ISAR5_AES_VMULL, "AES+VMULL"),
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap id_isar5_aes_caps[] = {
+	MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_AES, ID_ISAR5_AES_BASE),
+	MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_PMULL, ID_ISAR5_AES_VMULL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value id_isar5_sevl[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, SEVL, NOP, IMPL),
 	MRS_FIELD_VALUE_END,
@@ -1043,10 +1265,14 @@ static struct mrs_field_value id_isar5_sevl[] = {
 static struct mrs_field id_isar5_fields[] = {
 	MRS_FIELD(ID_ISAR5, VCMA, false, MRS_LOWER, id_isar5_vcma),
 	MRS_FIELD(ID_ISAR5, RDM, false, MRS_LOWER, id_isar5_rdm),
-	MRS_FIELD(ID_ISAR5, CRC32, false, MRS_LOWER, id_isar5_crc32),
-	MRS_FIELD(ID_ISAR5, SHA2, false, MRS_LOWER, id_isar5_sha2),
-	MRS_FIELD(ID_ISAR5, SHA1, false, MRS_LOWER, id_isar5_sha1),
-	MRS_FIELD(ID_ISAR5, AES, false, MRS_LOWER, id_isar5_aes),
+	MRS_FIELD_HWCAP(ID_ISAR5, CRC32, false, MRS_LOWER, id_isar5_crc32,
+	    id_isar5_crc32_caps),
+	MRS_FIELD_HWCAP(ID_ISAR5, SHA2, false, MRS_LOWER, id_isar5_sha2,
+	    id_isar5_sha2_caps),
+	MRS_FIELD_HWCAP(ID_ISAR5, SHA1, false, MRS_LOWER, id_isar5_sha1,
+	    id_isar5_sha1_caps),
+	MRS_FIELD_HWCAP(ID_ISAR5, AES, false, MRS_LOWER, id_isar5_aes,
+	    id_isar5_aes_caps),
 	MRS_FIELD(ID_ISAR5, SEVL, false, MRS_LOWER, id_isar5_sevl),
 	MRS_FIELD_END,
 };
@@ -1079,6 +1305,11 @@ static struct mrs_field_value mvfr0_fpdp[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap mvfr0_fpdp_caps[] = {
+	MRS_HWCAP(&elf32_hwcap, HWCAP32_VFP, MVFR0_FPDP_VFP_v2),
+	MRS_HWCAP(&elf32_hwcap, HWCAP32_VFPv3, MVFR0_FPDP_VFP_v3_v4),
+};
+
 static struct mrs_field_value mvfr0_fpsp[] = {
 	MRS_FIELD_VALUE(MVFR0_FPSP_NONE, ""),
 	MRS_FIELD_VALUE(MVFR0_FPSP_VFP_v2, "SP VFPv2"),
@@ -1098,7 +1329,8 @@ static struct mrs_field mvfr0_fields[] = {
 	MRS_FIELD(MVFR0, FPSqrt, false, MRS_LOWER, mvfr0_fpsqrt),
 	MRS_FIELD(MVFR0, FPDivide, false, MRS_LOWER, mvfr0_fpdivide),
 	MRS_FIELD(MVFR0, FPTrap, false, MRS_LOWER, mvfr0_fptrap),
-	MRS_FIELD(MVFR0, FPDP, false, MRS_LOWER, mvfr0_fpdp),
+	MRS_FIELD_HWCAP(MVFR0, FPDP, false, MRS_LOWER, mvfr0_fpdp,
+	    mvfr0_fpdp_caps),
 	MRS_FIELD(MVFR0, FPSP, false, MRS_LOWER, mvfr0_fpsp),
 	MRS_FIELD(MVFR0, SIMDReg, false, MRS_LOWER, mvfr0_simdreg),
 	MRS_FIELD_END,
@@ -1110,6 +1342,11 @@ static struct mrs_field_value mvfr1_simdfmac[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap mvfr1_simdfmac_caps[] = {
+	MRS_HWCAP(&elf32_hwcap, HWCAP32_VFPv4, MVFR1_SIMDFMAC_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value mvfr1_fphp[] = {
 	MRS_FIELD_VALUE(MVFR1_FPHP_NONE, ""),
 	MRS_FIELD_VALUE(MVFR1_FPHP_CONV_SP, "FPHP SP Conv"),
@@ -1140,6 +1377,11 @@ static struct mrs_field_value mvfr1_simdls[] = {
 	MRS_FIELD_VALUE_END,
 };
 
+static struct mrs_field_hwcap mvfr1_simdls_caps[] = {
+	MRS_HWCAP(&elf32_hwcap, HWCAP32_VFPv4, MVFR1_SIMDFMAC_IMPL),
+	MRS_HWCAP_END
+};
+
 static struct mrs_field_value mvfr1_fpdnan[] = {
 	MRS_FIELD_VALUE_NONE_IMPL(MVFR1, FPDNaN, NONE, IMPL),
 	MRS_FIELD_VALUE_END,
@@ -1151,12 +1393,14 @@ static struct mrs_field_value mvfr1_fpftz[] = {
 };
 
 static struct mrs_field mvfr1_fields[] = {
-	MRS_FIELD(MVFR1, SIMDFMAC, false, MRS_LOWER, mvfr1_simdfmac),
+	MRS_FIELD_HWCAP(MVFR1, SIMDFMAC, false, MRS_LOWER, mvfr1_simdfmac,
+	    mvfr1_simdfmac_caps),
 	MRS_FIELD(MVFR1, FPHP, false, MRS_LOWER, mvfr1_fphp),
 	MRS_FIELD(MVFR1, SIMDHP, false, MRS_LOWER, mvfr1_simdhp),
 	MRS_FIELD(MVFR1, SIMDSP, false, MRS_LOWER, mvfr1_simdsp),
 	MRS_FIELD(MVFR1, SIMDInt, false, MRS_LOWER, mvfr1_simdint),
-	MRS_FIELD(MVFR1, SIMDLS, false, MRS_LOWER, mvfr1_simdls),
+	MRS_FIELD_HWCAP(MVFR1, SIMDLS, false, MRS_LOWER, mvfr1_simdls,
+	    mvfr1_simdls_caps),
 	MRS_FIELD(MVFR1, FPDNaN, false, MRS_LOWER, mvfr1_fpdnan),
 	MRS_FIELD(MVFR1, FPFtZ, false, MRS_LOWER, mvfr1_fpftz),
 	MRS_FIELD_END,
@@ -1424,6 +1668,41 @@ int64_t dcache_line_size;	/* The minimum D cache line size */
 int64_t icache_line_size;	/* The minimum I cache line size */
 int64_t idcache_line_size;	/* The minimum cache line size */
 
+/*
+ * Find the values to export to userspace as AT_HWCAP and AT_HWCAP2.
+ */
+static void
+parse_cpu_features(void)
+{
+	struct mrs_field_hwcap *hwcaps;
+	struct mrs_field *fields;
+	uint64_t min, reg;
+	int i, j, k;
+
+	for (i = 0; i < nitems(user_regs); i++) {
+		reg = CPU_DESC_FIELD(user_cpu_desc, i);
+		fields = user_regs[i].fields;
+		for (j = 0; fields[j].type != 0; j++) {
+			hwcaps = fields[j].hwcaps;
+			if (hwcaps == NULL)
+				continue;
+
+			for (k = 0; hwcaps[k].hwcap != NULL; k++) {
+				min = hwcaps[k].min;
+
+				/*
+				 * If the field is greater than the minimum
+				 * value we can set the hwcap;
+				 */
+				if (mrs_field_cmp(reg, min, fields[j].shift,
+				    4, fields[j].sign) >= 0) {
+					*hwcaps[k].hwcap |= hwcaps[k].hwcap_val;
+				}
+			}
+		}
+	}
+}
+
 static void
 identify_cpu_sysinit(void *dummy __unused)
 {
@@ -1444,14 +1723,12 @@ identify_cpu_sysinit(void *dummy __unused)
 			idc = false;
 	}
 
-	/* Exposed to userspace as AT_HWCAP and AT_HWCAP2 */
-	elf_hwcap = parse_cpu_features_hwcap();
-	elf_hwcap2 = parse_cpu_features_hwcap2();
+	/* Find the values to export to userspace as AT_HWCAP and AT_HWCAP2 */
+	parse_cpu_features();
 
 #ifdef COMPAT_FREEBSD32
-	/* 32-bit ARM versions of AT_HWCAP/HWCAP2 */
-	elf32_hwcap = parse_cpu_features_hwcap32();
-	elf32_hwcap2 = parse_cpu_features_hwcap32_2();
+	/* Set the default caps and any that need to check multiple fields */
+	elf32_hwcap |= parse_cpu_features_hwcap32();
 #endif
 
 	if (dic && idc) {
@@ -1485,244 +1762,22 @@ cpu_features_sysinit(void *dummy __unused)
 /* Log features before APs are released and start printing to the dmesg. */
 SYSINIT(cpu_features, SI_SUB_SMP - 1, SI_ORDER_ANY, cpu_features_sysinit, NULL);
 
-static u_long
-parse_cpu_features_hwcap(void)
-{
-	u_long hwcap = 0;
-
-	switch (ID_AA64ISAR0_TS_VAL(user_cpu_desc.id_aa64isar0)) {
-	case ID_AA64ISAR0_TS_CondM_8_4:
-	case ID_AA64ISAR0_TS_CondM_8_5:
-		hwcap |= HWCAP_FLAGM;
-		break;
-	default:
-		break;
-	}
-
-	if (ID_AA64ISAR0_FHM_VAL(user_cpu_desc.id_aa64isar0) ==
-	    ID_AA64ISAR0_FHM_IMPL)
-		hwcap |= HWCAP_ASIMDFHM;
-
-	if (ID_AA64ISAR0_DP_VAL(user_cpu_desc.id_aa64isar0) ==
-	    ID_AA64ISAR0_DP_IMPL)
-		hwcap |= HWCAP_ASIMDDP;
-
-	if (ID_AA64ISAR0_SM4_VAL(user_cpu_desc.id_aa64isar0) ==
-	    ID_AA64ISAR0_SM4_IMPL)
-		hwcap |= HWCAP_SM4;
-
-	if (ID_AA64ISAR0_SM3_VAL(user_cpu_desc.id_aa64isar0) ==
-	    ID_AA64ISAR0_SM3_IMPL)
-		hwcap |= HWCAP_SM3;
-
-	if (ID_AA64ISAR0_SHA3_VAL(user_cpu_desc.id_aa64isar0) ==
-	    ID_AA64ISAR0_SHA3_IMPL)
-		hwcap |= HWCAP_SHA3;
-
-	if (ID_AA64ISAR0_RDM_VAL(user_cpu_desc.id_aa64isar0) ==
-	    ID_AA64ISAR0_RDM_IMPL)
-		hwcap |= HWCAP_ASIMDRDM;
-
-	if (ID_AA64ISAR0_Atomic_VAL(user_cpu_desc.id_aa64isar0) ==
-	    ID_AA64ISAR0_Atomic_IMPL)
-		hwcap |= HWCAP_ATOMICS;
-
-	if (ID_AA64ISAR0_CRC32_VAL(user_cpu_desc.id_aa64isar0) ==
-	    ID_AA64ISAR0_CRC32_BASE)
-		hwcap |= HWCAP_CRC32;
-
-	switch (ID_AA64ISAR0_SHA2_VAL(user_cpu_desc.id_aa64isar0)) {
-	case ID_AA64ISAR0_SHA2_BASE:
-		hwcap |= HWCAP_SHA2;
-		break;
-	case ID_AA64ISAR0_SHA2_512:
-		hwcap |= HWCAP_SHA2 | HWCAP_SHA512;
-		break;
-	default:
-		break;
-	}
-
-	if (ID_AA64ISAR0_SHA1_VAL(user_cpu_desc.id_aa64isar0) ==
-	    ID_AA64ISAR0_SHA1_BASE)
-		hwcap |= HWCAP_SHA1;
-
-	switch (ID_AA64ISAR0_AES_VAL(user_cpu_desc.id_aa64isar0)) {
-	case ID_AA64ISAR0_AES_BASE:
-		hwcap |= HWCAP_AES;
-		break;
-	case ID_AA64ISAR0_AES_PMULL:
-		hwcap |= HWCAP_PMULL | HWCAP_AES;
-		break;
-	default:
-		break;
-	}
-
-	if (ID_AA64ISAR1_SB_VAL(user_cpu_desc.id_aa64isar1) ==
-	    ID_AA64ISAR1_SB_IMPL)
-		hwcap |= HWCAP_SB;
-
-	switch (ID_AA64ISAR1_LRCPC_VAL(user_cpu_desc.id_aa64isar1)) {
-	case ID_AA64ISAR1_LRCPC_RCPC_8_3:
-		hwcap |= HWCAP_LRCPC;
-		break;
-	case ID_AA64ISAR1_LRCPC_RCPC_8_4:
-		hwcap |= HWCAP_LRCPC | HWCAP_ILRCPC;
-		break;
-	default:
-		break;
-	}
-
-	if (ID_AA64ISAR1_FCMA_VAL(user_cpu_desc.id_aa64isar1) ==
-	    ID_AA64ISAR1_FCMA_IMPL)
-		hwcap |= HWCAP_FCMA;
-
-	if (ID_AA64ISAR1_JSCVT_VAL(user_cpu_desc.id_aa64isar1) ==
-	    ID_AA64ISAR1_JSCVT_IMPL)
-		hwcap |= HWCAP_JSCVT;
-
-	if (ID_AA64ISAR1_DPB_VAL(user_cpu_desc.id_aa64isar1) ==
-	    ID_AA64ISAR1_DPB_DCCVAP)
-		hwcap |= HWCAP_DCPOP;
-
-	if (ID_AA64MMFR2_AT_VAL(user_cpu_desc.id_aa64mmfr2) ==
-	    ID_AA64MMFR2_AT_IMPL)
-		hwcap |= HWCAP_USCAT;
-
-	if (ID_AA64PFR0_DIT_VAL(user_cpu_desc.id_aa64pfr0) ==
-	    ID_AA64PFR0_DIT_PSTATE)
-		hwcap |= HWCAP_DIT;
-
-	if (ID_AA64PFR0_SVE_VAL(user_cpu_desc.id_aa64pfr0) ==
-	    ID_AA64PFR0_SVE_IMPL)
-		hwcap |= HWCAP_SVE;
-
-	switch (ID_AA64PFR0_AdvSIMD_VAL(user_cpu_desc.id_aa64pfr0)) {
-	case ID_AA64PFR0_AdvSIMD_IMPL:
-		hwcap |= HWCAP_ASIMD;
-		break;
-	case ID_AA64PFR0_AdvSIMD_HP:
-		hwcap |= HWCAP_ASIMD | HWCAP_ASIMDHP;
-		break;
-	default:
-		break;
-	}
-
-	switch (ID_AA64PFR0_FP_VAL(user_cpu_desc.id_aa64pfr0)) {
-	case ID_AA64PFR0_FP_IMPL:
-		hwcap |= HWCAP_FP;
-		break;
-	case ID_AA64PFR0_FP_HP:
-		hwcap |= HWCAP_FP | HWCAP_FPHP;
-		break;
-	default:
-		break;
-	}
-
-	if (ID_AA64PFR1_SSBS_VAL(user_cpu_desc.id_aa64pfr1) ==
-	    ID_AA64PFR1_SSBS_PSTATE_MSR)
-		hwcap |= HWCAP_SSBS;
-
-	return (hwcap);
-}
-
-static u_long
-parse_cpu_features_hwcap2(void)
-{
-	u_long hwcap2 = 0;
-
-	if (ID_AA64ISAR0_RNDR_VAL(user_cpu_desc.id_aa64isar0) ==
-	    ID_AA64ISAR0_RNDR_IMPL)
-		hwcap2 |= HWCAP2_RNG;
-
-	if (ID_AA64ISAR0_TS_VAL(user_cpu_desc.id_aa64isar0) ==
-	    ID_AA64ISAR0_TS_CondM_8_5)
-		hwcap2 |= HWCAP2_FLAGM2;
-
-	if (ID_AA64ISAR1_I8MM_VAL(user_cpu_desc.id_aa64isar1) ==
-	    ID_AA64ISAR1_I8MM_IMPL)
-		hwcap2 |= HWCAP2_I8MM;
-
-	if (ID_AA64ISAR1_DGH_VAL(user_cpu_desc.id_aa64isar1) ==
-	    ID_AA64ISAR1_DGH_IMPL)
-		hwcap2 |= HWCAP2_DGH;
-
-	if (ID_AA64ISAR1_BF16_VAL(user_cpu_desc.id_aa64isar1) ==
-	    ID_AA64ISAR1_BF16_IMPL)
-		hwcap2 |= HWCAP2_BF16;
-
-	if (ID_AA64ISAR1_FRINTTS_VAL(user_cpu_desc.id_aa64isar1) ==
-	    ID_AA64ISAR1_FRINTTS_IMPL)
-		hwcap2 |= HWCAP2_FRINT;
-
-	if (ID_AA64ISAR1_DPB_VAL(user_cpu_desc.id_aa64isar1) ==
-	    ID_AA64ISAR1_DPB_DCCVADP)
-		hwcap2 |= HWCAP2_DCPODP;
-
-	if (ID_AA64PFR1_BT_VAL(user_cpu_desc.id_aa64pfr1) ==
-	    ID_AA64PFR1_BT_IMPL)
-		hwcap2 |= HWCAP2_BTI;
-
-	return (hwcap2);
-}
-
 #ifdef COMPAT_FREEBSD32
 static u_long
 parse_cpu_features_hwcap32(void)
 {
 	u_long hwcap = HWCAP32_DEFAULT;
 
-	if (MVFR0_FPDP_VAL(user_cpu_desc.mvfr0) >=
-	    MVFR0_FPDP_VFP_v2) {
-		hwcap |= HWCAP32_VFP;
-
-		if (MVFR0_FPDP_VAL(user_cpu_desc.mvfr0) ==
-		    MVFR0_FPDP_VFP_v3_v4) {
-			hwcap |= HWCAP32_VFPv3;
-
-			if (MVFR1_SIMDFMAC_VAL(user_cpu_desc.mvfr1) ==
-			    MVFR1_SIMDFMAC_IMPL)
-				hwcap |= HWCAP32_VFPv4;
-		}
-	}
-
-	if ((MVFR1_SIMDLS_VAL(user_cpu_desc.mvfr1) ==
+	if ((MVFR1_SIMDLS_VAL(user_cpu_desc.mvfr1) >=
 	     MVFR1_SIMDLS_IMPL) &&
-	    (MVFR1_SIMDInt_VAL(user_cpu_desc.mvfr1) ==
+	    (MVFR1_SIMDInt_VAL(user_cpu_desc.mvfr1) >=
 	     MVFR1_SIMDInt_IMPL) &&
-	    (MVFR1_SIMDSP_VAL(user_cpu_desc.mvfr1) ==
+	    (MVFR1_SIMDSP_VAL(user_cpu_desc.mvfr1) >=
 	     MVFR1_SIMDSP_IMPL))
 		hwcap |= HWCAP32_NEON;
 
 	return (hwcap);
 }
-
-static u_long
-parse_cpu_features_hwcap32_2(void)
-{
-	u_long hwcap2 = 0;
-
-	if (ID_ISAR5_AES_VAL(user_cpu_desc.id_isar5) >=
-	    ID_ISAR5_AES_BASE)
-		hwcap2 |= HWCAP32_2_AES;
-
-	if (ID_ISAR5_AES_VAL(user_cpu_desc.id_isar5) ==
-	    ID_ISAR5_AES_VMULL)
-		hwcap2 |= HWCAP32_2_PMULL;
-
-	if (ID_ISAR5_SHA1_VAL(user_cpu_desc.id_isar5) ==
-	    ID_ISAR5_SHA1_IMPL)
-		hwcap2 |= HWCAP32_2_SHA1;
-
-	if (ID_ISAR5_SHA2_VAL(user_cpu_desc.id_isar5) ==
-	    ID_ISAR5_SHA2_IMPL)
-		hwcap2 |= HWCAP32_2_SHA2;
-
-	if (ID_ISAR5_CRC32_VAL(user_cpu_desc.id_isar5) ==
-	    ID_ISAR5_CRC32_IMPL)
-		hwcap2 |= HWCAP32_2_CRC32;
-
-	return (hwcap2);
-}
 #endif /* COMPAT_FREEBSD32 */
 
 static void


More information about the dev-commits-src-all mailing list