/// Checking `rdrand'.
FUNC(dispatch_x86ish_rdrand)
- // Enter with two arguments: a code OP requesting `rdrand' (0), and a
- // pointer X_OUT to a 32-bit word. Try to generate a random word
- // using the requested instruction. If successful, set *X_OUT to the
- // generated word, and return zero; otherwise, return -1.
+ // Enter with two arguments: a code OP requesting either `rdrand' (0)
+ // or `rdseed' (1), and a pointer X_OUT to a 32-bit word. Try to
+ // generate a random word using the requested instruction'. If
+ // successful, set *X_OUT to the generated word, and return zero;
+ // otherwise, return -1.
#if CPUFAM_X86
# define OP eax
#endif
endprologue
+ cmp OP, 0
mov COUNT, 16 // fairly persistent
+ jne 1f
+
0: rdrand eax
jc 9f
dec COUNT
jnz 0b
jmp 8f
+1: rdseed eax
+ jc 9f
+ dec COUNT
+ jnz 1b
+ jmp 8f
+
// Failed to come up with a random value.
8: mov eax, -1
ret
# define CPUID1C_AVX (1u << 28)
# define CPUID1C_RDRAND (1u << 30)
+ CPUID_7_0_B, /* eax = 7, ecx = 0 => ebx&?? */
+# define CPUID70B_RDSEED (1u << 18)
};
struct cpuid { unsigned a, b, c, d; };
if (cpuid_maxleaf() < 1) return (0);
cpuid(&c, 1, 0); r = c.c;
break;
+ case CPUID_7_0_B:
+ if (cpuid_maxleaf() < 7) return (0);
+ cpuid(&c, 7, 0); r = c.b;
+ break;
default:
assert(!"unknown cpuid leaf");
}
switch (op) {
case OP_RDRAND: what = "RDRAND"; break;
+ case OP_RDSEED: what = "RDSEED"; break;
default: assert(!"unexpected op");
}
CASE_CPUFEAT(X86_PCLMUL, "x86:pclmul",
cpuid_feature_p(CPUID_1_C, CPUID1C_PCLMUL) &&
xmm_registers_available_p());
+ CASE_CPUFEAT(X86_RDSEED, "x86:rdseed",
+ cpuid_feature_p(CPUID_7_0_B, CPUID70B_RDSEED) &&
+ rdrand_works_p(OP_RDSEED));
#endif
#ifdef CAPMAP
# define FEATP__CASE(feat, tok) \
CPUFEAT_ARM_NEON, /* Advanced SIMD (v1 or v2) */
CPUFEAT_ARM_V4, /* VFPv4 and/or SIMD v2 */
CPUFEAT_ARM_D32, /* 32 double registers, not 16 */
- CPUFEAT_X86_RDRAND, /* Built-in entropy source */
+ CPUFEAT_X86_RDRAND, /* Built-in cooked entropy source */
CPUFEAT_ARM_AES, /* AES instructions */
CPUFEAT_X86_AVX, /* AVX 1 (i.e., 256-bit YMM regs) */
CPUFEAT_X86_SSSE3, /* Supplementary SSE 3 */
CPUFEAT_X86_PCLMUL, /* Carry-less multiplication */
- CPUFEAT_ARM_PMULL /* Polynomial multiplication */
+ CPUFEAT_ARM_PMULL, /* Polynomial multiplication */
+ CPUFEAT_X86_RDSEED /* Built-in raw entropy source */
};
extern int cpu_feature_p(int /*feat*/);
rand_seed@Base 2.2.3
rand_quick@Base 2.5.2
(optional|arch=i386 amd64)rand_quick_x86ish_rdrand@Base 2.5.0
+ (optional|arch=i386 amd64)rand_quick_x86ish_rdseed@Base 2.5.99~
rand_key@Base 2.5.2
rand_add@Base 2.2.3
rand_goodbits@Base 2.2.3
// Failed.
mov eax, -1
jmp 9f
+ENDFUNC
+
+FUNC(rand_quick_x86ish_rdseed)
+ // Enter with a pointer to the random context in the first argument.
+ // Return zero on success, or -1 on error.
+
+#if CPUFAM_X86
+ mov edx, [SP + 4]
+ stalloc 28
+#endif
+#if CPUFAM_AMD64 && ABI_SYSV
+ stalloc 8
+#endif
+#if CPUFAM_AMD64 && ABI_WIN
+ stalloc 40
+#endif
+ endprologue
+
+ // Try to fetch a random number.
+ mov COUNT, 16
+0: rdseed AX
+ jc 1f
+ dec COUNT
+ jnz 0b
+
+ // Failed.
+ mov eax, -1
+ jmp 9f
// Success.
1:
#if CPUFAM_X86 || CPUFAM_AMD64
extern int rand_quick_x86ish_rdrand(rand_pool */*r*/);
+extern int rand_quick_x86ish_rdseed(rand_pool */*r*/);
#endif
static quick__functype *pick_quick(void)
{
#if CPUFAM_X86 || CPUFAM_AMD64
+ DISPATCH_PICK_COND(rand_quick, rand_quick_x86ish_rdseed,
+ cpu_feature_p(CPUFEAT_X86_RDSEED));
DISPATCH_PICK_COND(rand_quick, rand_quick_x86ish_rdrand,
cpu_feature_p(CPUFEAT_X86_RDRAND));
#endif