linux/arch/x86/include/asm/archrandom.h
<<
>>
Prefs
   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
  30static inline bool rdrand_long(unsigned long *v)
  31{
  32        bool ok;
  33        unsigned int retry = RDRAND_RETRY_LOOPS;
  34        do {
  35                asm volatile(RDRAND_LONG
  36                             CC_SET(c)
  37                             : CC_OUT(c) (ok), "=a" (*v));
  38                if (ok)
  39                        return true;
  40        } while (--retry);
  41        return false;
  42}
  43
  44static inline bool rdrand_int(unsigned int *v)
  45{
  46        bool ok;
  47        unsigned int retry = RDRAND_RETRY_LOOPS;
  48        do {
  49                asm volatile(RDRAND_INT
  50                             CC_SET(c)
  51                             : CC_OUT(c) (ok), "=a" (*v));
  52                if (ok)
  53                        return true;
  54        } while (--retry);
  55        return false;
  56}
  57
  58static inline bool rdseed_long(unsigned long *v)
  59{
  60        bool ok;
  61        asm volatile(RDSEED_LONG
  62                     CC_SET(c)
  63                     : CC_OUT(c) (ok), "=a" (*v));
  64        return ok;
  65}
  66
  67static inline bool rdseed_int(unsigned int *v)
  68{
  69        bool ok;
  70        asm volatile(RDSEED_INT
  71                     CC_SET(c)
  72                     : CC_OUT(c) (ok), "=a" (*v));
  73        return ok;
  74}
  75
  76/* Conditional execution based on CPU type */
  77#define arch_has_random()       static_cpu_has(X86_FEATURE_RDRAND)
  78#define arch_has_random_seed()  static_cpu_has(X86_FEATURE_RDSEED)
  79
  80/*
  81 * These are the generic interfaces; they must not be declared if the
  82 * stubs in <linux/random.h> are to be invoked,
  83 * i.e. CONFIG_ARCH_RANDOM is not defined.
  84 */
  85#ifdef CONFIG_ARCH_RANDOM
  86
  87static inline bool arch_get_random_long(unsigned long *v)
  88{
  89        return arch_has_random() ? rdrand_long(v) : false;
  90}
  91
  92static inline bool arch_get_random_int(unsigned int *v)
  93{
  94        return arch_has_random() ? rdrand_int(v) : false;
  95}
  96
  97static inline bool arch_get_random_seed_long(unsigned long *v)
  98{
  99        return arch_has_random_seed() ? rdseed_long(v) : false;
 100}
 101
 102static inline bool arch_get_random_seed_int(unsigned int *v)
 103{
 104        return arch_has_random_seed() ? rdseed_int(v) : false;
 105}
 106
 107extern void x86_init_rdrand(struct cpuinfo_x86 *c);
 108
 109#else  /* !CONFIG_ARCH_RANDOM */
 110
 111static inline void x86_init_rdrand(struct cpuinfo_x86 *c) { }
 112
 113#endif  /* !CONFIG_ARCH_RANDOM */
 114
 115#endif /* ASM_X86_ARCHRANDOM_H */
 116