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/* Unconditional execution of RDRAND and RDSEED */
19
20static inline bool __must_check rdrand_long(unsigned long *v)
21{
22	bool ok;
23	unsigned int retry = RDRAND_RETRY_LOOPS;
24	do {
25		asm volatile("rdrand %[out]"
26			     CC_SET(c)
27			     : CC_OUT(c) (ok), [out] "=r" (*v));
28		if (ok)
29			return true;
30	} while (--retry);
31	return false;
32}
33
34static inline bool __must_check rdrand_int(unsigned int *v)
35{
36	bool ok;
37	unsigned int retry = RDRAND_RETRY_LOOPS;
38	do {
39		asm volatile("rdrand %[out]"
40			     CC_SET(c)
41			     : CC_OUT(c) (ok), [out] "=r" (*v));
42		if (ok)
43			return true;
44	} while (--retry);
45	return false;
46}
47
48static inline bool __must_check rdseed_long(unsigned long *v)
49{
50	bool ok;
51	asm volatile("rdseed %[out]"
52		     CC_SET(c)
53		     : CC_OUT(c) (ok), [out] "=r" (*v));
54	return ok;
55}
56
57static inline bool __must_check rdseed_int(unsigned int *v)
58{
59	bool ok;
60	asm volatile("rdseed %[out]"
61		     CC_SET(c)
62		     : CC_OUT(c) (ok), [out] "=r" (*v));
63	return ok;
64}
65
66/*
67 * These are the generic interfaces; they must not be declared if the
68 * stubs in <linux/random.h> are to be invoked,
69 * i.e. CONFIG_ARCH_RANDOM is not defined.
70 */
71#ifdef CONFIG_ARCH_RANDOM
72
73static inline bool __must_check arch_get_random_long(unsigned long *v)
74{
75	return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_long(v) : false;
76}
77
78static inline bool __must_check arch_get_random_int(unsigned int *v)
79{
80	return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_int(v) : false;
81}
82
83static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
84{
85	return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_long(v) : false;
86}
87
88static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
89{
90	return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_int(v) : false;
91}
92
93extern void x86_init_rdrand(struct cpuinfo_x86 *c);
94
95#else  /* !CONFIG_ARCH_RANDOM */
96
97static inline void x86_init_rdrand(struct cpuinfo_x86 *c) { }
98
99#endif  /* !CONFIG_ARCH_RANDOM */
100
101#endif /* ASM_X86_ARCHRANDOM_H */
102