Index: sys/arm64/arm64/elf_machdep.c =================================================================== --- sys/arm64/arm64/elf_machdep.c +++ sys/arm64/arm64/elf_machdep.c @@ -55,6 +55,8 @@ #include "linker_if.h" +u_long elf_hwcap; + static struct sysentvec elf64_freebsd_sysvec = { .sv_size = SYS_MAXSYSCALL, .sv_table = sysent, @@ -88,6 +90,7 @@ .sv_schedtail = NULL, .sv_thread_detach = NULL, .sv_trap = NULL, + .sv_hwcap = &elf_hwcap, }; INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); Index: sys/arm64/arm64/identcpu.c =================================================================== --- sys/arm64/arm64/identcpu.c +++ sys/arm64/arm64/identcpu.c @@ -44,8 +44,11 @@ #include #include #include +#include static int ident_lock; +static void print_cpu_features(u_int cpu); +static u_long parse_cpu_features_hwcap(u_int cpu); char machine[] = "arm64"; @@ -408,10 +411,14 @@ } } +/* HWCAP */ +extern u_long elf_hwcap; + static void identify_cpu_sysinit(void *dummy __unused) { int cpu; + u_long hwcap; /* Create a user visible cpu description with safe values */ memset(&user_cpu_desc, 0, sizeof(user_cpu_desc)); @@ -423,6 +430,11 @@ CPU_FOREACH(cpu) { print_cpu_features(cpu); + hwcap = parse_cpu_features_hwcap(cpu); + if (elf_hwcap == 0) + elf_hwcap = hwcap; + else + elf_hwcap &= hwcap; update_user_regs(cpu); } @@ -430,12 +442,101 @@ } SYSINIT(idenrity_cpu, SI_SUB_SMP, SI_ORDER_ANY, identify_cpu_sysinit, NULL); -void +static u_long +parse_cpu_features_hwcap(u_int cpu) +{ + u_long hwcap = 0; + + if (ID_AA64ISAR0_DP(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_DP_IMPL) + hwcap |= HWCAP_ASIMDDP; + + if (ID_AA64ISAR0_SM4(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_SM4_IMPL) + hwcap |= HWCAP_SM4; + + if (ID_AA64ISAR0_SM3(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_SM3_IMPL) + hwcap |= HWCAP_SM3; + + if (ID_AA64ISAR0_RDM(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_RDM_IMPL) + hwcap |= HWCAP_ASIMDRDM; + + if (ID_AA64ISAR0_ATOMIC(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_ATOMIC_IMPL) + hwcap |= HWCAP_ATOMICS; + + if (ID_AA64ISAR0_CRC32(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_CRC32_BASE) + hwcap |= HWCAP_CRC32; + + switch (ID_AA64ISAR0_SHA2(cpu_desc[cpu].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(cpu_desc[cpu].id_aa64isar0)) + hwcap |= HWCAP_SHA1; + + switch (ID_AA64ISAR0_AES(cpu_desc[cpu].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_LRCPC(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_LRCPC_IMPL) + hwcap |= HWCAP_LRCPC; + + if (ID_AA64ISAR1_FCMA(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_FCMA_IMPL) + hwcap |= HWCAP_FCMA; + + if (ID_AA64ISAR1_JSCVT(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_JSCVT_IMPL) + hwcap |= HWCAP_JSCVT; + + if (ID_AA64ISAR1_DPB(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_DPB_IMPL) + hwcap |= HWCAP_DCPOP; + + if (ID_AA64PFR0_SVE(cpu_desc[cpu].id_aa64pfr0) == ID_AA64PFR0_SVE_IMPL) + hwcap |= HWCAP_SVE; + + switch (ID_AA64PFR0_ADV_SIMD(cpu_desc[cpu].id_aa64pfr0)) { + case ID_AA64PFR0_ADV_SIMD_IMPL: + hwcap |= HWCAP_ASIMD; + break; + case ID_AA64PFR0_ADV_SIMD_HP: + hwcap |= HWCAP_ASIMD | HWCAP_ASIMDDP; + break; + default: + break; + } + + switch (ID_AA64PFR0_FP(cpu_desc[cpu].id_aa64pfr0)) { + case ID_AA64PFR0_FP_IMPL: + hwcap |= HWCAP_FP; + break; + case ID_AA64PFR0_FP_HP: + hwcap |= HWCAP_FP | HWCAP_FPHP; + break; + default: + break; + } + + return (hwcap); +} + +static void print_cpu_features(u_int cpu) { struct sbuf *sb; int printed; + printf("%s: cpu=%d cpu_print_regs=%x\n", __func__, cpu, cpu_print_regs); sb = sbuf_new_auto(); sbuf_printf(sb, "CPU%3d: %s %s r%dp%d", cpu, cpu_desc[cpu].cpu_impl_name, cpu_desc[cpu].cpu_part_name, @@ -484,8 +585,10 @@ "hardware bugs that may cause the incorrect operation of " "atomic operations.\n"); - if (cpu != 0 && cpu_print_regs == 0) + if (cpu != 0 && cpu_print_regs == 0) { + printf("cpu_print_reg = %d cpu = %d\n", cpu_print_regs, cpu); return; + } #define SEP_STR ((printed++) == 0) ? "" : "," Index: sys/arm64/include/cpu.h =================================================================== --- sys/arm64/include/cpu.h +++ sys/arm64/include/cpu.h @@ -160,7 +160,6 @@ void fork_trampoline(void); void identify_cpu(void); void install_cpu_errata(void); -void print_cpu_features(u_int); void swi_vm(void *v); #define CPU_AFFINITY(cpu) __cpu_affinity[(cpu)] Index: sys/arm64/include/elf.h =================================================================== --- sys/arm64/include/elf.h +++ sys/arm64/include/elf.h @@ -87,4 +87,34 @@ #define ET_DYN_LOAD_ADDR 0x100000 #endif +/* HWCAP */ + +#define HWCAP_FP 0x00000001 +#define HWCAP_ASIMD 0x00000002 +#define HWCAP_EVTSTRM 0x00000004 +#define HWCAP_AES 0x00000008 +#define HWCAP_PMULL 0x00000010 +#define HWCAP_SHA1 0x00000020 +#define HWCAP_SHA2 0x00000040 +#define HWCAP_CRC32 0x00000080 +#define HWCAP_ATOMICS 0x00000100 +#define HWCAP_FPHP 0x00000200 +#define HWCAP_CPUID 0x00000400 +#define HWCAP_ASIMDRDM 0x00000800 +#define HWCAP_JSCVT 0x00001000 +#define HWCAP_FCMA 0x00002000 +#define HWCAP_LRCPC 0x00004000 +#define HWCAP_DCPOP 0x00008000 +#define HWCAP_SHA3 0x00010000 +#define HWCAP_SM3 0x00020000 +#define HWCAP_SM4 0x00040000 +#define HWCAP_ASIMDDP 0x00080000 +#define HWCAP_SHA512 0x00100000 +#define HWCAP_SVE 0x00200000 +#define HWCAP_ASIMDFHM 0x00400000 +#define HWCAP_DIT 0x00800000 +#define HWCAP_USCAT 0x01000000 +#define HWCAP_ILRCPC 0x02000000 +#define HWCAP_FLAGM 0x04000000 + #endif /* !_MACHINE_ELF_H_ */