aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Grehan <grehan@FreeBSD.org>2021-07-25 09:34:14 +0000
committerPeter Grehan <grehan@FreeBSD.org>2021-08-22 04:17:46 +0000
commit28e22482279f43dda9c78f3fec2189630e9b84cd (patch)
tree7dc96098e25769e6466f59252ae4ca605ccbf11f
parent66e088e12b9fd3a42e5a92a0de79d75a3d4b5cd3 (diff)
downloadsrc-28e22482279f.tar.gz
src-28e22482279f.zip
arm64: HWCAP/HWCAP2 aux args support for 32-bit ARM binaries.
This fixes build/run of golang under COMPAT32 emulation. PR: 256897 Reviewed by: andrew, mmel, manu, jhb, cognet, Robert Clausecker Tested by: brd, andrew, Robert Clausecker Relnotes: yes Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D31175 (cherry picked from commit bbe80bff7c3549128bd19862eea7899b3def1d7f)
-rw-r--r--sys/arm64/arm64/elf32_machdep.c5
-rw-r--r--sys/arm64/arm64/identcpu.c302
-rw-r--r--sys/arm64/include/armreg.h131
-rw-r--r--sys/arm64/include/elf.h29
-rw-r--r--sys/arm64/include/md_var.h4
5 files changed, 471 insertions, 0 deletions
diff --git a/sys/arm64/arm64/elf32_machdep.c b/sys/arm64/arm64/elf32_machdep.c
index 48d6dc189e3a..3625a4d124da 100644
--- a/sys/arm64/arm64/elf32_machdep.c
+++ b/sys/arm64/arm64/elf32_machdep.c
@@ -77,6 +77,9 @@ static boolean_t elf32_arm_abi_supported(struct image_params *, int32_t *,
extern void freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
+u_long __read_frequently elf32_hwcap;
+u_long __read_frequently elf32_hwcap2;
+
static struct sysentvec elf32_freebsd_sysvec = {
.sv_size = SYS_MAXSYSCALL,
.sv_table = freebsd32_sysent,
@@ -109,6 +112,8 @@ static struct sysentvec elf32_freebsd_sysvec = {
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
+ .sv_hwcap = &elf32_hwcap,
+ .sv_hwcap2 = &elf32_hwcap2,
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
};
diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index 6395b3e0f08a..522526b92307 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -50,6 +50,10 @@ __FBSDID("$FreeBSD$");
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";
@@ -135,6 +139,11 @@ struct cpu_desc {
uint64_t id_aa64pfr0;
uint64_t id_aa64pfr1;
uint64_t ctr;
+#ifdef COMPAT_FREEBSD32
+ uint64_t id_isar5;
+ uint64_t mvfr0;
+ uint64_t mvfr1;
+#endif
};
static struct cpu_desc cpu_desc[MAXCPU];
@@ -152,6 +161,11 @@ static u_int cpu_print_regs;
#define PRINT_ID_AA64_MMFR2 0x00004000
#define PRINT_ID_AA64_PFR0 0x00010000
#define PRINT_ID_AA64_PFR1 0x00020000
+#ifdef COMPAT_FREEBSD32
+#define PRINT_ID_ISAR5 0x01000000
+#define PRINT_MVFR0 0x02000000
+#define PRINT_MVFR1 0x04000000
+#endif
#define PRINT_CTR_EL0 0x10000000
struct cpu_parts {
@@ -987,6 +1001,167 @@ static struct mrs_field id_aa64pfr1_fields[] = {
MRS_FIELD_END,
};
+#ifdef COMPAT_FREEBSD32
+/* ID_ISAR5_EL1 */
+static struct mrs_field_value id_isar5_vcma[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, VCMA, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value id_isar5_rdm[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, RDM, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value id_isar5_crc32[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, CRC32, NONE, IMPL),
+ MRS_FIELD_VALUE_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_value id_isar5_sha1[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, SHA1, NONE, IMPL),
+ MRS_FIELD_VALUE_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_value id_isar5_sevl[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, SEVL, NOP, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+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(ID_ISAR5, SEVL, false, MRS_LOWER, id_isar5_sevl),
+ MRS_FIELD_END,
+};
+
+/* MVFR0 */
+static struct mrs_field_value mvfr0_fpround[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(MVFR0, FPRound, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr0_fpsqrt[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(MVFR0, FPSqrt, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr0_fpdivide[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(MVFR0, FPDivide, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr0_fptrap[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(MVFR0, FPTrap, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr0_fpdp[] = {
+ MRS_FIELD_VALUE(MVFR0_FPDP_NONE, ""),
+ MRS_FIELD_VALUE(MVFR0_FPDP_VFP_v2, "DP VFPv2"),
+ MRS_FIELD_VALUE(MVFR0_FPDP_VFP_v3_v4, "DP VFPv3+v4"),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr0_fpsp[] = {
+ MRS_FIELD_VALUE(MVFR0_FPSP_NONE, ""),
+ MRS_FIELD_VALUE(MVFR0_FPSP_VFP_v2, "SP VFPv2"),
+ MRS_FIELD_VALUE(MVFR0_FPSP_VFP_v3_v4, "SP VFPv3+v4"),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr0_simdreg[] = {
+ MRS_FIELD_VALUE(MVFR0_SIMDReg_NONE, ""),
+ MRS_FIELD_VALUE(MVFR0_SIMDReg_FP, "FP 16x64"),
+ MRS_FIELD_VALUE(MVFR0_SIMDReg_AdvSIMD, "AdvSIMD"),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field mvfr0_fields[] = {
+ MRS_FIELD(MVFR0, FPRound, false, MRS_LOWER, mvfr0_fpround),
+ 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(MVFR0, FPSP, false, MRS_LOWER, mvfr0_fpsp),
+ MRS_FIELD(MVFR0, SIMDReg, false, MRS_LOWER, mvfr0_simdreg),
+ MRS_FIELD_END,
+};
+
+/* MVFR1 */
+static struct mrs_field_value mvfr1_simdfmac[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(MVFR1, SIMDFMAC, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr1_fphp[] = {
+ MRS_FIELD_VALUE(MVFR1_FPHP_NONE, ""),
+ MRS_FIELD_VALUE(MVFR1_FPHP_CONV_SP, "FPHP SP Conv"),
+ MRS_FIELD_VALUE(MVFR1_FPHP_CONV_DP, "FPHP DP Conv"),
+ MRS_FIELD_VALUE(MVFR1_FPHP_ARITH, "FPHP Arith"),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr1_simdhp[] = {
+ MRS_FIELD_VALUE(MVFR1_SIMDHP_NONE, ""),
+ MRS_FIELD_VALUE(MVFR1_SIMDHP_CONV_SP, "SIMDHP SP Conv"),
+ MRS_FIELD_VALUE(MVFR1_SIMDHP_ARITH, "SIMDHP Arith"),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr1_simdsp[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(MVFR1, SIMDSP, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr1_simdint[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(MVFR1, SIMDInt, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr1_simdls[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(MVFR1, SIMDLS, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr1_fpdnan[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(MVFR1, FPDNaN, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field_value mvfr1_fpftz[] = {
+ MRS_FIELD_VALUE_NONE_IMPL(MVFR1, FPFtZ, NONE, IMPL),
+ MRS_FIELD_VALUE_END,
+};
+
+static struct mrs_field mvfr1_fields[] = {
+ MRS_FIELD(MVFR1, SIMDFMAC, false, MRS_LOWER, mvfr1_simdfmac),
+ 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(MVFR1, FPDNaN, false, MRS_LOWER, mvfr1_fpdnan),
+ MRS_FIELD(MVFR1, FPFtZ, false, MRS_LOWER, mvfr1_fpftz),
+ MRS_FIELD_END,
+};
+#endif /* COMPAT_FREEBSD32 */
+
struct mrs_user_reg {
u_int reg;
u_int CRm;
@@ -1038,6 +1213,32 @@ static struct mrs_user_reg user_regs[] = {
.offset = __offsetof(struct cpu_desc, id_aa64mmfr0),
.fields = id_aa64mmfr0_fields,
},
+#ifdef COMPAT_FREEBSD32
+ {
+ /* id_isar5_el1 */
+ .reg = ID_ISAR5_EL1,
+ .CRm = 2,
+ .Op2 = 5,
+ .offset = __offsetof(struct cpu_desc, id_isar5),
+ .fields = id_isar5_fields,
+ },
+ {
+ /* mvfr0 */
+ .reg = MVFR0_EL1,
+ .CRm = 3,
+ .Op2 = 0,
+ .offset = __offsetof(struct cpu_desc, mvfr0),
+ .fields = mvfr0_fields,
+ },
+ {
+ /* mvfr1 */
+ .reg = MVFR1_EL1,
+ .CRm = 3,
+ .Op2 = 1,
+ .offset = __offsetof(struct cpu_desc, mvfr1),
+ .fields = mvfr1_fields,
+ },
+#endif /* COMPAT_FREEBSD32 */
};
#define CPU_DESC_FIELD(desc, idx) \
@@ -1272,6 +1473,12 @@ identify_cpu_sysinit(void *dummy __unused)
elf_hwcap = parse_cpu_features_hwcap();
elf_hwcap2 = parse_cpu_features_hwcap2();
+#ifdef COMPAT_FREEBSD32
+ /* 32-bit ARM versions of AT_HWCAP/HWCAP2 */
+ elf32_hwcap = parse_cpu_features_hwcap32();
+ elf32_hwcap2 = parse_cpu_features_hwcap32_2();
+#endif
+
if (dic && idc) {
arm64_icache_sync_range = &arm64_dic_idc_icache_sync_range;
if (bootverbose)
@@ -1483,6 +1690,66 @@ parse_cpu_features_hwcap2(void)
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) ==
+ MVFR1_SIMDLS_IMPL) &&
+ (MVFR1_SIMDInt_VAL(user_cpu_desc.mvfr1) ==
+ MVFR1_SIMDInt_IMPL) &&
+ (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
print_ctr_fields(struct sbuf *sb, uint64_t reg, void *arg)
{
@@ -1696,6 +1963,23 @@ print_cpu_features(u_int cpu)
print_id_register(sb, "Auxiliary Features 1",
cpu_desc[cpu].id_aa64afr1, id_aa64afr1_fields);
+#ifdef COMPAT_FREEBSD32
+ /* AArch32 Instruction Set Attribute Register 5 */
+ if (cpu == 0 || (cpu_print_regs & PRINT_ID_ISAR5) != 0)
+ print_id_register(sb, "AArch32 Instruction Set Attributes 5",
+ cpu_desc[cpu].id_isar5, id_isar5_fields);
+
+ /* AArch32 Media and VFP Feature Register 0 */
+ if (cpu == 0 || (cpu_print_regs & PRINT_MVFR0) != 0)
+ print_id_register(sb, "AArch32 Media and VFP Features 0",
+ cpu_desc[cpu].mvfr0, mvfr0_fields);
+
+ /* AArch32 Media and VFP Feature Register 1 */
+ if (cpu == 0 || (cpu_print_regs & PRINT_MVFR1) != 0)
+ print_id_register(sb, "AArch32 Media and VFP Features 1",
+ cpu_desc[cpu].mvfr1, mvfr1_fields);
+#endif
+
sbuf_delete(sb);
sb = NULL;
#undef SEP_STR
@@ -1795,6 +2079,15 @@ identify_cpu(u_int cpu)
cpu_desc[cpu].id_aa64mmfr2 = READ_SPECIALREG(id_aa64mmfr2_el1);
cpu_desc[cpu].id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
cpu_desc[cpu].id_aa64pfr1 = READ_SPECIALREG(id_aa64pfr1_el1);
+#ifdef COMPAT_FREEBSD32
+ /* Only read aarch32 SRs if EL0-32 is available */
+ if (ID_AA64PFR0_EL0_VAL(cpu_desc[cpu].id_aa64pfr0) ==
+ ID_AA64PFR0_EL0_64_32) {
+ cpu_desc[cpu].id_isar5 = READ_SPECIALREG(id_isar5_el1);
+ cpu_desc[cpu].mvfr0 = READ_SPECIALREG(mvfr0_el1);
+ cpu_desc[cpu].mvfr1 = READ_SPECIALREG(mvfr1_el1);
+ }
+#endif
}
static void
@@ -1859,4 +2152,13 @@ check_cpu_regs(u_int cpu)
identify_cache(cpu_desc[cpu].ctr);
cpu_print_regs |= PRINT_CTR_EL0;
}
+
+#ifdef COMPAT_FREEBSD32
+ if (cpu_desc[cpu].id_isar5 != cpu_desc[0].id_isar5)
+ cpu_print_regs |= PRINT_ID_ISAR5;
+ if (cpu_desc[cpu].mvfr0 != cpu_desc[0].mvfr0)
+ cpu_print_regs |= PRINT_MVFR0;
+ if (cpu_desc[cpu].mvfr1 != cpu_desc[0].mvfr1)
+ cpu_print_regs |= PRINT_MVFR1;
+#endif
}
diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h
index 9521b0826064..60389f4171ef 100644
--- a/sys/arm64/include/armreg.h
+++ b/sys/arm64/include/armreg.h
@@ -771,6 +771,45 @@
#define ID_AA64PFR1_RAS_frac_V1 (UL(0x0) << ID_AA64PFR1_RAS_frac_SHIFT)
#define ID_AA64PFR1_RAS_frac_V2 (UL(0x1) << ID_AA64PFR1_RAS_frac_SHIFT)
+/* ID_ISAR5_EL1 */
+#define ID_ISAR5_EL1 MRS_REG(3, 0, 0, 2, 5)
+#define ID_ISAR5_SEVL_SHIFT 0
+#define ID_ISAR5_SEVL_MASK (UL(0xf) << ID_ISAR5_SEVL_SHIFT)
+#define ID_ISAR5_SEVL_VAL(x) ((x) & ID_ISAR5_SEVL_MASK)
+#define ID_ISAR5_SEVL_NOP (UL(0x0) << ID_ISAR5_SEVL_SHIFT)
+#define ID_ISAR5_SEVL_IMPL (UL(0x1) << ID_ISAR5_SEVL_SHIFT)
+#define ID_ISAR5_AES_SHIFT 4
+#define ID_ISAR5_AES_MASK (UL(0xf) << ID_ISAR5_AES_SHIFT)
+#define ID_ISAR5_AES_VAL(x) ((x) & ID_ISAR5_AES_MASK)
+#define ID_ISAR5_AES_NONE (UL(0x0) << ID_ISAR5_AES_SHIFT)
+#define ID_ISAR5_AES_BASE (UL(0x1) << ID_ISAR5_AES_SHIFT)
+#define ID_ISAR5_AES_VMULL (UL(0x2) << ID_ISAR5_AES_SHIFT)
+#define ID_ISAR5_SHA1_SHIFT 8
+#define ID_ISAR5_SHA1_MASK (UL(0xf) << ID_ISAR5_SHA1_SHIFT)
+#define ID_ISAR5_SHA1_VAL(x) ((x) & ID_ISAR5_SHA1_MASK)
+#define ID_ISAR5_SHA1_NONE (UL(0x0) << ID_ISAR5_SHA1_SHIFT)
+#define ID_ISAR5_SHA1_IMPL (UL(0x1) << ID_ISAR5_SHA1_SHIFT)
+#define ID_ISAR5_SHA2_SHIFT 12
+#define ID_ISAR5_SHA2_MASK (UL(0xf) << ID_ISAR5_SHA2_SHIFT)
+#define ID_ISAR5_SHA2_VAL(x) ((x) & ID_ISAR5_SHA2_MASK)
+#define ID_ISAR5_SHA2_NONE (UL(0x0) << ID_ISAR5_SHA2_SHIFT)
+#define ID_ISAR5_SHA2_IMPL (UL(0x1) << ID_ISAR5_SHA2_SHIFT)
+#define ID_ISAR5_CRC32_SHIFT 16
+#define ID_ISAR5_CRC32_MASK (UL(0xf) << ID_ISAR5_CRC32_SHIFT)
+#define ID_ISAR5_CRC32_VAL(x) ((x) & ID_ISAR5_CRC32_MASK)
+#define ID_ISAR5_CRC32_NONE (UL(0x0) << ID_ISAR5_CRC32_SHIFT)
+#define ID_ISAR5_CRC32_IMPL (UL(0x1) << ID_ISAR5_CRC32_SHIFT)
+#define ID_ISAR5_RDM_SHIFT 24
+#define ID_ISAR5_RDM_MASK (UL(0xf) << ID_ISAR5_RDM_SHIFT)
+#define ID_ISAR5_RDM_VAL(x) ((x) & ID_ISAR5_RDM_MASK)
+#define ID_ISAR5_RDM_NONE (UL(0x0) << ID_ISAR5_RDM_SHIFT)
+#define ID_ISAR5_RDM_IMPL (UL(0x1) << ID_ISAR5_RDM_SHIFT)
+#define ID_ISAR5_VCMA_SHIFT 28
+#define ID_ISAR5_VCMA_MASK (UL(0xf) << ID_ISAR5_VCMA_SHIFT)
+#define ID_ISAR5_VCMA_VAL(x) ((x) & ID_ISAR5_VCMA_MASK)
+#define ID_ISAR5_VCMA_NONE (UL(0x0) << ID_ISAR5_VCMA_SHIFT)
+#define ID_ISAR5_VCMA_IMPL (UL(0x1) << ID_ISAR5_VCMA_SHIFT)
+
/* MAIR_EL1 - Memory Attribute Indirection Register */
#define MAIR_ATTR_MASK(idx) (0xff << ((n)* 8))
#define MAIR_ATTR(attr, idx) ((attr) << ((idx) * 8))
@@ -779,6 +818,98 @@
#define MAIR_NORMAL_WT 0xbb
#define MAIR_NORMAL_WB 0xff
+/* MVFR0_EL1 */
+#define MVFR0_EL1 MRS_REG(3, 0, 0, 3, 0)
+#define MVFR0_SIMDReg_SHIFT 0
+#define MVFR0_SIMDReg_MASK (UL(0xf) << MVFR0_SIMDReg_SHIFT)
+#define MVFR0_SIMDReg_VAL(x) ((x) & MVFR0_SIMDReg_MASK)
+#define MVFR0_SIMDReg_NONE (UL(0x0) << MVFR0_SIMDReg_SHIFT)
+#define MVFR0_SIMDReg_FP (UL(0x1) << MVFR0_SIMDReg_SHIFT)
+#define MVFR0_SIMDReg_AdvSIMD (UL(0x2) << MVFR0_SIMDReg_SHIFT)
+#define MVFR0_FPSP_SHIFT 4
+#define MVFR0_FPSP_MASK (UL(0xf) << MVFR0_FPSP_SHIFT)
+#define MVFR0_FPSP_VAL(x) ((x) & MVFR0_FPSP_MASK)
+#define MVFR0_FPSP_NONE (UL(0x0) << MVFR0_FPSP_SHIFT)
+#define MVFR0_FPSP_VFP_v2 (UL(0x1) << MVFR0_FPSP_SHIFT)
+#define MVFR0_FPSP_VFP_v3_v4 (UL(0x2) << MVFR0_FPSP_SHIFT)
+#define MVFR0_FPDP_SHIFT 8
+#define MVFR0_FPDP_MASK (UL(0xf) << MVFR0_FPDP_SHIFT)
+#define MVFR0_FPDP_VAL(x) ((x) & MVFR0_FPDP_MASK)
+#define MVFR0_FPDP_NONE (UL(0x0) << MVFR0_FPDP_SHIFT)
+#define MVFR0_FPDP_VFP_v2 (UL(0x1) << MVFR0_FPDP_SHIFT)
+#define MVFR0_FPDP_VFP_v3_v4 (UL(0x2) << MVFR0_FPDP_SHIFT)
+#define MVFR0_FPTrap_SHIFT 12
+#define MVFR0_FPTrap_MASK (UL(0xf) << MVFR0_FPTrap_SHIFT)
+#define MVFR0_FPTrap_VAL(x) ((x) & MVFR0_FPTrap_MASK)
+#define MVFR0_FPTrap_NONE (UL(0x0) << MVFR0_FPTrap_SHIFT)
+#define MVFR0_FPTrap_IMPL (UL(0x1) << MVFR0_FPTrap_SHIFT)
+#define MVFR0_FPDivide_SHIFT 16
+#define MVFR0_FPDivide_MASK (UL(0xf) << MVFR0_FPDivide_SHIFT)
+#define MVFR0_FPDivide_VAL(x) ((x) & MVFR0_FPDivide_MASK)
+#define MVFR0_FPDivide_NONE (UL(0x0) << MVFR0_FPDivide_SHIFT)
+#define MVFR0_FPDivide_IMPL (UL(0x1) << MVFR0_FPDivide_SHIFT)
+#define MVFR0_FPSqrt_SHIFT 20
+#define MVFR0_FPSqrt_MASK (UL(0xf) << MVFR0_FPSqrt_SHIFT)
+#define MVFR0_FPSqrt_VAL(x) ((x) & MVFR0_FPSqrt_MASK)
+#define MVFR0_FPSqrt_NONE (UL(0x0) << MVFR0_FPSqrt_SHIFT)
+#define MVFR0_FPSqrt_IMPL (UL(0x1) << MVFR0_FPSqrt_SHIFT)
+#define MVFR0_FPShVec_SHIFT 24
+#define MVFR0_FPShVec_MASK (UL(0xf) << MVFR0_FPShVec_SHIFT)
+#define MVFR0_FPShVec_VAL(x) ((x) & MVFR0_FPShVec_MASK)
+#define MVFR0_FPShVec_NONE (UL(0x0) << MVFR0_FPShVec_SHIFT)
+#define MVFR0_FPShVec_IMPL (UL(0x1) << MVFR0_FPShVec_SHIFT)
+#define MVFR0_FPRound_SHIFT 28
+#define MVFR0_FPRound_MASK (UL(0xf) << MVFR0_FPRound_SHIFT)
+#define MVFR0_FPRound_VAL(x) ((x) & MVFR0_FPRound_MASK)
+#define MVFR0_FPRound_NONE (UL(0x0) << MVFR0_FPRound_SHIFT)
+#define MVFR0_FPRound_IMPL (UL(0x1) << MVFR0_FPRound_SHIFT)
+
+/* MVFR1_EL1 */
+#define MVFR1_EL1 MRS_REG(3, 0, 0, 3, 1)
+#define MVFR1_FPFtZ_SHIFT 0
+#define MVFR1_FPFtZ_MASK (UL(0xf) << MVFR1_FPFtZ_SHIFT)
+#define MVFR1_FPFtZ_VAL(x) ((x) & MVFR1_FPFtZ_MASK)
+#define MVFR1_FPFtZ_NONE (UL(0x0) << MVFR1_FPFtZ_SHIFT)
+#define MVFR1_FPFtZ_IMPL (UL(0x1) << MVFR1_FPFtZ_SHIFT)
+#define MVFR1_FPDNaN_SHIFT 4
+#define MVFR1_FPDNaN_MASK (UL(0xf) << MVFR1_FPDNaN_SHIFT)
+#define MVFR1_FPDNaN_VAL(x) ((x) & MVFR1_FPDNaN_MASK)
+#define MVFR1_FPDNaN_NONE (UL(0x0) << MVFR1_FPDNaN_SHIFT)
+#define MVFR1_FPDNaN_IMPL (UL(0x1) << MVFR1_FPDNaN_SHIFT)
+#define MVFR1_SIMDLS_SHIFT 8
+#define MVFR1_SIMDLS_MASK (UL(0xf) << MVFR1_SIMDLS_SHIFT)
+#define MVFR1_SIMDLS_VAL(x) ((x) & MVFR1_SIMDLS_MASK)
+#define MVFR1_SIMDLS_NONE (UL(0x0) << MVFR1_SIMDLS_SHIFT)
+#define MVFR1_SIMDLS_IMPL (UL(0x1) << MVFR1_SIMDLS_SHIFT)
+#define MVFR1_SIMDInt_SHIFT 12
+#define MVFR1_SIMDInt_MASK (UL(0xf) << MVFR1_SIMDInt_SHIFT)
+#define MVFR1_SIMDInt_VAL(x) ((x) & MVFR1_SIMDInt_MASK)
+#define MVFR1_SIMDInt_NONE (UL(0x0) << MVFR1_SIMDInt_SHIFT)
+#define MVFR1_SIMDInt_IMPL (UL(0x1) << MVFR1_SIMDInt_SHIFT)
+#define MVFR1_SIMDSP_SHIFT 16
+#define MVFR1_SIMDSP_MASK (UL(0xf) << MVFR1_SIMDSP_SHIFT)
+#define MVFR1_SIMDSP_VAL(x) ((x) & MVFR1_SIMDSP_MASK)
+#define MVFR1_SIMDSP_NONE (UL(0x0) << MVFR1_SIMDSP_SHIFT)
+#define MVFR1_SIMDSP_IMPL (UL(0x1) << MVFR1_SIMDSP_SHIFT)
+#define MVFR1_SIMDHP_SHIFT 20
+#define MVFR1_SIMDHP_MASK (UL(0xf) << MVFR1_SIMDHP_SHIFT)
+#define MVFR1_SIMDHP_VAL(x) ((x) & MVFR1_SIMDHP_MASK)
+#define MVFR1_SIMDHP_NONE (UL(0x0) << MVFR1_SIMDHP_SHIFT)
+#define MVFR1_SIMDHP_CONV_SP (UL(0x1) << MVFR1_SIMDHP_SHIFT)
+#define MVFR1_SIMDHP_ARITH (UL(0x2) << MVFR1_SIMDHP_SHIFT)
+#define MVFR1_FPHP_SHIFT 24
+#define MVFR1_FPHP_MASK (UL(0xf) << MVFR1_FPHP_SHIFT)
+#define MVFR1_FPHP_VAL(x) ((x) & MVFR1_FPHP_MASK)
+#define MVFR1_FPHP_NONE (UL(0x0) << MVFR1_FPHP_SHIFT)
+#define MVFR1_FPHP_CONV_SP (UL(0x1) << MVFR1_FPHP_SHIFT)
+#define MVFR1_FPHP_CONV_DP (UL(0x2) << MVFR1_FPHP_SHIFT)
+#define MVFR1_FPHP_ARITH (UL(0x3) << MVFR1_FPHP_SHIFT)
+#define MVFR1_SIMDFMAC_SHIFT 28
+#define MVFR1_SIMDFMAC_MASK (UL(0xf) << MVFR1_SIMDFMAC_SHIFT)
+#define MVFR1_SIMDFMAC_VAL(x) ((x) & MVFR1_SIMDFMAC_MASK)
+#define MVFR1_SIMDFMAC_NONE (UL(0x0) << MVFR1_SIMDFMAC_SHIFT)
+#define MVFR1_SIMDFMAC_IMPL (UL(0x1) << MVFR1_SIMDFMAC_SHIFT)
+
/* PAR_EL1 - Physical Address Register */
#define PAR_F_SHIFT 0
#define PAR_F (0x1 << PAR_F_SHIFT)
diff --git a/sys/arm64/include/elf.h b/sys/arm64/include/elf.h
index bed84e6c755a..3f7c3964d428 100644
--- a/sys/arm64/include/elf.h
+++ b/sys/arm64/include/elf.h
@@ -150,4 +150,33 @@ __ElfType(Auxinfo);
#define HWCAP2_RNG 0x00010000
#define HWCAP2_BTI 0x00020000
+#ifdef COMPAT_FREEBSD32
+/* ARM HWCAP */
+#define HWCAP32_HALF 0x00000002 /* Always set. */
+#define HWCAP32_THUMB 0x00000004 /* Always set. */
+#define HWCAP32_FAST_MULT 0x00000010 /* Always set. */
+#define HWCAP32_VFP 0x00000040
+#define HWCAP32_EDSP 0x00000080 /* Always set. */
+#define HWCAP32_NEON 0x00001000
+#define HWCAP32_VFPv3 0x00002000
+#define HWCAP32_TLS 0x00008000 /* Always set. */
+#define HWCAP32_VFPv4 0x00010000
+#define HWCAP32_IDIVA 0x00020000 /* Always set. */
+#define HWCAP32_IDIVT 0x00040000 /* Always set. */
+#define HWCAP32_VFPD32 0x00080000 /* Always set. */
+#define HWCAP32_LPAE 0x00100000 /* Always set. */
+
+#define HWCAP32_DEFAULT \
+ (HWCAP32_HALF | HWCAP32_THUMB | HWCAP32_FAST_MULT | HWCAP32_EDSP |\
+ HWCAP32_TLS | HWCAP32_IDIVA | HWCAP32_IDIVT | HWCAP32_VFPD32 | \
+ HWCAP32_LPAE)
+
+/* ARM HWCAP2 */
+#define HWCAP32_2_AES 0x00000001
+#define HWCAP32_2_PMULL 0x00000002
+#define HWCAP32_2_SHA1 0x00000004
+#define HWCAP32_2_SHA2 0x00000008
+#define HWCAP32_2_CRC32 0x00000010
+#endif
+
#endif /* !_MACHINE_ELF_H_ */
diff --git a/sys/arm64/include/md_var.h b/sys/arm64/include/md_var.h
index 73cf642148b5..beaea0f8e719 100644
--- a/sys/arm64/include/md_var.h
+++ b/sys/arm64/include/md_var.h
@@ -38,6 +38,10 @@ extern char sigcode[];
extern int szsigcode;
extern u_long elf_hwcap;
extern u_long elf_hwcap2;
+#ifdef COMPAT_FREEBSD32
+extern u_long elf32_hwcap;
+extern u_long elf32_hwcap2;
+#endif
struct dumperinfo;