Author: manu
Date: Sat Jul 20 14:29:11 2019
New Revision: 350166
URL: https://svnweb.freebsd.org/changeset/base/350166

Log:
  arm64: Implement HWCAP
  
  Add HWCAP support for arm64.
  defines are the same as in Linux and a userland program can use
  elf_aux_info to get the data.
  We only save the common denominator for all cores in case the
  big and little cluster have different support (this is known to
  exists even if we don't support those SoCs in FreeBSD)
  
  Differential Revision:        https://reviews.freebsd.org/D17137

Modified:
  head/sys/arm64/arm64/elf_machdep.c
  head/sys/arm64/arm64/identcpu.c
  head/sys/arm64/include/cpu.h
  head/sys/arm64/include/elf.h

Modified: head/sys/arm64/arm64/elf_machdep.c
==============================================================================
--- head/sys/arm64/arm64/elf_machdep.c  Sat Jul 20 08:40:31 2019        
(r350165)
+++ head/sys/arm64/arm64/elf_machdep.c  Sat Jul 20 14:29:11 2019        
(r350166)
@@ -55,6 +55,8 @@ __FBSDID("$FreeBSD$");
 
 #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 @@ static struct sysentvec elf64_freebsd_sysvec = {
        .sv_schedtail   = NULL,
        .sv_thread_detach = NULL,
        .sv_trap        = NULL,
+       .sv_hwcap       = &elf_hwcap,
 };
 INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
 

Modified: head/sys/arm64/arm64/identcpu.c
==============================================================================
--- head/sys/arm64/arm64/identcpu.c     Sat Jul 20 08:40:31 2019        
(r350165)
+++ head/sys/arm64/arm64/identcpu.c     Sat Jul 20 14:29:11 2019        
(r350166)
@@ -44,8 +44,11 @@ __FBSDID("$FreeBSD$");
 #include <machine/cpu.h>
 #include <machine/cpufunc.h>
 #include <machine/undefined.h>
+#include <machine/elf.h>
 
 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";
 
@@ -412,10 +415,14 @@ update_user_regs(u_int cpu)
        }
 }
 
+/* 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));
@@ -427,6 +434,11 @@ identify_cpu_sysinit(void *dummy __unused)
 
        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);
        }
 
@@ -434,7 +446,95 @@ identify_cpu_sysinit(void *dummy __unused)
 }
 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_AdvSIMD(cpu_desc[cpu].id_aa64pfr0)) {
+       case ID_AA64PFR0_AdvSIMD_IMPL:
+               hwcap |= HWCAP_ASIMD;
+               break;
+       case ID_AA64PFR0_AdvSIMD_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;
@@ -487,9 +587,6 @@ print_cpu_features(u_int cpu)
                printf("WARNING: ThunderX Pass 1.1 detected.\nThis has known "
                    "hardware bugs that may cause the incorrect operation of "
                    "atomic operations.\n");
-
-       if (cpu != 0 && cpu_print_regs == 0)
-               return;
 
 #define SEP_STR        ((printed++) == 0) ? "" : ","
 

Modified: head/sys/arm64/include/cpu.h
==============================================================================
--- head/sys/arm64/include/cpu.h        Sat Jul 20 08:40:31 2019        
(r350165)
+++ head/sys/arm64/include/cpu.h        Sat Jul 20 14:29:11 2019        
(r350166)
@@ -160,7 +160,6 @@ void        cpu_reset(void) __dead2;
 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)]

Modified: head/sys/arm64/include/elf.h
==============================================================================
--- head/sys/arm64/include/elf.h        Sat Jul 20 08:40:31 2019        
(r350165)
+++ head/sys/arm64/include/elf.h        Sat Jul 20 14:29:11 2019        
(r350166)
@@ -87,4 +87,34 @@ __ElfType(Auxinfo);
 #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_ */
_______________________________________________
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"

Reply via email to