diff options
Diffstat (limited to 'arch/x86/kernel/cpu/rdrand.c')
-rw-r--r-- | arch/x86/kernel/cpu/rdrand.c | 25 |
1 files changed, 12 insertions, 13 deletions
diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c index 136ac74dee82..819d94982e07 100644 --- a/arch/x86/kernel/cpu/rdrand.c +++ b/arch/x86/kernel/cpu/rdrand.c | |||
@@ -33,28 +33,27 @@ static int __init x86_rdrand_setup(char *s) | |||
33 | __setup("nordrand", x86_rdrand_setup); | 33 | __setup("nordrand", x86_rdrand_setup); |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * Force a reseed cycle; we are architecturally guaranteed a reseed | 36 | * RDRAND has Built-In-Self-Test (BIST) that runs on every invocation. |
37 | * after no more than 512 128-bit chunks of random data. This also | 37 | * Run the instruction a few times as a sanity check. |
38 | * acts as a test of the CPU capability. | 38 | * If it fails, it is simple to disable RDRAND here. |
39 | */ | 39 | */ |
40 | #define RESEED_LOOP ((512*128)/sizeof(unsigned long)) | 40 | #define SANITY_CHECK_LOOPS 8 |
41 | 41 | ||
42 | void x86_init_rdrand(struct cpuinfo_x86 *c) | 42 | void x86_init_rdrand(struct cpuinfo_x86 *c) |
43 | { | 43 | { |
44 | #ifdef CONFIG_ARCH_RANDOM | 44 | #ifdef CONFIG_ARCH_RANDOM |
45 | unsigned long tmp; | 45 | unsigned long tmp; |
46 | int i, count, ok; | 46 | int i; |
47 | 47 | ||
48 | if (!cpu_has(c, X86_FEATURE_RDRAND)) | 48 | if (!cpu_has(c, X86_FEATURE_RDRAND)) |
49 | return; /* Nothing to do */ | 49 | return; |
50 | 50 | ||
51 | for (count = i = 0; i < RESEED_LOOP; i++) { | 51 | for (i = 0; i < SANITY_CHECK_LOOPS; i++) { |
52 | ok = rdrand_long(&tmp); | 52 | if (!rdrand_long(&tmp)) { |
53 | if (ok) | 53 | clear_cpu_cap(c, X86_FEATURE_RDRAND); |
54 | count++; | 54 | printk_once(KERN_WARNING "rdrand: disabled\n"); |
55 | return; | ||
56 | } | ||
55 | } | 57 | } |
56 | |||
57 | if (count != RESEED_LOOP) | ||
58 | clear_cpu_cap(c, X86_FEATURE_RDRAND); | ||
59 | #endif | 58 | #endif |
60 | } | 59 | } |