Index: head/sys/arm64/arm64/elf_machdep.c =================================================================== --- head/sys/arm64/arm64/elf_machdep.c +++ head/sys/arm64/arm64/elf_machdep.c @@ -55,7 +55,8 @@ #include "linker_if.h" -u_long elf_hwcap; +u_long __read_frequently elf_hwcap; +u_long __read_frequently 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: head/sys/arm64/arm64/identcpu.c =================================================================== --- head/sys/arm64/arm64/identcpu.c +++ head/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(void); +static u_long parse_cpu_features_hwcap2(void); char machine[] = "arm64"; @@ -869,7 +871,7 @@ static struct mrs_field id_aa64pfr1_fields[] = { MRS_FIELD(ID_AA64PFR1, BT, false, MRS_EXACT, id_aa64pfr1_bt), - MRS_FIELD(ID_AA64PFR1, SSBS, false, MRS_EXACT, id_aa64pfr1_ssbs), + MRS_FIELD(ID_AA64PFR1, SSBS, false, MRS_LOWER, id_aa64pfr1_ssbs), MRS_FIELD(ID_AA64PFR1, MTE, false, MRS_EXACT, id_aa64pfr1_mte), MRS_FIELD_END, }; @@ -1126,7 +1128,6 @@ } /* HWCAP */ -extern u_long elf_hwcap; bool __read_frequently lse_supported = false; bool __read_frequently icache_aliasing = false; @@ -1156,8 +1157,9 @@ idc = false; } - /* Exposed to userspace as AT_HWCAP */ + /* Exposed to userspace as AT_HWCAP and AT_HWCAP2 */ elf_hwcap = parse_cpu_features_hwcap(); + elf_hwcap2 = parse_cpu_features_hwcap2(); if (dic && idc) { arm64_icache_sync_range = &arm64_dic_idc_icache_sync_range; @@ -1194,6 +1196,15 @@ { 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_DP_VAL(user_cpu_desc.id_aa64isar0) == ID_AA64ISAR0_DP_IMPL) hwcap |= HWCAP_ASIMDDP; @@ -1206,6 +1217,10 @@ 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; @@ -1229,7 +1244,8 @@ break; } - if (ID_AA64ISAR0_SHA1_VAL(user_cpu_desc.id_aa64isar0)) + 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)) { @@ -1243,9 +1259,20 @@ break; } - if (ID_AA64ISAR1_LRCPC_VAL(user_cpu_desc.id_aa64isar1) == - ID_AA64ISAR1_LRCPC_RCPC_8_3) + 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) @@ -1285,7 +1312,51 @@ 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); } static void Index: head/sys/arm64/include/md_var.h =================================================================== --- head/sys/arm64/include/md_var.h +++ head/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;