+# define OSSL_HWCAP AT_HWCAP
+# define OSSL_HWCAP_NEON (1 << 1)
+
+# define OSSL_HWCAP_CE AT_HWCAP
+# define OSSL_HWCAP_CE_AES (1 << 3)
+# define OSSL_HWCAP_CE_PMULL (1 << 4)
+# define OSSL_HWCAP_CE_SHA1 (1 << 5)
+# define OSSL_HWCAP_CE_SHA256 (1 << 6)
+# define OSSL_HWCAP_CPUID (1 << 11)
+# define OSSL_HWCAP_SHA3 (1 << 17)
+# define OSSL_HWCAP_CE_SM3 (1 << 18)
+# define OSSL_HWCAP_CE_SM4 (1 << 19)
+# define OSSL_HWCAP_CE_SHA512 (1 << 21)
+# define OSSL_HWCAP_SVE (1 << 22)
+ /* AT_HWCAP2 */
+# define OSSL_HWCAP2 26
+# define OSSL_HWCAP2_SVE2 (1 << 1)
+# define OSSL_HWCAP2_RNG (1 << 16)
+# endif
+
+uint32_t _armv7_tick(void);
+
+uint32_t OPENSSL_rdtsc(void)
+{
+ if (OPENSSL_armcap_P & ARMV7_TICK)
+ return _armv7_tick();
+ else
+ return 0;
+}
+
+# ifdef __aarch64__
+size_t OPENSSL_rndr_asm(unsigned char *buf, size_t len);
+size_t OPENSSL_rndrrs_asm(unsigned char *buf, size_t len);
+
+size_t OPENSSL_rndr_bytes(unsigned char *buf, size_t len);
+size_t OPENSSL_rndrrs_bytes(unsigned char *buf, size_t len);
+
+static size_t OPENSSL_rndr_wrapper(size_t (*func)(unsigned char *, size_t), unsigned char *buf, size_t len)
+{
+ size_t buffer_size = 0;
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ buffer_size = func(buf, len);
+ if (buffer_size == len)
+ break;
+ usleep(5000); /* 5000 microseconds (5 milliseconds) */
+ }
+ return buffer_size;
+}
+
+size_t OPENSSL_rndr_bytes(unsigned char *buf, size_t len)
+{
+ return OPENSSL_rndr_wrapper(OPENSSL_rndr_asm, buf, len);
+}
+
+size_t OPENSSL_rndrrs_bytes(unsigned char *buf, size_t len)
+{
+ return OPENSSL_rndr_wrapper(OPENSSL_rndrrs_asm, buf, len);
+}
+# endif
+
+# if !defined(__APPLE__) && !defined(OSSL_IMPLEMENT_GETAUXVAL)
+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 not all
+ * ARM compilers support inline assembler, and we'd then have to
+ * worry about the compiler optimising out the detection code...
+ */
+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);
+# ifdef __aarch64__
+void _armv8_sm3_probe(void);
+void _armv8_sm4_probe(void);
+void _armv8_sha512_probe(void);
+void _armv8_eor3_probe(void);
+void _armv8_sve_probe(void);
+void _armv8_sve2_probe(void);
+void _armv8_rng_probe(void);
+# endif
+# endif /* !__APPLE__ && !OSSL_IMPLEMENT_GETAUXVAL */
+
+/* We only call _armv8_cpuid_probe() if (OPENSSL_armcap_P & ARMV8_CPUID) != 0 */
+unsigned int _armv8_cpuid_probe(void);
+
+# if defined(__APPLE__)
+/*
+ * Checks the specified integer sysctl, returning `value` if it's 1, otherwise returning 0.
+ */
+static unsigned int sysctl_query(const char *name, unsigned int value)
+{
+ unsigned int sys_value = 0;
+ size_t len = sizeof(sys_value);
+
+ return (sysctlbyname(name, &sys_value, &len, NULL, 0) == 0 && sys_value == 1) ? value : 0;
+}
+# elif !defined(OSSL_IMPLEMENT_GETAUXVAL)
+/*
+ * Calls a provided probe function, which may SIGILL. If it doesn't, return `value`, otherwise return 0.
+ */
+static unsigned int arm_probe_for(void (*probe)(void), volatile unsigned int value)
+{
+ if (sigsetjmp(ill_jmp, 1) == 0) {
+ probe();
+ return value;
+ } else {
+ /* The probe function gave us SIGILL */
+ return 0;
+ }
+}