git: 148222e3a099 - stable/14 - arm64: Use a hwcap ID rather than pointer

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Mon, 19 Feb 2024 16:45:21 UTC
The branch stable/14 has been updated by andrew:

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

commit 148222e3a09965a7d8af72d00ee4584a0df16ca7
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2023-10-26 10:21:57 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2024-02-19 13:13:30 +0000

    arm64: Use a hwcap ID rather than pointer
    
    To allow for a different Linux hwcap value store the hwcap ID rather
    than a pointer to elf{32,}_hwcap{2,}. This will be needed when creating
    a different view of the ID registers for FreeBSD and Linux.
    
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D42371
    
    (cherry picked from commit c9e8b4b27966acf710f86d8c9f867f857f05f2c3)
---
 sys/arm64/arm64/identcpu.c | 133 +++++++++++++++++++++++++--------------------
 1 file changed, 74 insertions(+), 59 deletions(-)

diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index b1d963c07630..7acce7f5fc5b 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -317,19 +317,19 @@ 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;
+	u_int		hwcap_id;
 };
 
-#define	MRS_HWCAP(_hwcap, _val, _min)				\
+#define	MRS_HWCAP(_hwcap_id, _val, _min)			\
 {								\
-	.hwcap = (_hwcap),					\
+	.hwcap_id = (_hwcap_id),				\
 	.hwcap_val = (_val),					\
 	.min = (_min),						\
 }
 
-#define	MRS_HWCAP_END		{ .hwcap = NULL }
+#define	MRS_HWCAP_END		{ .hwcap_id = 0 }
 
 struct mrs_field {
 	const char	*name;
@@ -493,7 +493,7 @@ static const struct mrs_field_value id_aa64isar0_rndr[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar0_rndr_caps[] = {
-	MRS_HWCAP(&elf_hwcap2, HWCAP2_RNG, ID_AA64ISAR0_RNDR_IMPL),
+	MRS_HWCAP(2, HWCAP2_RNG, ID_AA64ISAR0_RNDR_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -512,8 +512,8 @@ static const struct mrs_field_value id_aa64isar0_ts[] = {
 };
 
 static const 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(1, HWCAP_FLAGM, ID_AA64ISAR0_TS_CondM_8_4),
+	MRS_HWCAP(2, HWCAP2_FLAGM2, ID_AA64ISAR0_TS_CondM_8_5),
 	MRS_HWCAP_END
 };
 
@@ -523,7 +523,7 @@ static const struct mrs_field_value id_aa64isar0_fhm[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar0_fhm_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDFHM, ID_AA64ISAR0_FHM_IMPL),
+	MRS_HWCAP(1, HWCAP_ASIMDFHM, ID_AA64ISAR0_FHM_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -533,7 +533,7 @@ static const struct mrs_field_value id_aa64isar0_dp[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar0_dp_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDDP, ID_AA64ISAR0_DP_IMPL),
+	MRS_HWCAP(1, HWCAP_ASIMDDP, ID_AA64ISAR0_DP_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -543,7 +543,7 @@ static const struct mrs_field_value id_aa64isar0_sm4[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar0_sm4_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_SM4, ID_AA64ISAR0_SM4_IMPL),
+	MRS_HWCAP(1, HWCAP_SM4, ID_AA64ISAR0_SM4_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -553,7 +553,7 @@ static const struct mrs_field_value id_aa64isar0_sm3[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar0_sm3_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_SM3, ID_AA64ISAR0_SM3_IMPL),
+	MRS_HWCAP(1, HWCAP_SM3, ID_AA64ISAR0_SM3_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -563,7 +563,7 @@ static const struct mrs_field_value id_aa64isar0_sha3[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar0_sha3_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_SHA3, ID_AA64ISAR0_SHA3_IMPL),
+	MRS_HWCAP(1, HWCAP_SHA3, ID_AA64ISAR0_SHA3_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -573,7 +573,7 @@ static const struct mrs_field_value id_aa64isar0_rdm[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar0_rdm_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDRDM, ID_AA64ISAR0_RDM_IMPL),
+	MRS_HWCAP(1, HWCAP_ASIMDRDM, ID_AA64ISAR0_RDM_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -588,7 +588,7 @@ static const struct mrs_field_value id_aa64isar0_atomic[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar0_atomic_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_ATOMICS, ID_AA64ISAR0_Atomic_IMPL),
+	MRS_HWCAP(1, HWCAP_ATOMICS, ID_AA64ISAR0_Atomic_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -598,7 +598,7 @@ static const struct mrs_field_value id_aa64isar0_crc32[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar0_crc32_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_CRC32, ID_AA64ISAR0_CRC32_BASE),
+	MRS_HWCAP(1, HWCAP_CRC32, ID_AA64ISAR0_CRC32_BASE),
 	MRS_HWCAP_END
 };
 
@@ -609,8 +609,8 @@ static const struct mrs_field_value id_aa64isar0_sha2[] = {
 };
 
 static const 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(1, HWCAP_SHA2, ID_AA64ISAR0_SHA2_BASE),
+	MRS_HWCAP(1, HWCAP_SHA512, ID_AA64ISAR0_SHA2_512),
 	MRS_HWCAP_END
 };
 
@@ -620,7 +620,7 @@ static const struct mrs_field_value id_aa64isar0_sha1[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar0_sha1_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_SHA1, ID_AA64ISAR0_SHA1_BASE),
+	MRS_HWCAP(1, HWCAP_SHA1, ID_AA64ISAR0_SHA1_BASE),
 	MRS_HWCAP_END
 };
 
@@ -631,8 +631,8 @@ static const struct mrs_field_value id_aa64isar0_aes[] = {
 };
 
 static const 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(1, HWCAP_AES, ID_AA64ISAR0_AES_BASE),
+	MRS_HWCAP(1, HWCAP_PMULL, ID_AA64ISAR0_AES_PMULL),
 	MRS_HWCAP_END
 };
 
@@ -688,7 +688,7 @@ static const struct mrs_field_value id_aa64isar1_i8mm[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar1_i8mm_caps[] = {
-	MRS_HWCAP(&elf_hwcap2, HWCAP2_I8MM, ID_AA64ISAR1_I8MM_IMPL),
+	MRS_HWCAP(2, HWCAP2_I8MM, ID_AA64ISAR1_I8MM_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -698,7 +698,7 @@ static const struct mrs_field_value id_aa64isar1_dgh[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar1_dgh_caps[] = {
-	MRS_HWCAP(&elf_hwcap2, HWCAP2_DGH, ID_AA64ISAR1_DGH_IMPL),
+	MRS_HWCAP(2, HWCAP2_DGH, ID_AA64ISAR1_DGH_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -709,7 +709,7 @@ static const struct mrs_field_value id_aa64isar1_bf16[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar1_bf16_caps[] = {
-	MRS_HWCAP(&elf_hwcap2, HWCAP2_BF16, ID_AA64ISAR1_BF16_IMPL),
+	MRS_HWCAP(2, HWCAP2_BF16, ID_AA64ISAR1_BF16_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -725,7 +725,7 @@ static const struct mrs_field_value id_aa64isar1_sb[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar1_sb_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_SB, ID_AA64ISAR1_SB_IMPL),
+	MRS_HWCAP(1, HWCAP_SB, ID_AA64ISAR1_SB_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -735,7 +735,7 @@ static const struct mrs_field_value id_aa64isar1_frintts[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar1_frintts_caps[] = {
-	MRS_HWCAP(&elf_hwcap2, HWCAP2_FRINT, ID_AA64ISAR1_FRINTTS_IMPL),
+	MRS_HWCAP(2, HWCAP2_FRINT, ID_AA64ISAR1_FRINTTS_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -745,7 +745,7 @@ static const struct mrs_field_value id_aa64isar1_gpi[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar1_gpi_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_PACG, ID_AA64ISAR1_GPI_IMPL),
+	MRS_HWCAP(1, HWCAP_PACG, ID_AA64ISAR1_GPI_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -755,7 +755,7 @@ static const struct mrs_field_value id_aa64isar1_gpa[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar1_gpa_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_PACG, ID_AA64ISAR1_GPA_IMPL),
+	MRS_HWCAP(1, HWCAP_PACG, ID_AA64ISAR1_GPA_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -767,8 +767,8 @@ static const struct mrs_field_value id_aa64isar1_lrcpc[] = {
 };
 
 static const 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(1, HWCAP_LRCPC, ID_AA64ISAR1_LRCPC_RCPC_8_3),
+	MRS_HWCAP(1, HWCAP_ILRCPC, ID_AA64ISAR1_LRCPC_RCPC_8_4),
 	MRS_HWCAP_END
 };
 
@@ -778,7 +778,7 @@ static const struct mrs_field_value id_aa64isar1_fcma[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar1_fcma_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_FCMA, ID_AA64ISAR1_FCMA_IMPL),
+	MRS_HWCAP(1, HWCAP_FCMA, ID_AA64ISAR1_FCMA_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -788,7 +788,7 @@ static const struct mrs_field_value id_aa64isar1_jscvt[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar1_jscvt_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_JSCVT, ID_AA64ISAR1_JSCVT_IMPL),
+	MRS_HWCAP(1, HWCAP_JSCVT, ID_AA64ISAR1_JSCVT_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -804,7 +804,7 @@ static const struct mrs_field_value id_aa64isar1_api[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar1_api_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_PACA, ID_AA64ISAR1_API_PAC),
+	MRS_HWCAP(1, HWCAP_PACA, ID_AA64ISAR1_API_PAC),
 	MRS_HWCAP_END
 };
 
@@ -820,7 +820,7 @@ static const struct mrs_field_value id_aa64isar1_apa[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar1_apa_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_PACA, ID_AA64ISAR1_APA_PAC),
+	MRS_HWCAP(1, HWCAP_PACA, ID_AA64ISAR1_APA_PAC),
 	MRS_HWCAP_END
 };
 
@@ -832,8 +832,8 @@ static const struct mrs_field_value id_aa64isar1_dpb[] = {
 };
 
 static const 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(1, HWCAP_DCPOP, ID_AA64ISAR1_DPB_DCCVAP),
+	MRS_HWCAP(2, HWCAP2_DCPODP, ID_AA64ISAR1_DPB_DCCVADP),
 	MRS_HWCAP_END
 };
 
@@ -900,7 +900,7 @@ static const struct mrs_field_value id_aa64isar2_apa3[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar2_apa3_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_PACA, ID_AA64ISAR2_APA3_PAC),
+	MRS_HWCAP(1, HWCAP_PACA, ID_AA64ISAR2_APA3_PAC),
 	MRS_HWCAP_END
 };
 
@@ -910,7 +910,7 @@ static const struct mrs_field_value id_aa64isar2_gpa3[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64isar2_gpa3_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_PACG, ID_AA64ISAR2_GPA3_IMPL),
+	MRS_HWCAP(1, HWCAP_PACG, ID_AA64ISAR2_GPA3_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -1201,7 +1201,7 @@ static const struct mrs_field_value id_aa64mmfr2_at[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64mmfr2_at_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_USCAT, ID_AA64MMFR2_AT_IMPL),
+	MRS_HWCAP(1, HWCAP_USCAT, ID_AA64MMFR2_AT_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -1336,7 +1336,7 @@ static const struct mrs_field_value id_aa64pfr0_dit[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64pfr0_dit_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_DIT, ID_AA64PFR0_DIT_PSTATE),
+	MRS_HWCAP(1, HWCAP_DIT, ID_AA64PFR0_DIT_PSTATE),
 	MRS_HWCAP_END
 };
 
@@ -1365,7 +1365,7 @@ static const struct mrs_field_value id_aa64pfr0_sve[] = {
 #if 0
 /* Enable when we add SVE support */
 static const struct mrs_field_hwcap id_aa64pfr0_sve_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_SVE, ID_AA64PFR0_SVE_IMPL),
+	MRS_HWCAP(1, HWCAP_SVE, ID_AA64PFR0_SVE_IMPL),
 	MRS_HWCAP_END
 };
 #endif
@@ -1392,8 +1392,8 @@ static const struct mrs_field_value id_aa64pfr0_advsimd[] = {
 };
 
 static const 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(1, HWCAP_ASIMD, ID_AA64PFR0_AdvSIMD_IMPL),
+	MRS_HWCAP(1, HWCAP_ASIMDHP, ID_AA64PFR0_AdvSIMD_HP),
 	MRS_HWCAP_END
 };
 
@@ -1404,8 +1404,8 @@ static const struct mrs_field_value id_aa64pfr0_fp[] = {
 };
 
 static const 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(1, HWCAP_FP, ID_AA64PFR0_FP_IMPL),
+	MRS_HWCAP(1, HWCAP_FPHP, ID_AA64PFR0_FP_HP),
 	MRS_HWCAP_END
 };
 
@@ -1510,7 +1510,7 @@ static const struct mrs_field_value id_aa64pfr1_ssbs[] = {
 };
 
 static const struct mrs_field_hwcap id_aa64pfr1_ssbs_caps[] = {
-	MRS_HWCAP(&elf_hwcap, HWCAP_SSBS, ID_AA64PFR1_SSBS_PSTATE),
+	MRS_HWCAP(1, HWCAP_SSBS, ID_AA64PFR1_SSBS_PSTATE),
 	MRS_HWCAP_END
 };
 
@@ -1523,7 +1523,7 @@ static const struct mrs_field_value id_aa64pfr1_bt[] = {
 #if 0
 /* Enable when we add BTI support */
 static const struct mrs_field_hwcap id_aa64pfr1_bt_caps[] = {
-	MRS_HWCAP(&elf_hwcap2, HWCAP2_BTI, ID_AA64PFR1_BT_IMPL),
+	MRS_HWCAP(2, HWCAP2_BTI, ID_AA64PFR1_BT_IMPL),
 	MRS_HWCAP_END
 };
 #endif
@@ -1636,7 +1636,7 @@ static const struct mrs_field_value id_isar5_crc32[] = {
 };
 
 static const struct mrs_field_hwcap id_isar5_crc32_caps[] = {
-	MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_CRC32, ID_ISAR5_CRC32_IMPL),
+	MRS_HWCAP(2, HWCAP32_2_CRC32, ID_ISAR5_CRC32_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -1646,7 +1646,7 @@ static const struct mrs_field_value id_isar5_sha2[] = {
 };
 
 static const struct mrs_field_hwcap id_isar5_sha2_caps[] = {
-	MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_SHA2, ID_ISAR5_SHA2_IMPL),
+	MRS_HWCAP(2, HWCAP32_2_SHA2, ID_ISAR5_SHA2_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -1656,7 +1656,7 @@ static const struct mrs_field_value id_isar5_sha1[] = {
 };
 
 static const struct mrs_field_hwcap id_isar5_sha1_caps[] = {
-	MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_SHA1, ID_ISAR5_SHA1_IMPL),
+	MRS_HWCAP(2, HWCAP32_2_SHA1, ID_ISAR5_SHA1_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -1667,8 +1667,8 @@ static const struct mrs_field_value id_isar5_aes[] = {
 };
 
 static const 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(2, HWCAP32_2_AES, ID_ISAR5_AES_BASE),
+	MRS_HWCAP(2, HWCAP32_2_PMULL, ID_ISAR5_AES_VMULL),
 	MRS_HWCAP_END
 };
 
@@ -1721,8 +1721,8 @@ static const struct mrs_field_value mvfr0_fpdp[] = {
 };
 
 static const 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),
+	MRS_HWCAP(1, HWCAP32_VFP, MVFR0_FPDP_VFP_v2),
+	MRS_HWCAP(1, HWCAP32_VFPv3, MVFR0_FPDP_VFP_v3_v4),
 	MRS_HWCAP_END
 };
 
@@ -1759,7 +1759,7 @@ static const struct mrs_field_value mvfr1_simdfmac[] = {
 };
 
 static const struct mrs_field_hwcap mvfr1_simdfmac_caps[] = {
-	MRS_HWCAP(&elf32_hwcap, HWCAP32_VFPv4, MVFR1_SIMDFMAC_IMPL),
+	MRS_HWCAP(1, HWCAP32_VFPv4, MVFR1_SIMDFMAC_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -1794,7 +1794,7 @@ static const struct mrs_field_value mvfr1_simdls[] = {
 };
 
 static const struct mrs_field_hwcap mvfr1_simdls_caps[] = {
-	MRS_HWCAP(&elf32_hwcap, HWCAP32_VFPv4, MVFR1_SIMDFMAC_IMPL),
+	MRS_HWCAP(1, HWCAP32_VFPv4, MVFR1_SIMDFMAC_IMPL),
 	MRS_HWCAP_END
 };
 
@@ -2148,14 +2148,18 @@ 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)
+parse_cpu_features(bool is64bit, u_long *hwcap, u_long *hwcap2)
 {
 	const struct mrs_field_hwcap *hwcaps;
 	const struct mrs_field *fields;
 	uint64_t min, reg;
+	u_long *cur_hwcap;
 	int i, j, k;
 
 	for (i = 0; i < nitems(user_regs); i++) {
+		if (user_regs[i].is64bit != is64bit)
+			continue;
+
 		reg = CPU_DESC_FIELD(user_cpu_desc, i);
 		fields = user_regs[i].fields;
 		for (j = 0; fields[j].type != 0; j++) {
@@ -2163,7 +2167,14 @@ parse_cpu_features(void)
 			if (hwcaps == NULL)
 				continue;
 
-			for (k = 0; hwcaps[k].hwcap != NULL; k++) {
+			for (k = 0; hwcaps[k].hwcap_id != 0; k++) {
+				KASSERT(hwcaps[k].hwcap_id == 1 ||
+				    hwcaps[k].hwcap_id == 2,
+				    ("%s: Invalid HWCAP ID %d", __func__,
+				    hwcaps[k].hwcap_id));
+
+				cur_hwcap = hwcaps[k].hwcap_id == 1 ?
+				    hwcap : hwcap2;
 				min = hwcaps[k].min;
 
 				/*
@@ -2172,7 +2183,7 @@ parse_cpu_features(void)
 				 */
 				if (mrs_field_cmp(reg, min, fields[j].shift,
 				    4, fields[j].sign) >= 0) {
-					*hwcaps[k].hwcap |= hwcaps[k].hwcap_val;
+					*cur_hwcap |= hwcaps[k].hwcap_val;
 				}
 			}
 		}
@@ -2205,7 +2216,11 @@ identify_cpu_sysinit(void *dummy __unused)
 	}
 
 	/* Find the values to export to userspace as AT_HWCAP and AT_HWCAP2 */
-	parse_cpu_features();
+	parse_cpu_features(true, &elf_hwcap, &elf_hwcap2);
+#ifdef COMPAT_FREEBSD32
+	parse_cpu_features(false, &elf32_hwcap, &elf32_hwcap2);
+#endif
+
 	/* We export the CPUID registers */
 	elf_hwcap |= HWCAP_CPUID;