struct cpuid { unsigned a, b, c, d; };
extern int dispatch_x86ish_cpuid(struct cpuid *, unsigned a, unsigned c);
extern int dispatch_x86ish_xmmregisters_p(void);
+extern int dispatch_x86ish_rdrand(unsigned *);
static void cpuid(struct cpuid *cc, unsigned a, unsigned c)
{
return (f);
}
+/* --- @rdrand_works_p@ --- *
+ *
+ *
+ * Arguments: ---
+ *
+ * Returns: Nonzero if the `rdrand' instruction actually works. Assumes
+ * that it's already been verified to be safe to issue.
+ */
+
+static int rdrand_works_p(void)
+{
+ unsigned ref, x, i;
+
+ /* Check that it doesn't always give the same answer. Try four times: this
+ * will fail with probability %$2^{-128}$% with a truly random generator,
+ * which seems fair enough.
+ */
+ if (dispatch_x86ish_rdrand(&ref)) goto fail;
+ for (i = 0; i < 4; i++) {
+ if (dispatch_x86ish_rdrand(&x)) goto fail;
+ if (x != ref) goto not_stuck;
+ }
+ dispatch_debug("RDRAND always returns 0x%08x!", ref);
+ return (0);
+
+not_stuck:
+ dispatch_debug("RDRAND instruction looks plausible");
+ return (1);
+
+fail:
+ dispatch_debug("RDRAND instruction fails too often");
+ return (0);
+}
+
#endif
/*----- General feature probing using auxiliary vectors -------------------*/
# define WANTAUX(_) \
WANT_AT_HWCAP(_)
# define CAPMAP(_) \
+ _(ARM_NEON, "arm:neon") \
_(ARM_AES, "arm:aes") \
_(ARM_PMULL, "arm:pmull")
#endif
# endif
#endif
#if CPUFAM_ARM64
+ if (probed.hwcap & HWCAP_ASIMD) hw |= HF_ARM_NEON;
if (probed.hwcap & HWCAP_AES) hw |= HF_ARM_AES;
if (probed.hwcap & HWCAP_PMULL) hw |= HF_ARM_PMULL;
#endif
if (!p) return (-1);
for (;;) {
- while (isspace((unsigned char)*p)) p++;
+ while (ISSPACE(*p)) p++;
if (!*p) return (-1);
switch (*p) {
case '+': d = +1; p++; break;
case '-': d = 0; p++; break;
default: d = -1; break;
}
- for (q = p; *q && !isspace((unsigned char)*q); q++);
+ for (q = p; *q && !ISSPACE(*q); q++);
if (d >= 0) {
for (pp = ftok; p < q && *pp && *p == *pp; p++, pp++);
if ((p == q && !*pp) || (*p == '*' && p + 1 == q)) return (d);
cpuid_features_p(CPUID1D_SSE2, CPUID1C_AESNI) &&
xmm_registers_available_p());
CASE_CPUFEAT(X86_RDRAND, "x86:rdrand",
- cpuid_features_p(0, CPUID1C_RDRAND));
+ cpuid_features_p(0, CPUID1C_RDRAND) && rdrand_works_p());
CASE_CPUFEAT(X86_AVX, "x86:avx",
cpuid_features_p(0, CPUID1C_AVX) &&
xmm_registers_available_p());