summaryrefslogtreecommitdiff
path: root/sys/arm64
diff options
context:
space:
mode:
authorEmmanuel Vadot <manu@FreeBSD.org>2020-06-19 18:25:27 +0000
committerEmmanuel Vadot <manu@FreeBSD.org>2020-06-19 18:25:27 +0000
commit4b95d1ffa7a2426c5977e349037a22386a1b88ad (patch)
tree210c0872d46f4ac7c30ea77290a85ac4a97e5183 /sys/arm64
parenta1187fb9dd74bfb595d6b7224ecb569f2c32b51f (diff)
downloadsrc-test2-4b95d1ffa7a2426c5977e349037a22386a1b88ad.tar.gz
src-test2-4b95d1ffa7a2426c5977e349037a22386a1b88ad.zip
Notes
Diffstat (limited to 'sys/arm64')
-rw-r--r--sys/arm64/arm64/elf_machdep.c3
-rw-r--r--sys/arm64/arm64/identcpu.c105
-rw-r--r--sys/arm64/include/cpu.h1
-rw-r--r--sys/arm64/include/elf.h30
4 files changed, 134 insertions, 5 deletions
diff --git a/sys/arm64/arm64/elf_machdep.c b/sys/arm64/arm64/elf_machdep.c
index 1aa942cf28f4..90149303f664 100644
--- a/sys/arm64/arm64/elf_machdep.c
+++ b/sys/arm64/arm64/elf_machdep.c
@@ -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,
@@ -89,6 +91,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);
diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index 707b6bc4d284..62b4a7a2933e 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -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";
@@ -398,10 +401,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));
@@ -413,6 +420,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);
}
@@ -420,7 +432,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;
@@ -474,9 +574,6 @@ print_cpu_features(u_int cpu)
"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) ? "" : ","
/* AArch64 Instruction Set Attribute Register 0 */
diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h
index 5663e50ebcbc..4b2305967b1a 100644
--- a/sys/arm64/include/cpu.h
+++ b/sys/arm64/include/cpu.h
@@ -163,7 +163,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)]
diff --git a/sys/arm64/include/elf.h b/sys/arm64/include/elf.h
index 04487c43abf6..b1572784ff77 100644
--- a/sys/arm64/include/elf.h
+++ b/sys/arm64/include/elf.h
@@ -114,4 +114,34 @@ __ElfType(Auxinfo);
#define ET_DYN_LOAD_ADDR 0x100000
+/* 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_ */