linux/arch/x86/include/asm/archrandom.h
<<
>>
Prefs
   1/*
   2 * This file is part of the Linux kernel.
   3 *
   4 * Copyright (c) 2011-2014, Intel Corporation
   5 * Authors: Fenghua Yu <fenghua.yu@intel.com>,
   6 *          H. Peter Anvin <hpa@linux.intel.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify it
   9 * under the terms and conditions of the GNU General Public License,
  10 * version 2, as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope it will be useful, but WITHOUT
  13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  15 * more details.
  16 *
  17 * You should have received a copy of the GNU General Public License along with
  18 * this program; if not, write to the Free Software Foundation, Inc.,
  19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  20 *
  21 */
  22
  23#ifndef ASM_X86_ARCHRANDOM_H
  24#define ASM_X86_ARCHRANDOM_H
  25
  26#include <asm/processor.h>
  27#include <asm/cpufeature.h>
  28
  29#define RDRAND_RETRY_LOOPS      10
  30
  31#define RDRAND_INT      ".byte 0x0f,0xc7,0xf0"
  32#define RDSEED_INT      ".byte 0x0f,0xc7,0xf8"
  33#ifdef CONFIG_X86_64
  34# define RDRAND_LONG    ".byte 0x48,0x0f,0xc7,0xf0"
  35# define RDSEED_LONG    ".byte 0x48,0x0f,0xc7,0xf8"
  36#else
  37# define RDRAND_LONG    RDRAND_INT
  38# define RDSEED_LONG    RDSEED_INT
  39#endif
  40
  41/* Unconditional execution of RDRAND and RDSEED */
  42
  43static inline bool rdrand_long(unsigned long *v)
  44{
  45        bool ok;
  46        unsigned int retry = RDRAND_RETRY_LOOPS;
  47        do {
  48                asm volatile(RDRAND_LONG "\n\t"
  49                             CC_SET(c)
  50                             : CC_OUT(c) (ok), "=a" (*v));
  51                if (ok)
  52                        return true;
  53        } while (--retry);
  54        return false;
  55}
  56
  57static inline bool rdrand_int(unsigned int *v)
  58{
  59        bool ok;
  60        unsigned int retry = RDRAND_RETRY_LOOPS;
  61        do {
  62                asm volatile(RDRAND_INT "\n\t"
  63                             CC_SET(c)
  64                             : CC_OUT(c) (ok), "=a" (*v));
  65                if (ok)
  66                        return true;
  67        } while (--retry);
  68        return false;
  69}
  70
  71static inline bool rdseed_long(unsigned long *v)
  72{
  73        bool ok;
  74        asm volatile(RDSEED_LONG "\n\t"
  75                     CC_SET(c)
  76                     : CC_OUT(c) (ok), "=a" (*v));
  77        return ok;
  78}
  79
  80static inline bool rdseed_int(unsigned int *v)
  81{
  82        bool ok;
  83        asm volatile(RDSEED_INT "\n\t"
  84                     CC_SET(c)
  85                     : CC_OUT(c) (ok), "=a" (*v));
  86        return ok;
  87}
  88
  89/* Conditional execution based on CPU type */
  90#define arch_has_random()       static_cpu_has(X86_FEATURE_RDRAND)
  91#define arch_has_random_seed()  static_cpu_has(X86_FEATURE_RDSEED)
  92
  93/*
  94 * These are the generic interfaces; they must not be declared if the
  95 * stubs in <linux/random.h> are to be invoked,
  96 * i.e. CONFIG_ARCH_RANDOM is not defined.
  97 */
  98#ifdef CONFIG_ARCH_RANDOM
  99
 100static inline bool arch_get_random_long(unsigned long *v)
 101{
 102        return arch_has_random() ? rdrand_long(v) : false;
 103}
 104
 105static inline bool arch_get_random_int(unsigned int *v)
 106{
 107        return arch_has_random() ? rdrand_int(v) : false;
 108}
 109
 110static inline bool arch_get_random_seed_long(unsigned long *v)
 111{
 112        return arch_has_random_seed() ? rdseed_long(v) : false;
 113}
 114
 115static inline bool arch_get_random_seed_int(unsigned int *v)
 116{
 117        return arch_has_random_seed() ? rdseed_int(v) : false;
 118}
 119
 120extern void x86_init_rdrand(struct cpuinfo_x86 *c);
 121
 122#else  /* !CONFIG_ARCH_RANDOM */
 123
 124static inline void x86_init_rdrand(struct cpuinfo_x86 *c) { }
 125
 126#endif  /* !CONFIG_ARCH_RANDOM */
 127
 128#endif /* ASM_X86_ARCHRANDOM_H */
 129