diff options
-rw-r--r-- | arch/powerpc/include/asm/archrandom.h | 9 | ||||
-rw-r--r-- | arch/x86/include/asm/archrandom.h | 39 | ||||
-rw-r--r-- | include/linux/random.h | 8 |
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 | ||
28 | int powernv_get_random_long(unsigned long *v); | 28 | int powernv_get_random_long(unsigned long *v); |
29 | 29 | ||
30 | static inline int arch_get_random_seed_long(unsigned long *v) | ||
31 | { | ||
32 | return 0; | ||
33 | } | ||
34 | static 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 */ | ||
60 | static 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) \ |
57 | static inline int name(type *v) \ | 70 | static 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) \ | ||
87 | static 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 | ||
75 | GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5); | 101 | GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5); |
76 | GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4); | 102 | GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4); |
77 | 103 | ||
104 | GET_SEED(arch_get_random_seed_long, unsigned long, RDSEED_LONG, ASM_NOP5); | ||
105 | GET_SEED(arch_get_random_seed_int, unsigned int, RDSEED_INT, ASM_NOP4); | ||
106 | |||
78 | #else | 107 | #else |
79 | 108 | ||
80 | GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3); | 109 | GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3); |
81 | GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3); | 110 | GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3); |
82 | 111 | ||
112 | GET_SEED(arch_get_random_seed_long, unsigned long, RDSEED_LONG, ASM_NOP4); | ||
113 | GET_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 | ||
124 | static 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 | ||
94 | extern void x86_init_rdrand(struct cpuinfo_x86 *c); | 131 | extern 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 | } |
91 | static inline int arch_get_random_seed_long(unsigned long *v) | ||
92 | { | ||
93 | return 0; | ||
94 | } | ||
95 | static 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. */ |