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-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to