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