From 0cbf724ed03571bc90ed22c3b4bf8c6c7b2da564 Mon Sep 17 00:00:00 2001 From: Michal Meloun Date: Sat, 21 Oct 2017 12:16:21 +0000 Subject: [PATCH] Fullify implementation of AT_HWCAP and AT_HWCAP2 for ARMv6,7. This makes elf_aux_info(3) useable for ARM ports. MFC after: 1 month --- sys/arm/arm/cpuinfo.c | 46 +++++++++++++++++++++++++++++++++++++++ sys/arm/arm/elf_machdep.c | 2 ++ sys/arm/arm/vfp.c | 2 ++ sys/arm/include/elf.h | 26 ++++++++++++++++++++++ sys/arm/include/md_var.h | 1 + sys/arm/include/vfp.h | 6 +++++ 6 files changed, 83 insertions(+) diff --git a/sys/arm/arm/cpuinfo.c b/sys/arm/arm/cpuinfo.c index 5dceab37be00..0566f999bdbb 100644 --- a/sys/arm/arm/cpuinfo.c +++ b/sys/arm/arm/cpuinfo.c @@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include #if __ARM_ARCH >= 6 void reinit_mmu(uint32_t ttb, uint32_t aux_clr, uint32_t aux_set); @@ -77,6 +79,9 @@ SYSCTL_INT(_hw_cpu_quirks, OID_AUTO, actlr_set, void cpuinfo_init(void) { +#if __ARM_ARCH >= 6 + uint32_t tmp; +#endif /* * Prematurely fetch CPU quirks. Standard fetch for tunable @@ -190,6 +195,47 @@ cpuinfo_init(void) } cpuinfo.dcache_line_mask = cpuinfo.dcache_line_size - 1; cpuinfo.icache_line_mask = cpuinfo.icache_line_size - 1; + + /* Fill AT_HWCAP bits. */ + elf_hwcap |= HWCAP_HALF | HWCAP_FAST_MULT; /* Requierd for all CPUs */ + elf_hwcap |= HWCAP_TLS | HWCAP_EDSP; /* Requierd for v6+ CPUs */ + + tmp = (cpuinfo.id_isar0 >> 24) & 0xF; /* Divide_instrs */ + if (tmp >= 1) + elf_hwcap |= HWCAP_IDIVT; + if (tmp >= 2) + elf_hwcap |= HWCAP_IDIVA; + + tmp = (cpuinfo.id_pfr0 >> 4) & 0xF; /* State1 */ + if (tmp >= 1) + elf_hwcap |= HWCAP_THUMB; + + tmp = (cpuinfo.id_pfr0 >> 12) & 0xF; /* State3 */ + if (tmp >= 1) + elf_hwcap |= HWCAP_THUMBEE; + + tmp = (cpuinfo.id_mmfr0 >> 0) & 0xF; /* VMSA */ + if (tmp >= 5) + elf_hwcap |= HWCAP_LPAE; + + /* Fill AT_HWCAP2 bits. */ + tmp = (cpuinfo.id_isar5 >> 4) & 0xF; /* AES */ + if (tmp >= 1) + elf_hwcap2 |= HWCAP2_AES; + if (tmp >= 2) + elf_hwcap2 |= HWCAP2_PMULL; + + tmp = (cpuinfo.id_isar5 >> 8) & 0xF; /* SHA1 */ + if (tmp >= 1) + elf_hwcap2 |= HWCAP2_SHA1; + + tmp = (cpuinfo.id_isar5 >> 12) & 0xF; /* SHA2 */ + if (tmp >= 1) + elf_hwcap2 |= HWCAP2_SHA2; + + tmp = (cpuinfo.id_isar5 >> 16) & 0xF; /* CRC32 */ + if (tmp >= 1) + elf_hwcap2 |= HWCAP2_CRC32; #endif } diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c index fba35eb159c6..cc8ef9994f0f 100644 --- a/sys/arm/arm/elf_machdep.c +++ b/sys/arm/arm/elf_machdep.c @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); static boolean_t elf32_arm_abi_supported(struct image_params *); u_long elf_hwcap; +u_long elf_hwcap2; struct sysentvec elf32_freebsd_sysvec = { .sv_size = SYS_MAXSYSCALL, @@ -92,6 +93,7 @@ struct sysentvec elf32_freebsd_sysvec = { .sv_thread_detach = NULL, .sv_trap = NULL, .sv_hwcap = &elf_hwcap, + .sv_hwcap2 = &elf_hwcap2, }; INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec); diff --git a/sys/arm/arm/vfp.c b/sys/arm/arm/vfp.c index 6a07a5595513..7e3e728ce1d2 100644 --- a/sys/arm/arm/vfp.c +++ b/sys/arm/arm/vfp.c @@ -149,6 +149,8 @@ vfp_init(void) (tmp & VMVFR1_I_MASK) >> VMVFR1_I_OFF == 1 && (tmp & VMVFR1_SP_MASK) >> VMVFR1_SP_OFF == 1) elf_hwcap |= HWCAP_NEON; + if ((tmp & VMVFR1_FMAC_MASK) >> VMVFR1_FMAC_OFF == 1) + elf_hwcap |= HWCAP_VFPv4; } /* initialize the coprocess 10 and 11 calls diff --git a/sys/arm/include/elf.h b/sys/arm/include/elf.h index 7e1564720026..ee854f76adde 100644 --- a/sys/arm/include/elf.h +++ b/sys/arm/include/elf.h @@ -117,10 +117,36 @@ __ElfType(Auxinfo); #define ET_DYN_LOAD_ADDR 0x12000 /* Flags passed in AT_HWCAP. */ +#define HWCAP_SWP 0x00000001 /* Unsupported, never set. */ +#define HWCAP_HALF 0x00000002 /* Always set. */ +#define HWCAP_THUMB 0x00000004 +#define HWCAP_26BIT 0x00000008 /* Unsupported, never set. */ +#define HWCAP_FAST_MULT 0x00000010 /* Always set. */ +#define HWCAP_FPA 0x00000020 /* Unsupported, never set. */ #define HWCAP_VFP 0x00000040 +#define HWCAP_EDSP 0x00000080 /* Always set for ARMv6+. */ +#define HWCAP_JAVA 0x00000100 /* Unsupported, never set. */ +#define HWCAP_IWMMXT 0x00000200 /* Unsupported, never set. */ +#define HWCAP_CRUNCH 0x00000400 /* Unsupported, never set. */ +#define HWCAP_THUMBEE 0x00000800 #define HWCAP_NEON 0x00001000 #define HWCAP_VFPv3 0x00002000 #define HWCAP_VFPv3D16 0x00004000 +#define HWCAP_TLS 0x00008000 /* Always set for ARMv6+. */ +#define HWCAP_VFPv4 0x00010000 +#define HWCAP_IDIVA 0x00020000 +#define HWCAP_IDIVT 0x00040000 #define HWCAP_VFPD32 0x00080000 +#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) +#define HWCAP_LPAE 0x00100000 +#define HWCAP_EVTSTRM 0x00200000 /* Not implemented yet. */ + + +/* Flags passed in AT_HWCAP2. */ +#define HWCAP2_AES 0x00000001 +#define HWCAP2_PMULL 0x00000002 +#define HWCAP2_SHA1 0x00000004 +#define HWCAP2_SHA2 0x00000008 +#define HWCAP2_CRC32 0x00000010 #endif /* !_MACHINE_ELF_H_ */ diff --git a/sys/arm/include/md_var.h b/sys/arm/include/md_var.h index 46d834b9ba36..39a174ee7a42 100644 --- a/sys/arm/include/md_var.h +++ b/sys/arm/include/md_var.h @@ -39,6 +39,7 @@ extern int szsigcode; extern uint32_t *vm_page_dump; extern int vm_page_dump_size; extern u_long elf_hwcap; +extern u_long elf_hwcap2; extern int (*_arm_memcpy)(void *, void *, int, int); extern int (*_arm_bzero)(void *, int, int); diff --git a/sys/arm/include/vfp.h b/sys/arm/include/vfp.h index 94e7a2d20a88..15ae54030005 100644 --- a/sys/arm/include/vfp.h +++ b/sys/arm/include/vfp.h @@ -119,6 +119,12 @@ #define VMVFR0_RB_MASK (0x0000000f) /* VFP 64 bit media support */ /* VMVFR1 */ +#define VMVFR1_FMAC_OFF 28 +#define VMVFR1_FMAC_MASK (0xf0000000) /* Neon FMAC support */ +#define VMVFR1_VFP_HP_OFF 24 +#define VMVFR1_VFP_HP_MASK (0x0f000000) /* VFP half prec support */ +#define VMVFR1_HP_OFF 20 +#define VMVFR1_HP_MASK (0x00f00000) /* Neon half prec support */ #define VMVFR1_SP_OFF 16 #define VMVFR1_SP_MASK (0x000f0000) /* Neon single prec support */ #define VMVFR1_I_OFF 12