Browse Source

Detect broken RDRAND during initialization

Some CPUs advertise RDRAND in CPUID, but return 0xFFFFFFFF
unconditionally. To avoid locking up later, test RDRAND during
initialization, and if it returns 0xFFFFFFFF, mark it as nonexistent.

Fixes #588.
pull/603/head
Tudor Brindus Björn Esser 5 years ago
parent
commit
23005a7d9d
1 changed files with 33 additions and 4 deletions
  1. +33
    -4
      random_seed.c

+ 33
- 4
random_seed.c View File

@@ -43,12 +43,41 @@ static void do_cpuid(int regs[], int h)

#if HAS_X86_CPUID

static int get_rdrand_seed(void);

// Valid values are -1 (haven't tested), 0 (no), and 1 (yes).
static int _has_rdrand = -1;

static int has_rdrand(void)
{
// CPUID.01H:ECX.RDRAND[bit 30] == 1
int regs[4];
do_cpuid(regs, 1);
return (regs[2] & (1 << 30)) != 0;
if (_has_rdrand == -1)
{
// CPUID.01H:ECX.RDRAND[bit 30] == 1
int regs[4];
do_cpuid(regs, 1);
if (!(regs[2] & (1 << 30)))
{
_has_rdrand = 0;
} else
{
// Some CPUs advertise RDRAND in CPUID, but return 0xFFFFFFFF
// unconditionally. To avoid locking up later, test RDRAND here. If over
// 10 trials RDRAND has returned the same value, declare it broken.
_has_rdrand = 0;
int prev = get_rdrand_seed();
for (int i = 0; i < 10; i++) {
int temp = get_rdrand_seed();
if (temp != prev) {
_has_rdrand = 1;
break;
}

prev = temp;
}
}
}

return _has_rdrand;
}

#endif


Loading…
Cancel
Save