Author: mhorne Date: Sat Aug 15 15:06:39 2020 New Revision: 364255 URL: https://svnweb.freebsd.org/changeset/base/364255
Log: arm64: parse HWCAP values using user_cpu_desc The hard work of parsing fields per-CPU, handling heterogeneous features, and excluding features from userspace is already done by update_special_regs. We can build our set of HWCAPs from the result. This exposed a small bug in update_special_regs, in which the generated bitmask was not wide enough, and as a result some bits weren't being exposed in user_cpu_desc. Fix this. While here, adjust some formatting. Reviewed by: andrew MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D26069 Modified: head/sys/arm64/arm64/identcpu.c Modified: head/sys/arm64/arm64/identcpu.c ============================================================================== --- head/sys/arm64/arm64/identcpu.c Sat Aug 15 14:57:53 2020 (r364254) +++ head/sys/arm64/arm64/identcpu.c Sat Aug 15 15:06:39 2020 (r364255) @@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$"); #include <machine/elf.h> static void print_cpu_features(u_int cpu); -static u_long parse_cpu_features_hwcap(u_int cpu); +static u_long parse_cpu_features_hwcap(void); char machine[] = "arm64"; @@ -1095,7 +1095,7 @@ update_special_regs(u_int cpu) for (j = 0; fields[j].type != 0; j++) { switch (fields[j].type & MRS_TYPE_MASK) { case MRS_EXACT: - user_reg &= ~(0xfu << fields[j].shift); + user_reg &= ~(0xful << fields[j].shift); user_reg |= (uint64_t)MRS_EXACT_FIELD(fields[j].type) << fields[j].shift; @@ -1131,7 +1131,6 @@ static void identify_cpu_sysinit(void *dummy __unused) { int cpu; - u_long hwcap; bool dic, idc; dic = (allow_dic != 0); @@ -1139,11 +1138,6 @@ identify_cpu_sysinit(void *dummy __unused) CPU_FOREACH(cpu) { check_cpu_regs(cpu); - hwcap = parse_cpu_features_hwcap(cpu); - if (elf_hwcap == 0) - elf_hwcap = hwcap; - else - elf_hwcap &= hwcap; if (cpu != 0) update_special_regs(cpu); @@ -1153,6 +1147,9 @@ identify_cpu_sysinit(void *dummy __unused) idc = false; } + /* Exposed to userspace as AT_HWCAP */ + elf_hwcap = parse_cpu_features_hwcap(); + if (dic && idc) { arm64_icache_sync_range = &arm64_dic_idc_icache_sync_range; if (bootverbose) @@ -1184,43 +1181,49 @@ cpu_features_sysinit(void *dummy __unused) SYSINIT(cpu_features, SI_SUB_SMP, SI_ORDER_ANY, cpu_features_sysinit, NULL); static u_long -parse_cpu_features_hwcap(u_int cpu) +parse_cpu_features_hwcap(void) { u_long hwcap = 0; - if (ID_AA64ISAR0_DP_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_DP_IMPL) + if (ID_AA64ISAR0_DP_VAL(user_cpu_desc.id_aa64isar0) == + ID_AA64ISAR0_DP_IMPL) hwcap |= HWCAP_ASIMDDP; - if (ID_AA64ISAR0_SM4_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_SM4_IMPL) + if (ID_AA64ISAR0_SM4_VAL(user_cpu_desc.id_aa64isar0) == + ID_AA64ISAR0_SM4_IMPL) hwcap |= HWCAP_SM4; - if (ID_AA64ISAR0_SM3_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_SM3_IMPL) + if (ID_AA64ISAR0_SM3_VAL(user_cpu_desc.id_aa64isar0) == + ID_AA64ISAR0_SM3_IMPL) hwcap |= HWCAP_SM3; - if (ID_AA64ISAR0_RDM_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_RDM_IMPL) + if (ID_AA64ISAR0_RDM_VAL(user_cpu_desc.id_aa64isar0) == + ID_AA64ISAR0_RDM_IMPL) hwcap |= HWCAP_ASIMDRDM; - if (ID_AA64ISAR0_Atomic_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_Atomic_IMPL) + if (ID_AA64ISAR0_Atomic_VAL(user_cpu_desc.id_aa64isar0) == + ID_AA64ISAR0_Atomic_IMPL) hwcap |= HWCAP_ATOMICS; - if (ID_AA64ISAR0_CRC32_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_CRC32_BASE) + if (ID_AA64ISAR0_CRC32_VAL(user_cpu_desc.id_aa64isar0) == + ID_AA64ISAR0_CRC32_BASE) hwcap |= HWCAP_CRC32; - switch (ID_AA64ISAR0_SHA2_VAL(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; + switch (ID_AA64ISAR0_SHA2_VAL(user_cpu_desc.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_VAL(cpu_desc[cpu].id_aa64isar0)) + if (ID_AA64ISAR0_SHA1_VAL(user_cpu_desc.id_aa64isar0)) hwcap |= HWCAP_SHA1; - switch (ID_AA64ISAR0_AES_VAL(cpu_desc[cpu].id_aa64isar0)) { + switch (ID_AA64ISAR0_AES_VAL(user_cpu_desc.id_aa64isar0)) { case ID_AA64ISAR0_AES_BASE: hwcap |= HWCAP_AES; break; @@ -1231,22 +1234,27 @@ parse_cpu_features_hwcap(u_int cpu) break; } - if (ID_AA64ISAR1_LRCPC_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_LRCPC_RCPC_8_3) + if (ID_AA64ISAR1_LRCPC_VAL(user_cpu_desc.id_aa64isar1) == + ID_AA64ISAR1_LRCPC_RCPC_8_3) hwcap |= HWCAP_LRCPC; - if (ID_AA64ISAR1_FCMA_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_FCMA_IMPL) + if (ID_AA64ISAR1_FCMA_VAL(user_cpu_desc.id_aa64isar1) == + ID_AA64ISAR1_FCMA_IMPL) hwcap |= HWCAP_FCMA; - if (ID_AA64ISAR1_JSCVT_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_JSCVT_IMPL) + if (ID_AA64ISAR1_JSCVT_VAL(user_cpu_desc.id_aa64isar1) == + ID_AA64ISAR1_JSCVT_IMPL) hwcap |= HWCAP_JSCVT; - if (ID_AA64ISAR1_DPB_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_DPB_DCCVAP) + if (ID_AA64ISAR1_DPB_VAL(user_cpu_desc.id_aa64isar1) == + ID_AA64ISAR1_DPB_DCCVAP) hwcap |= HWCAP_DCPOP; - if (ID_AA64PFR0_SVE_VAL(cpu_desc[cpu].id_aa64pfr0) == ID_AA64PFR0_SVE_IMPL) + if (ID_AA64PFR0_SVE_VAL(user_cpu_desc.id_aa64pfr0) == + ID_AA64PFR0_SVE_IMPL) hwcap |= HWCAP_SVE; - switch (ID_AA64PFR0_AdvSIMD_VAL(cpu_desc[cpu].id_aa64pfr0)) { + switch (ID_AA64PFR0_AdvSIMD_VAL(user_cpu_desc.id_aa64pfr0)) { case ID_AA64PFR0_AdvSIMD_IMPL: hwcap |= HWCAP_ASIMD; break; @@ -1257,7 +1265,7 @@ parse_cpu_features_hwcap(u_int cpu) break; } - switch (ID_AA64PFR0_FP_VAL(cpu_desc[cpu].id_aa64pfr0)) { + switch (ID_AA64PFR0_FP_VAL(user_cpu_desc.id_aa64pfr0)) { case ID_AA64PFR0_FP_IMPL: hwcap |= HWCAP_FP; break; _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"