From 6031485b6ac1cfd8d2fe566ec0053a3941e253c8 Mon Sep 17 00:00:00 2001 From: tb <> Date: Wed, 23 Mar 2022 15:13:31 +0000 Subject: Start disentangling armv7 and aarch64 code arm_arch.h and armcap.c are shared between armv7 and aarch64 which results in an inscrutable #ifdef maze. Move copies of these files into arch/{arm,aarch64}/ with appropriate names and some trivial minor adjustments. ok deraadt inoguchi kettenis --- src/lib/libcrypto/arch/aarch64/Makefile.inc | 4 +- src/lib/libcrypto/arch/aarch64/arm64_arch.h | 59 ++++++++++ src/lib/libcrypto/arch/aarch64/arm64cap.c | 88 +++++++++++++++ src/lib/libcrypto/arch/aarch64/arm64cpuid.S | 47 ++++++++ src/lib/libcrypto/arch/arm/arm_arch.h | 59 ++++++++++ src/lib/libcrypto/arch/arm/armcap.c | 88 +++++++++++++++ src/lib/libcrypto/arch/arm/armv4cpuid.S | 165 ++++++++++++++++++++++++++++ 7 files changed, 508 insertions(+), 2 deletions(-) create mode 100644 src/lib/libcrypto/arch/aarch64/arm64_arch.h create mode 100644 src/lib/libcrypto/arch/aarch64/arm64cap.c create mode 100644 src/lib/libcrypto/arch/aarch64/arm64cpuid.S create mode 100644 src/lib/libcrypto/arch/arm/arm_arch.h create mode 100644 src/lib/libcrypto/arch/arm/armcap.c create mode 100644 src/lib/libcrypto/arch/arm/armv4cpuid.S (limited to 'src/lib/libcrypto/arch') diff --git a/src/lib/libcrypto/arch/aarch64/Makefile.inc b/src/lib/libcrypto/arch/aarch64/Makefile.inc index d3d33e5941..48a340a6a2 100644 --- a/src/lib/libcrypto/arch/aarch64/Makefile.inc +++ b/src/lib/libcrypto/arch/aarch64/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.2 2019/07/02 19:31:28 patrick Exp $ +# $OpenBSD: Makefile.inc,v 1.3 2022/03/23 15:13:31 tb Exp $ # aarch64-specific libcrypto build rules @@ -28,4 +28,4 @@ ${f}.S: ${LCRYPTO_SRC}/${dir}/asm/${f}.pl .endfor CFLAGS+= -DOPENSSL_CPUID_OBJ -SRCS+= arm64cpuid.S armcap.c +SRCS+= arm64cpuid.S arm64cap.c diff --git a/src/lib/libcrypto/arch/aarch64/arm64_arch.h b/src/lib/libcrypto/arch/aarch64/arm64_arch.h new file mode 100644 index 0000000000..7f35acaa7d --- /dev/null +++ b/src/lib/libcrypto/arch/aarch64/arm64_arch.h @@ -0,0 +1,59 @@ +/* $OpenBSD: arm64_arch.h,v 1.1 2022/03/23 15:13:31 tb Exp $ */ +#ifndef __ARM_ARCH_H__ +#define __ARM_ARCH_H__ + +#if !defined(__ARM_ARCH__) +# if defined(__CC_ARM) +# define __ARM_ARCH__ __TARGET_ARCH_ARM +# if defined(__BIG_ENDIAN) +# define __ARMEB__ +# else +# define __ARMEL__ +# endif +# elif defined(__GNUC__) + /* + * Why doesn't gcc define __ARM_ARCH__? Instead it defines + * bunch of below macros. See all_architectures[] table in + * gcc/config/arm/arm.c. On a side note it defines + * __ARMEL__/__ARMEB__ for little-/big-endian. + */ +# if defined(__ARM_ARCH) +# define __ARM_ARCH__ __ARM_ARCH +# elif defined(__ARM_ARCH_8A__) +# define __ARM_ARCH__ 8 +# elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ + defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \ + defined(__ARM_ARCH_7EM__) +# define __ARM_ARCH__ 7 +# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__) || \ + defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__) || \ + defined(__ARM_ARCH_6T2__) +# define __ARM_ARCH__ 6 +# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \ + defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__) || \ + defined(__ARM_ARCH_5TEJ__) +# define __ARM_ARCH__ 5 +# elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) +# define __ARM_ARCH__ 4 +# else +# error "unsupported ARM architecture" +# endif +# endif +#endif + +#if !defined(__ASSEMBLER__) +extern unsigned int OPENSSL_armcap_P; + +#define ARMV7_NEON (1<<0) +#define ARMV8_AES (1<<1) +#define ARMV8_SHA1 (1<<2) +#define ARMV8_SHA256 (1<<3) +#define ARMV8_PMULL (1<<4) +#endif + +#if defined(__OpenBSD__) +#define __STRICT_ALIGNMENT +#endif + +#endif diff --git a/src/lib/libcrypto/arch/aarch64/arm64cap.c b/src/lib/libcrypto/arch/aarch64/arm64cap.c new file mode 100644 index 0000000000..b541ac31b9 --- /dev/null +++ b/src/lib/libcrypto/arch/aarch64/arm64cap.c @@ -0,0 +1,88 @@ +/* $OpenBSD: arm64cap.c,v 1.1 2022/03/23 15:13:31 tb Exp $ */ +#include +#include +#include +#include +#include +#include + +#include "arm64_arch.h" + +unsigned int OPENSSL_armcap_P; + +#if __ARM_ARCH__ >= 7 +static sigset_t all_masked; + +static sigjmp_buf ill_jmp; + static void ill_handler (int sig) { siglongjmp(ill_jmp, sig); +} + +/* + * Following subroutines could have been inlined, but it's not all + * ARM compilers support inline assembler... + */ +void _armv7_neon_probe(void); +void _armv8_aes_probe(void); +void _armv8_sha1_probe(void); +void _armv8_sha256_probe(void); +void _armv8_pmull_probe(void); +#endif + +#if defined(__GNUC__) && __GNUC__>=2 +void OPENSSL_cpuid_setup(void) __attribute__((constructor)); +#endif + +void +OPENSSL_cpuid_setup(void) +{ +#if __ARM_ARCH__ >= 7 + struct sigaction ill_oact, ill_act; + sigset_t oset; +#endif + static int trigger = 0; + + if (trigger) + return; + trigger = 1; + + OPENSSL_armcap_P = 0; + +#if __ARM_ARCH__ >= 7 + sigfillset(&all_masked); + sigdelset(&all_masked, SIGILL); + sigdelset(&all_masked, SIGTRAP); + sigdelset(&all_masked, SIGFPE); + sigdelset(&all_masked, SIGBUS); + sigdelset(&all_masked, SIGSEGV); + + memset(&ill_act, 0, sizeof(ill_act)); + ill_act.sa_handler = ill_handler; + ill_act.sa_mask = all_masked; + + sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); + sigaction(SIGILL, &ill_act, &ill_oact); + + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv7_neon_probe(); + OPENSSL_armcap_P |= ARMV7_NEON; + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_pmull_probe(); + OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; + } else if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_aes_probe(); + OPENSSL_armcap_P |= ARMV8_AES; + } + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_sha1_probe(); + OPENSSL_armcap_P |= ARMV8_SHA1; + } + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_sha256_probe(); + OPENSSL_armcap_P |= ARMV8_SHA256; + } + } + + sigaction (SIGILL, &ill_oact, NULL); + sigprocmask(SIG_SETMASK, &oset, NULL); +#endif +} diff --git a/src/lib/libcrypto/arch/aarch64/arm64cpuid.S b/src/lib/libcrypto/arch/aarch64/arm64cpuid.S new file mode 100644 index 0000000000..d267ad6897 --- /dev/null +++ b/src/lib/libcrypto/arch/aarch64/arm64cpuid.S @@ -0,0 +1,47 @@ +#include "arm64_arch.h" + +.text +.arch armv8-a+crypto+sha3 + +.align 5 +.globl _armv7_neon_probe +.type _armv7_neon_probe,%function +_armv7_neon_probe: + orr v15.16b, v15.16b, v15.16b + ret +.size _armv7_neon_probe,.-_armv7_neon_probe + +.globl _armv8_aes_probe +.type _armv8_aes_probe,%function +_armv8_aes_probe: + aese v0.16b, v0.16b + ret +.size _armv8_aes_probe,.-_armv8_aes_probe + +.globl _armv8_sha1_probe +.type _armv8_sha1_probe,%function +_armv8_sha1_probe: + sha1h s0, s0 + ret +.size _armv8_sha1_probe,.-_armv8_sha1_probe + +.globl _armv8_sha256_probe +.type _armv8_sha256_probe,%function +_armv8_sha256_probe: + sha256su0 v0.4s, v0.4s + ret +.size _armv8_sha256_probe,.-_armv8_sha256_probe + +.globl _armv8_pmull_probe +.type _armv8_pmull_probe,%function +_armv8_pmull_probe: + pmull v0.1q, v0.1d, v0.1d + ret +.size _armv8_pmull_probe,.-_armv8_pmull_probe + +.globl _armv8_sha512_probe +.type _armv8_sha512_probe,%function +_armv8_sha512_probe: + sha512su0 v0.2d,v0.2d + ret +.size _armv8_sha512_probe,.-_armv8_sha512_probe diff --git a/src/lib/libcrypto/arch/arm/arm_arch.h b/src/lib/libcrypto/arch/arm/arm_arch.h new file mode 100644 index 0000000000..5ac3b935f1 --- /dev/null +++ b/src/lib/libcrypto/arch/arm/arm_arch.h @@ -0,0 +1,59 @@ +/* $OpenBSD: arm_arch.h,v 1.1 2022/03/23 15:13:31 tb Exp $ */ +#ifndef __ARM_ARCH_H__ +#define __ARM_ARCH_H__ + +#if !defined(__ARM_ARCH__) +# if defined(__CC_ARM) +# define __ARM_ARCH__ __TARGET_ARCH_ARM +# if defined(__BIG_ENDIAN) +# define __ARMEB__ +# else +# define __ARMEL__ +# endif +# elif defined(__GNUC__) + /* + * Why doesn't gcc define __ARM_ARCH__? Instead it defines + * bunch of below macros. See all_architectures[] table in + * gcc/config/arm/arm.c. On a side note it defines + * __ARMEL__/__ARMEB__ for little-/big-endian. + */ +# if defined(__ARM_ARCH) +# define __ARM_ARCH__ __ARM_ARCH +# elif defined(__ARM_ARCH_8A__) +# define __ARM_ARCH__ 8 +# elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ + defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \ + defined(__ARM_ARCH_7EM__) +# define __ARM_ARCH__ 7 +# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__) || \ + defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__) || \ + defined(__ARM_ARCH_6T2__) +# define __ARM_ARCH__ 6 +# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \ + defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__) || \ + defined(__ARM_ARCH_5TEJ__) +# define __ARM_ARCH__ 5 +# elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) +# define __ARM_ARCH__ 4 +# else +# error "unsupported ARM architecture" +# endif +# endif +#endif + +#if !defined(__ASSEMBLER__) +extern unsigned int OPENSSL_armcap_P; + +#define ARMV7_NEON (1<<0) +#define ARMV8_AES (1<<1) +#define ARMV8_SHA1 (1<<2) +#define ARMV8_SHA256 (1<<3) +#define ARMV8_PMULL (1<<4) +#endif + +#if defined(__OpenBSD__) +#define __STRICT_ALIGNMENT +#endif + +#endif diff --git a/src/lib/libcrypto/arch/arm/armcap.c b/src/lib/libcrypto/arch/arm/armcap.c new file mode 100644 index 0000000000..e1a721b71f --- /dev/null +++ b/src/lib/libcrypto/arch/arm/armcap.c @@ -0,0 +1,88 @@ +/* $OpenBSD: armcap.c,v 1.1 2022/03/23 15:13:31 tb Exp $ */ +#include +#include +#include +#include +#include +#include + +#include "arm_arch.h" + +unsigned int OPENSSL_armcap_P; + +#if __ARM_ARCH__ >= 7 +static sigset_t all_masked; + +static sigjmp_buf ill_jmp; + static void ill_handler (int sig) { siglongjmp(ill_jmp, sig); +} + +/* + * Following subroutines could have been inlined, but it's not all + * ARM compilers support inline assembler... + */ +void _armv7_neon_probe(void); +void _armv8_aes_probe(void); +void _armv8_sha1_probe(void); +void _armv8_sha256_probe(void); +void _armv8_pmull_probe(void); +#endif + +#if defined(__GNUC__) && __GNUC__>=2 +void OPENSSL_cpuid_setup(void) __attribute__((constructor)); +#endif + +void +OPENSSL_cpuid_setup(void) +{ +#if __ARM_ARCH__ >= 7 + struct sigaction ill_oact, ill_act; + sigset_t oset; +#endif + static int trigger = 0; + + if (trigger) + return; + trigger = 1; + + OPENSSL_armcap_P = 0; + +#if __ARM_ARCH__ >= 7 + sigfillset(&all_masked); + sigdelset(&all_masked, SIGILL); + sigdelset(&all_masked, SIGTRAP); + sigdelset(&all_masked, SIGFPE); + sigdelset(&all_masked, SIGBUS); + sigdelset(&all_masked, SIGSEGV); + + memset(&ill_act, 0, sizeof(ill_act)); + ill_act.sa_handler = ill_handler; + ill_act.sa_mask = all_masked; + + sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset); + sigaction(SIGILL, &ill_act, &ill_oact); + + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv7_neon_probe(); + OPENSSL_armcap_P |= ARMV7_NEON; + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_pmull_probe(); + OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES; + } else if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_aes_probe(); + OPENSSL_armcap_P |= ARMV8_AES; + } + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_sha1_probe(); + OPENSSL_armcap_P |= ARMV8_SHA1; + } + if (sigsetjmp(ill_jmp, 1) == 0) { + _armv8_sha256_probe(); + OPENSSL_armcap_P |= ARMV8_SHA256; + } + } + + sigaction (SIGILL, &ill_oact, NULL); + sigprocmask(SIG_SETMASK, &oset, NULL); +#endif +} diff --git a/src/lib/libcrypto/arch/arm/armv4cpuid.S b/src/lib/libcrypto/arch/arm/armv4cpuid.S new file mode 100644 index 0000000000..bb9abafebe --- /dev/null +++ b/src/lib/libcrypto/arch/arm/armv4cpuid.S @@ -0,0 +1,165 @@ +#include "arm_arch.h" + +.text +#if defined(__thumb2__) && !defined(__APPLE__) +.syntax unified +.thumb +#else +.code 32 +#undef __thumb2__ +#endif + +.align 5 +.globl OPENSSL_atomic_add +.type OPENSSL_atomic_add,%function +OPENSSL_atomic_add: +#if __ARM_ARCH__>=6 +.Ladd: ldrex r2,[r0] + add r3,r2,r1 + strex r2,r3,[r0] + cmp r2,#0 + bne .Ladd + mov r0,r3 + bx lr +#else + stmdb sp!,{r4,r5,r6,lr} + ldr r2,.Lspinlock + adr r3,.Lspinlock + mov r4,r0 + mov r5,r1 + add r6,r3,r2 @ &spinlock + b .+8 +.Lspin: bl sched_yield + mov r0,#-1 + swp r0,r0,[r6] + cmp r0,#0 + bne .Lspin + + ldr r2,[r4] + add r2,r2,r5 + str r2,[r4] + str r0,[r6] @ release spinlock + ldmia sp!,{r4,r5,r6,lr} + tst lr,#1 + moveq pc,lr +.word 0xe12fff1e @ bx lr +#endif +.size OPENSSL_atomic_add,.-OPENSSL_atomic_add + +#if __ARM_ARCH__>=7 +.arch armv7-a +.fpu neon + +.align 5 +.globl _armv7_neon_probe +.type _armv7_neon_probe,%function +_armv7_neon_probe: + vorr q0,q0,q0 + bx lr +.size _armv7_neon_probe,.-_armv7_neon_probe + +.globl _armv8_aes_probe +.type _armv8_aes_probe,%function +_armv8_aes_probe: +#if defined(__thumb2__) && !defined(__APPLE__) +.byte 0xb0,0xff,0x00,0x03 @ aese.8 q0,q0 +#else +.byte 0x00,0x03,0xb0,0xf3 @ aese.8 q0,q0 +#endif + bx lr +.size _armv8_aes_probe,.-_armv8_aes_probe + +.globl _armv8_sha1_probe +.type _armv8_sha1_probe,%function +_armv8_sha1_probe: +#if defined(__thumb2__) && !defined(__APPLE__) +.byte 0x00,0xef,0x40,0x0c @ sha1c.32 q0,q0,q0 +#else +.byte 0x40,0x0c,0x00,0xf2 @ sha1c.32 q0,q0,q0 +#endif + bx lr +.size _armv8_sha1_probe,.-_armv8_sha1_probe + +.globl _armv8_sha256_probe +.type _armv8_sha256_probe,%function +_armv8_sha256_probe: +#if defined(__thumb2__) && !defined(__APPLE__) +.byte 0x00,0xff,0x40,0x0c @ sha256h.32 q0,q0,q0 +#else +.byte 0x40,0x0c,0x00,0xf3 @ sha256h.32 q0,q0,q0 +#endif + bx lr +.size _armv8_sha256_probe,.-_armv8_sha256_probe +.globl _armv8_pmull_probe +.type _armv8_pmull_probe,%function +_armv8_pmull_probe: +#if defined(__thumb2__) && !defined(__APPLE__) +.byte 0xa0,0xef,0x00,0x0e @ vmull.p64 q0,d0,d0 +#else +.byte 0x00,0x0e,0xa0,0xf2 @ vmull.p64 q0,d0,d0 +#endif + bx lr +.size _armv8_pmull_probe,.-_armv8_pmull_probe +#endif + +.globl OPENSSL_wipe_cpu +.type OPENSSL_wipe_cpu,%function +OPENSSL_wipe_cpu: +#if __ARM_ARCH__>=7 + ldr r0,.LOPENSSL_armcap + adr r1,.LOPENSSL_armcap + ldr r0,[r1,r0] +#ifdef __APPLE__ + ldr r0,[r0] +#endif +#endif + eor r2,r2,r2 + eor r3,r3,r3 + eor ip,ip,ip +#if __ARM_ARCH__>=7 + tst r0,#1 + beq .Lwipe_done + veor q0, q0, q0 + veor q1, q1, q1 + veor q2, q2, q2 + veor q3, q3, q3 + veor q8, q8, q8 + veor q9, q9, q9 + veor q10, q10, q10 + veor q11, q11, q11 + veor q12, q12, q12 + veor q13, q13, q13 + veor q14, q14, q14 + veor q15, q15, q15 +.Lwipe_done: +#endif + mov r0,sp +#if __ARM_ARCH__>=5 + bx lr +#else + tst lr,#1 + moveq pc,lr +.word 0xe12fff1e @ bx lr +#endif +.size OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu + +.align 5 +#if __ARM_ARCH__>=7 +.LOPENSSL_armcap: +.word OPENSSL_armcap_P-. +#endif +#if __ARM_ARCH__>=6 +.align 5 +#else +.Lspinlock: +.word atomic_add_spinlock-.Lspinlock +.align 5 + +.data +.align 2 +atomic_add_spinlock: +.word 0 +#endif + +.comm OPENSSL_armcap_P,4,4 +.hidden OPENSSL_armcap_P -- cgit v1.2.3-55-g6feb