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 10 #include <asm/processor.h> 11 #include <asm/archrandom.h> 12 #include <asm/sections.h> 13 14 static int __init x86_rdrand_setup(char *s) 15 { 16 setup_clear_cpu_cap(X86_FEATURE_RDRAND); 17 setup_clear_cpu_cap(X86_FEATURE_RDSEED); 18 return 1; 19 } 20 __setup("nordrand", x86_rdrand_setup); 21 22 /* 23 * RDRAND has Built-In-Self-Test (BIST) that runs on every invocation. 24 * Run the instruction a few times as a sanity check. 25 * If it fails, it is simple to disable RDRAND here. 26 */ 27 #define SANITY_CHECK_LOOPS 8 28 29 #ifdef CONFIG_ARCH_RANDOM 30 void x86_init_rdrand(struct cpuinfo_x86 *c) 31 { 32 unsigned int changed = 0; 33 unsigned long tmp, prev; 34 int i; 35 36 if (!cpu_has(c, X86_FEATURE_RDRAND)) 37 return; 38 39 for (i = 0; i < SANITY_CHECK_LOOPS; i++) { 40 if (!rdrand_long(&tmp)) { 41 clear_cpu_cap(c, X86_FEATURE_RDRAND); 42 pr_warn_once("rdrand: disabled\n"); 43 return; 44 } 45 } 46 47 /* 48 * Stupid sanity-check whether RDRAND does *actually* generate 49 * some at least random-looking data. 50 */ 51 prev = tmp; 52 for (i = 0; i < SANITY_CHECK_LOOPS; i++) { 53 if (rdrand_long(&tmp)) { 54 if (prev != tmp) 55 changed++; 56 57 prev = tmp; 58 } 59 } 60 61 if (WARN_ON_ONCE(!changed)) 62 pr_emerg( 63 "RDRAND gives funky smelling output, might consider not using it by booting with \"nordrand\""); 64 65 } 66 #endif 67