1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
/* $OpenBSD: arm64cap.c,v 1.2 2022/03/25 17:42:07 robert Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <signal.h>
#include <openssl/crypto.h>
#if defined(__OpenBSD__)
#include <sys/sysctl.h>
#include <machine/cpu.h> /* CPU_ID_AA64ISAR0 */
#endif
#include "arm64_arch.h"
/* ID_AA64ISAR0_EL1 required for OPENSSL_cpuid_setup */
#define ID_AA64ISAR0_AES_SHIFT 4
#define ID_AA64ISAR0_AES_MASK (0xf << ID_AA64ISAR0_AES_SHIFT)
#define ID_AA64ISAR0_AES(x) ((x) & ID_AA64ISAR0_AES_MASK)
#define ID_AA64ISAR0_AES_BASE (0x1 << ID_AA64ISAR0_AES_SHIFT)
#define ID_AA64ISAR0_AES_PMULL (0x2 << ID_AA64ISAR0_AES_SHIFT)
#define ID_AA64ISAR0_SHA1_SHIFT 8
#define ID_AA64ISAR0_SHA1_MASK (0xf << ID_AA64ISAR0_SHA1_SHIFT)
#define ID_AA64ISAR0_SHA1(x) ((x) & ID_AA64ISAR0_SHA1_MASK)
#define ID_AA64ISAR0_SHA1_BASE (0x1 << ID_AA64ISAR0_SHA1_SHIFT)
#define ID_AA64ISAR0_SHA2_SHIFT 12
#define ID_AA64ISAR0_SHA2_MASK (0xf << ID_AA64ISAR0_SHA2_SHIFT)
#define ID_AA64ISAR0_SHA2(x) ((x) & ID_AA64ISAR0_SHA2_MASK)
#define ID_AA64ISAR0_SHA2_BASE (0x1 << ID_AA64ISAR0_SHA2_SHIFT)
unsigned int OPENSSL_armcap_P;
#if defined(__GNUC__) && __GNUC__ >= 2
void OPENSSL_cpuid_setup(void) __attribute__((constructor));
#endif
#if defined(CPU_ID_AA64ISAR0)
void
OPENSSL_cpuid_setup(void)
{
int isar0_mib[] = { CTL_MACHDEP, CPU_ID_AA64ISAR0 };
size_t len = sizeof(uint64_t);
uint64_t cpu_id = 0;
if (OPENSSL_armcap_P != 0)
return;
if (sysctl(isar0_mib, 2, &cpu_id, &len, NULL, 0) < 0)
return;
OPENSSL_armcap_P |= ARMV7_NEON;
if (ID_AA64ISAR0_AES(cpu_id) >= ID_AA64ISAR0_AES_BASE)
OPENSSL_armcap_P |= ARMV8_AES;
if (ID_AA64ISAR0_AES(cpu_id) >= ID_AA64ISAR0_AES_PMULL)
OPENSSL_armcap_P |= ARMV8_PMULL;
if (ID_AA64ISAR0_SHA1(cpu_id) >= ID_AA64ISAR0_SHA1_BASE)
OPENSSL_armcap_P |= ARMV8_SHA1;
if (ID_AA64ISAR0_SHA2(cpu_id) >= ID_AA64ISAR0_SHA2_BASE)
OPENSSL_armcap_P |= ARMV8_SHA256;
}
#else
#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
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
}
#endif
|