Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Jul 2019 14:29:12 +0000 (UTC)
From:      Emmanuel Vadot <manu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r350166 - in head/sys/arm64: arm64 include
Message-ID:  <201907201429.x6KETC4j079649@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201907201429.x6KETC4j079649>