mirror of https://gitee.com/openkylin/linux.git
x86: Replace RDRAND forced-reseed with simple sanity check
x86_init_rdrand() was added with 2 goals: 1. Sanity check that the built-in-self-test circuit on the Digital Random Number Generator (DRNG) is not complaining. As RDRAND HW self-checks on every invocation, this goal is achieved by simply invoking RDRAND and checking its return code. 2. Force a full re-seed of the random number generator. This was done out of paranoia to benefit the most un-sophisticated DRNG implementation conceivable in the architecture, an implementation that does not exist, and unlikely ever will. This worst-case full-re-seed is achieved by invoking a 64-bit RDRAND 8192 times. Unfortunately, this worst-case re-seed costs O(1,000us). Magnifying this cost, it is done from identify_cpu(), which is the synchronous critical path to bring a processor on-line -- repeated for every logical processor in the system at boot and resume from S3. As it is very expensive, and of highly dubious value, we delete the worst-case re-seed from the kernel. We keep the 1st goal -- sanity check the hardware, and mark it absent if it complains. This change reduces the cost of x86_init_rdrand() by a factor of 1,000x, to O(1us) from O(1,000us). Signed-off-by: Len Brown <len.brown@intel.com> Link: http://lkml.kernel.org/r/058618cc56ec6611171427ad7205e37e377aa8d4.1439738240.git.len.brown@intel.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
679bcea857
commit
0007bccc3c
|
@ -33,28 +33,27 @@ static int __init x86_rdrand_setup(char *s)
|
||||||
__setup("nordrand", x86_rdrand_setup);
|
__setup("nordrand", x86_rdrand_setup);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force a reseed cycle; we are architecturally guaranteed a reseed
|
* RDRAND has Built-In-Self-Test (BIST) that runs on every invocation.
|
||||||
* after no more than 512 128-bit chunks of random data. This also
|
* Run the instruction a few times as a sanity check.
|
||||||
* acts as a test of the CPU capability.
|
* If it fails, it is simple to disable RDRAND here.
|
||||||
*/
|
*/
|
||||||
#define RESEED_LOOP ((512*128)/sizeof(unsigned long))
|
#define SANITY_CHECK_LOOPS 8
|
||||||
|
|
||||||
void x86_init_rdrand(struct cpuinfo_x86 *c)
|
void x86_init_rdrand(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_ARCH_RANDOM
|
#ifdef CONFIG_ARCH_RANDOM
|
||||||
unsigned long tmp;
|
unsigned long tmp;
|
||||||
int i, count, ok;
|
int i;
|
||||||
|
|
||||||
if (!cpu_has(c, X86_FEATURE_RDRAND))
|
if (!cpu_has(c, X86_FEATURE_RDRAND))
|
||||||
return; /* Nothing to do */
|
return;
|
||||||
|
|
||||||
for (count = i = 0; i < RESEED_LOOP; i++) {
|
for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
|
||||||
ok = rdrand_long(&tmp);
|
if (!rdrand_long(&tmp)) {
|
||||||
if (ok)
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count != RESEED_LOOP)
|
|
||||||
clear_cpu_cap(c, X86_FEATURE_RDRAND);
|
clear_cpu_cap(c, X86_FEATURE_RDRAND);
|
||||||
|
printk_once(KERN_WARNING "rdrand: disabled\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue