aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/cpu/rdrand.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2011-07-31 17:02:19 -0400
committerH. Peter Anvin <hpa@zytor.com>2011-07-31 17:02:19 -0400
commit49d859d78c5aeb998b6936fcb5f288f78d713489 (patch)
tree04b7746d1b79ab12bf94ff1eaf9ab91e74db37ef /arch/x86/kernel/cpu/rdrand.c
parent628c6246d47b85f5357298601df2444d7f4dd3fd (diff)
x86, random: Verify RDRAND functionality and allow it to be disabled
If the CPU declares that RDRAND is available, go through a guranteed reseed sequence, and make sure that it is actually working (producing data.) If it does not, disable the CPU feature flag. Allow RDRAND to be disabled on the command line (as opposed to at compile time) for a user who has special requirements with regards to random numbers. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> Cc: Matt Mackall <mpm@selenic.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'arch/x86/kernel/cpu/rdrand.c')
-rw-r--r--arch/x86/kernel/cpu/rdrand.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c
new file mode 100644
index 000000000000..feca286c2bb4
--- /dev/null
+++ b/arch/x86/kernel/cpu/rdrand.c
@@ -0,0 +1,73 @@
1/*
2 * This file is part of the Linux kernel.
3 *
4 * Copyright (c) 2011, Intel Corporation
5 * Authors: Fenghua Yu <fenghua.yu@intel.com>,
6 * H. Peter Anvin <hpa@linux.intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <asm/processor.h>
24#include <asm/archrandom.h>
25#include <asm/sections.h>
26
27static int __init x86_rdrand_setup(char *s)
28{
29 setup_clear_cpu_cap(X86_FEATURE_RDRAND);
30 return 1;
31}
32__setup("nordrand", x86_rdrand_setup);
33
34/* We can't use arch_get_random_long() here since alternatives haven't run */
35static inline int rdrand_long(unsigned long *v)
36{
37 int ok;
38 asm volatile("1: " RDRAND_LONG "\n\t"
39 "jc 2f\n\t"
40 "decl %0\n\t"
41 "jnz 1b\n\t"
42 "2:"
43 : "=r" (ok), "=a" (*v)
44 : "0" (RDRAND_RETRY_LOOPS));
45 return ok;
46}
47
48/*
49 * Force a reseed cycle; we are architecturally guaranteed a reseed
50 * after no more than 512 128-bit chunks of random data. This also
51 * acts as a test of the CPU capability.
52 */
53#define RESEED_LOOP ((512*128)/sizeof(unsigned long))
54
55void __cpuinit x86_init_rdrand(struct cpuinfo_x86 *c)
56{
57#ifdef CONFIG_ARCH_RANDOM
58 unsigned long tmp;
59 int i, count, ok;
60
61 if (!cpu_has(c, X86_FEATURE_RDRAND))
62 return; /* Nothing to do */
63
64 for (count = i = 0; i < RESEED_LOOP; i++) {
65 ok = rdrand_long(&tmp);
66 if (ok)
67 count++;
68 }
69
70 if (count != RESEED_LOOP)
71 clear_cpu_cap(c, X86_FEATURE_RDRAND);
72#endif
73}