Index: sys/arm64/arm64/elf_machdep.c =================================================================== --- sys/arm64/arm64/elf_machdep.c +++ sys/arm64/arm64/elf_machdep.c @@ -56,6 +56,7 @@ #include "linker_if.h" u_long elf_hwcap; +u_long elf_hwcap2; static struct sysentvec elf64_freebsd_sysvec = { .sv_size = SYS_MAXSYSCALL, @@ -92,6 +93,7 @@ .sv_thread_detach = NULL, .sv_trap = NULL, .sv_hwcap = &elf_hwcap, + .sv_hwcap2 = &elf_hwcap2, }; INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); Index: sys/arm64/arm64/identcpu.c =================================================================== --- sys/arm64/arm64/identcpu.c +++ sys/arm64/arm64/identcpu.c @@ -43,11 +43,13 @@ #include #include #include -#include #include +#include +#include static void print_cpu_features(u_int cpu); static u_long parse_cpu_features_hwcap(u_int cpu); +static u_long parse_cpu_features_hwcap2(u_int cpu); char machine[] = "arm64"; @@ -1116,7 +1118,6 @@ } /* HWCAP */ -extern u_long elf_hwcap; bool __read_frequently lse_supported = false; bool __read_frequently icache_aliasing = false; @@ -1143,6 +1144,11 @@ elf_hwcap = hwcap; else elf_hwcap &= hwcap; + hwcap = parse_cpu_features_hwcap2(cpu); + if (elf_hwcap2 == 0) + elf_hwcap2 = hwcap; + else + elf_hwcap2 &= hwcap; if (cpu != 0) update_special_regs(cpu); @@ -1196,6 +1202,9 @@ if (ID_AA64ISAR0_SM3_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_SM3_IMPL) hwcap |= HWCAP_SM3; + if (ID_AA64ISAR0_SHA3_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_SHA3_IMPL) + hwcap |= HWCAP_SHA3; + if (ID_AA64ISAR0_RDM_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_RDM_IMPL) hwcap |= HWCAP_ASIMDRDM; @@ -1216,6 +1225,9 @@ break; } + if (ID_AA64ISAR0_TS_VAL(cpu_desc[cpu].id_aa64isar0) != ID_AA64ISAR0_TS_NONE) + hwcap |= HWCAP_FLAGM; + if (ID_AA64ISAR0_SHA1_VAL(cpu_desc[cpu].id_aa64isar0)) hwcap |= HWCAP_SHA1; @@ -1230,8 +1242,19 @@ break; } - if (ID_AA64ISAR1_LRCPC_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_LRCPC_IMPL) + if (ID_AA64ISAR1_SB_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_SB_IMPL) + hwcap |= HWCAP_SB; + + switch (ID_AA64ISAR1_LRCPC_VAL(cpu_desc[cpu].id_aa64isar1)) { + case ID_AA64ISAR1_LRCPC_IMPL: hwcap |= HWCAP_LRCPC; + break; + case ID_AA64ISAR1_LRCPC_ILRCPCP: + hwcap |= HWCAP_LRCPC | HWCAP_ILRCPC; + break; + default: + break; + } if (ID_AA64ISAR1_FCMA_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_FCMA_IMPL) hwcap |= HWCAP_FCMA; @@ -1267,9 +1290,53 @@ break; } + if (ID_AA64PFR1_SSBS_VAL(cpu_desc[cpu].id_aa64pfr1) == + ID_AA64PFR1_SSBS_PSTATE_MSR) + hwcap |= HWCAP_SSBS; + return (hwcap); } +static u_long +parse_cpu_features_hwcap2(u_int cpu) +{ + u_long hwcap2 = 0; + + if (ID_AA64ISAR0_RNDR_VAL(cpu_desc[cpu].id_aa64isar0) == + ID_AA64ISAR0_RNDR_IMPL) + hwcap2 |= HWCAP2_RNG; + + if (ID_AA64ISAR0_TS_VAL(cpu_desc[cpu].id_aa64isar0) == + ID_AA64ISAR0_TS_FLAGM2) + hwcap2 |= HWCAP2_FLAGM2; + + if (ID_AA64ISAR1_I8MM_VAL(cpu_desc[cpu].id_aa64isar1) == + ID_AA64ISAR1_I8MM_IMPL) + hwcap2 |= HWCAP2_I8MM; + + if (ID_AA64ISAR1_DGH_VAL(cpu_desc[cpu].id_aa64isar1) == + ID_AA64ISAR1_DGH_IMPL) + hwcap2 |= HWCAP2_DGH; + + if (ID_AA64ISAR1_BF16_VAL(cpu_desc[cpu].id_aa64isar1) == + ID_AA64ISAR1_BF16_IMPL) + hwcap2 |= HWCAP2_BF16; + + if (ID_AA64ISAR1_FRINTTS_VAL(cpu_desc[cpu].id_aa64isar1) == + ID_AA64ISAR1_FRINTTS_IMPL) + hwcap2 |= HWCAP2_FRINT; + + if (ID_AA64ISAR1_DPB_VAL(cpu_desc[cpu].id_aa64isar1) == + ID_AA64ISAR1_DPB_DCCVADP) + hwcap2 |= HWCAP2_DCPODP; + + if (ID_AA64PFR1_BT_VAL(cpu_desc[cpu].id_aa64pfr1) == + ID_AA64PFR1_BT_IMPL) + hwcap2 |= HWCAP2_BTI; + + return (hwcap2); +} + static void print_ctr_fields(struct sbuf *sb, uint64_t reg, void *arg) { Index: sys/arm64/include/md_var.h =================================================================== --- sys/arm64/include/md_var.h +++ sys/arm64/include/md_var.h @@ -38,6 +38,8 @@ extern int szsigcode; extern uint64_t *vm_page_dump; extern int vm_page_dump_size; +extern u_long elf_hwcap; +extern u_long elf_hwcap2; struct dumperinfo;