xref: /OK3568_Linux_fs/kernel/arch/x86/include/asm/archrandom.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * This file is part of the Linux kernel.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2011-2014, Intel Corporation
6*4882a593Smuzhiyun  * Authors: Fenghua Yu <fenghua.yu@intel.com>,
7*4882a593Smuzhiyun  *          H. Peter Anvin <hpa@linux.intel.com>
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #ifndef ASM_X86_ARCHRANDOM_H
11*4882a593Smuzhiyun #define ASM_X86_ARCHRANDOM_H
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <asm/processor.h>
14*4882a593Smuzhiyun #include <asm/cpufeature.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define RDRAND_RETRY_LOOPS	10
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun /* Unconditional execution of RDRAND and RDSEED */
19*4882a593Smuzhiyun 
rdrand_long(unsigned long * v)20*4882a593Smuzhiyun static inline bool __must_check rdrand_long(unsigned long *v)
21*4882a593Smuzhiyun {
22*4882a593Smuzhiyun 	bool ok;
23*4882a593Smuzhiyun 	unsigned int retry = RDRAND_RETRY_LOOPS;
24*4882a593Smuzhiyun 	do {
25*4882a593Smuzhiyun 		asm volatile("rdrand %[out]"
26*4882a593Smuzhiyun 			     CC_SET(c)
27*4882a593Smuzhiyun 			     : CC_OUT(c) (ok), [out] "=r" (*v));
28*4882a593Smuzhiyun 		if (ok)
29*4882a593Smuzhiyun 			return true;
30*4882a593Smuzhiyun 	} while (--retry);
31*4882a593Smuzhiyun 	return false;
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun 
rdrand_int(unsigned int * v)34*4882a593Smuzhiyun static inline bool __must_check rdrand_int(unsigned int *v)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	bool ok;
37*4882a593Smuzhiyun 	unsigned int retry = RDRAND_RETRY_LOOPS;
38*4882a593Smuzhiyun 	do {
39*4882a593Smuzhiyun 		asm volatile("rdrand %[out]"
40*4882a593Smuzhiyun 			     CC_SET(c)
41*4882a593Smuzhiyun 			     : CC_OUT(c) (ok), [out] "=r" (*v));
42*4882a593Smuzhiyun 		if (ok)
43*4882a593Smuzhiyun 			return true;
44*4882a593Smuzhiyun 	} while (--retry);
45*4882a593Smuzhiyun 	return false;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
rdseed_long(unsigned long * v)48*4882a593Smuzhiyun static inline bool __must_check rdseed_long(unsigned long *v)
49*4882a593Smuzhiyun {
50*4882a593Smuzhiyun 	bool ok;
51*4882a593Smuzhiyun 	asm volatile("rdseed %[out]"
52*4882a593Smuzhiyun 		     CC_SET(c)
53*4882a593Smuzhiyun 		     : CC_OUT(c) (ok), [out] "=r" (*v));
54*4882a593Smuzhiyun 	return ok;
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun 
rdseed_int(unsigned int * v)57*4882a593Smuzhiyun static inline bool __must_check rdseed_int(unsigned int *v)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun 	bool ok;
60*4882a593Smuzhiyun 	asm volatile("rdseed %[out]"
61*4882a593Smuzhiyun 		     CC_SET(c)
62*4882a593Smuzhiyun 		     : CC_OUT(c) (ok), [out] "=r" (*v));
63*4882a593Smuzhiyun 	return ok;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /*
67*4882a593Smuzhiyun  * These are the generic interfaces; they must not be declared if the
68*4882a593Smuzhiyun  * stubs in <linux/random.h> are to be invoked,
69*4882a593Smuzhiyun  * i.e. CONFIG_ARCH_RANDOM is not defined.
70*4882a593Smuzhiyun  */
71*4882a593Smuzhiyun #ifdef CONFIG_ARCH_RANDOM
72*4882a593Smuzhiyun 
arch_get_random_long(unsigned long * v)73*4882a593Smuzhiyun static inline bool __must_check arch_get_random_long(unsigned long *v)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_long(v) : false;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
arch_get_random_int(unsigned int * v)78*4882a593Smuzhiyun static inline bool __must_check arch_get_random_int(unsigned int *v)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_int(v) : false;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
arch_get_random_seed_long(unsigned long * v)83*4882a593Smuzhiyun static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_long(v) : false;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
arch_get_random_seed_int(unsigned int * v)88*4882a593Smuzhiyun static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_int(v) : false;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun extern void x86_init_rdrand(struct cpuinfo_x86 *c);
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun #else  /* !CONFIG_ARCH_RANDOM */
96*4882a593Smuzhiyun 
x86_init_rdrand(struct cpuinfo_x86 * c)97*4882a593Smuzhiyun static inline void x86_init_rdrand(struct cpuinfo_x86 *c) { }
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun #endif  /* !CONFIG_ARCH_RANDOM */
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun #endif /* ASM_X86_ARCHRANDOM_H */
102