blob: ebc248e495493a62b35a34d90583c56c82dac35c [file] [log] [blame]
David Brazdil0f672f62019-12-10 10:32:29 +00001/* SPDX-License-Identifier: GPL-2.0-only */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002/*
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>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00008 */
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
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000018/* Unconditional execution of RDRAND and RDSEED */
19
Olivier Deprez157378f2022-04-04 15:47:50 +020020static inline bool __must_check rdrand_long(unsigned long *v)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000021{
22 bool ok;
23 unsigned int retry = RDRAND_RETRY_LOOPS;
24 do {
Olivier Deprez157378f2022-04-04 15:47:50 +020025 asm volatile("rdrand %[out]"
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000026 CC_SET(c)
Olivier Deprez157378f2022-04-04 15:47:50 +020027 : CC_OUT(c) (ok), [out] "=r" (*v));
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000028 if (ok)
29 return true;
30 } while (--retry);
31 return false;
32}
33
Olivier Deprez157378f2022-04-04 15:47:50 +020034static inline bool __must_check rdrand_int(unsigned int *v)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000035{
36 bool ok;
37 unsigned int retry = RDRAND_RETRY_LOOPS;
38 do {
Olivier Deprez157378f2022-04-04 15:47:50 +020039 asm volatile("rdrand %[out]"
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000040 CC_SET(c)
Olivier Deprez157378f2022-04-04 15:47:50 +020041 : CC_OUT(c) (ok), [out] "=r" (*v));
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000042 if (ok)
43 return true;
44 } while (--retry);
45 return false;
46}
47
Olivier Deprez157378f2022-04-04 15:47:50 +020048static inline bool __must_check rdseed_long(unsigned long *v)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000049{
50 bool ok;
Olivier Deprez157378f2022-04-04 15:47:50 +020051 asm volatile("rdseed %[out]"
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000052 CC_SET(c)
Olivier Deprez157378f2022-04-04 15:47:50 +020053 : CC_OUT(c) (ok), [out] "=r" (*v));
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000054 return ok;
55}
56
Olivier Deprez157378f2022-04-04 15:47:50 +020057static inline bool __must_check rdseed_int(unsigned int *v)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000058{
59 bool ok;
Olivier Deprez157378f2022-04-04 15:47:50 +020060 asm volatile("rdseed %[out]"
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000061 CC_SET(c)
Olivier Deprez157378f2022-04-04 15:47:50 +020062 : CC_OUT(c) (ok), [out] "=r" (*v));
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000063 return ok;
64}
65
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000066/*
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
Olivier Deprez157378f2022-04-04 15:47:50 +020073static inline bool __must_check arch_get_random_long(unsigned long *v)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000074{
Olivier Deprez157378f2022-04-04 15:47:50 +020075 return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_long(v) : false;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000076}
77
Olivier Deprez157378f2022-04-04 15:47:50 +020078static inline bool __must_check arch_get_random_int(unsigned int *v)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000079{
Olivier Deprez157378f2022-04-04 15:47:50 +020080 return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_int(v) : false;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000081}
82
Olivier Deprez157378f2022-04-04 15:47:50 +020083static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000084{
Olivier Deprez157378f2022-04-04 15:47:50 +020085 return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_long(v) : false;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000086}
87
Olivier Deprez157378f2022-04-04 15:47:50 +020088static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000089{
Olivier Deprez157378f2022-04-04 15:47:50 +020090 return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_int(v) : false;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000091}
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 */