aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/archrandom.h9
-rw-r--r--arch/x86/include/asm/archrandom.h39
-rw-r--r--include/linux/random.h8
3 files changed, 55 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/archrandom.h b/arch/powerpc/include/asm/archrandom.h
index d853d163ba47..801beba4e64b 100644
--- a/arch/powerpc/include/asm/archrandom.h
+++ b/arch/powerpc/include/asm/archrandom.h
@@ -27,6 +27,15 @@ static inline int arch_get_random_int(unsigned int *v)
27 27
28int powernv_get_random_long(unsigned long *v); 28int powernv_get_random_long(unsigned long *v);
29 29
30static inline int arch_get_random_seed_long(unsigned long *v)
31{
32 return 0;
33}
34static inline int arch_get_random_seed_int(unsigned int *v)
35{
36 return 0;
37}
38
30#endif /* CONFIG_ARCH_RANDOM */ 39#endif /* CONFIG_ARCH_RANDOM */
31 40
32#endif /* _ASM_POWERPC_ARCHRANDOM_H */ 41#endif /* _ASM_POWERPC_ARCHRANDOM_H */
diff --git a/arch/x86/include/asm/archrandom.h b/arch/x86/include/asm/archrandom.h
index e6a92455740e..6ad7f6d3f97f 100644
--- a/arch/x86/include/asm/archrandom.h
+++ b/arch/x86/include/asm/archrandom.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file is part of the Linux kernel. 2 * This file is part of the Linux kernel.
3 * 3 *
4 * Copyright (c) 2011, Intel Corporation 4 * Copyright (c) 2011-2014, Intel Corporation
5 * Authors: Fenghua Yu <fenghua.yu@intel.com>, 5 * Authors: Fenghua Yu <fenghua.yu@intel.com>,
6 * H. Peter Anvin <hpa@linux.intel.com> 6 * H. Peter Anvin <hpa@linux.intel.com>
7 * 7 *
@@ -31,10 +31,13 @@
31#define RDRAND_RETRY_LOOPS 10 31#define RDRAND_RETRY_LOOPS 10
32 32
33#define RDRAND_INT ".byte 0x0f,0xc7,0xf0" 33#define RDRAND_INT ".byte 0x0f,0xc7,0xf0"
34#define RDSEED_INT ".byte 0x0f,0xc7,0xf8"
34#ifdef CONFIG_X86_64 35#ifdef CONFIG_X86_64
35# define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0" 36# define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0"
37# define RDSEED_LONG ".byte 0x48,0x0f,0xc7,0xf8"
36#else 38#else
37# define RDRAND_LONG RDRAND_INT 39# define RDRAND_LONG RDRAND_INT
40# define RDSEED_LONG RDSEED_INT
38#endif 41#endif
39 42
40#ifdef CONFIG_ARCH_RANDOM 43#ifdef CONFIG_ARCH_RANDOM
@@ -53,6 +56,16 @@ static inline int rdrand_long(unsigned long *v)
53 return ok; 56 return ok;
54} 57}
55 58
59/* A single attempt at RDSEED */
60static inline bool rdseed_long(unsigned long *v)
61{
62 unsigned char ok;
63 asm volatile(RDSEED_LONG "\n\t"
64 "setc %0"
65 : "=qm" (ok), "=a" (*v));
66 return ok;
67}
68
56#define GET_RANDOM(name, type, rdrand, nop) \ 69#define GET_RANDOM(name, type, rdrand, nop) \
57static inline int name(type *v) \ 70static inline int name(type *v) \
58{ \ 71{ \
@@ -70,16 +83,35 @@ static inline int name(type *v) \
70 return ok; \ 83 return ok; \
71} 84}
72 85
86#define GET_SEED(name, type, rdseed, nop) \
87static inline int name(type *v) \
88{ \
89 unsigned char ok; \
90 alternative_io("movb $0, %0\n\t" \
91 nop, \
92 rdseed "\n\t" \
93 "setc %0", \
94 X86_FEATURE_RDSEED, \
95 ASM_OUTPUT2("=q" (ok), "=a" (*v))); \
96 return ok; \
97}
98
73#ifdef CONFIG_X86_64 99#ifdef CONFIG_X86_64
74 100
75GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5); 101GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5);
76GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4); 102GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4);
77 103
104GET_SEED(arch_get_random_seed_long, unsigned long, RDSEED_LONG, ASM_NOP5);
105GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4);
106
78#else 107#else
79 108
80GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3); 109GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3);
81GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3); 110GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3);
82 111
112GET_SEED(arch_get_random_seed_long, unsigned long, RDSEED_LONG, ASM_NOP4);
113GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4);
114
83#endif /* CONFIG_X86_64 */ 115#endif /* CONFIG_X86_64 */
84 116
85#else 117#else
@@ -89,6 +121,11 @@ static inline int rdrand_long(unsigned long *v)
89 return 0; 121 return 0;
90} 122}
91 123
124static inline bool rdseed_long(unsigned long *v)
125{
126 return 0;
127}
128
92#endif /* CONFIG_ARCH_RANDOM */ 129#endif /* CONFIG_ARCH_RANDOM */
93 130
94extern void x86_init_rdrand(struct cpuinfo_x86 *c); 131extern void x86_init_rdrand(struct cpuinfo_x86 *c);
diff --git a/include/linux/random.h b/include/linux/random.h
index 1cfce0e24dbd..c2f08131050d 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -88,6 +88,14 @@ static inline int arch_get_random_int(unsigned int *v)
88{ 88{
89 return 0; 89 return 0;
90} 90}
91static inline int arch_get_random_seed_long(unsigned long *v)
92{
93 return 0;
94}
95static inline int arch_get_random_seed_int(unsigned int *v)
96{
97 return 0;
98}
91#endif 99#endif
92 100
93/* Pseudo random number generator from numerical recipes. */ 101/* Pseudo random number generator from numerical recipes. */