1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * This file is part of the Linux kernel. 4 * 5 * Copyright (c) 2011, Intel Corporation 6 * Authors: Fenghua Yu <fenghua.yu@intel.com>, 7 * H. Peter Anvin <hpa@linux.intel.com> 8 */ 9 #include <linux/printk.h> 10 11 #include <asm/processor.h> 12 #include <asm/archrandom.h> 13 #include <asm/sections.h> 14 15 /* 16 * RDRAND has Built-In-Self-Test (BIST) that runs on every invocation. 17 * Run the instruction a few times as a sanity check. Also make sure 18 * it's not outputting the same value over and over, which has happened 19 * as a result of past CPU bugs. 20 * 21 * If it fails, it is simple to disable RDRAND and RDSEED here. 22 */ 23 24 void x86_init_rdrand(struct cpuinfo_x86 *c) 25 { 26 enum { SAMPLES = 8, MIN_CHANGE = 5 }; 27 unsigned long sample, prev; 28 bool failure = false; 29 size_t i, changed; 30 31 if (!cpu_has(c, X86_FEATURE_RDRAND)) 32 return; 33 34 for (changed = 0, i = 0; i < SAMPLES; ++i) { 35 if (!rdrand_long(&sample)) { 36 failure = true; 37 break; 38 } 39 changed += i && sample != prev; 40 prev = sample; 41 } 42 if (changed < MIN_CHANGE) 43 failure = true; 44 45 if (failure) { 46 clear_cpu_cap(c, X86_FEATURE_RDRAND); 47 clear_cpu_cap(c, X86_FEATURE_RDSEED); 48 pr_emerg("RDRAND is not reliable on this platform; disabling.\n"); 49 } 50 } 51