From 16dc07107d2abddccf7e42f684c16c3d8657b324 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 29 May 2015 10:44:19 -0600 Subject: [PATCH] Add Intel rdrand support Not wired up. Signed-off-by: Jens Axboe --- arch/arch-x86-common.h | 33 +++++++++++++++++++-------------- arch/arch-x86_64.h | 30 ++++++++++++++++++++++++++++++ lib/rand.c | 2 ++ lib/rand.h | 2 ++ 4 files changed, 53 insertions(+), 14 deletions(-) diff --git a/arch/arch-x86-common.h b/arch/arch-x86-common.h index 31aa79f1..cbf66b8d 100644 --- a/arch/arch-x86-common.h +++ b/arch/arch-x86-common.h @@ -15,8 +15,9 @@ static inline void cpuid(unsigned int op, #define ARCH_HAVE_INIT extern int tsc_reliable; +extern int arch_random; -static inline int arch_init_intel(unsigned int level) +static inline void arch_init_intel(unsigned int level) { unsigned int eax, ebx, ecx = 0, edx; @@ -26,47 +27,51 @@ static inline int arch_init_intel(unsigned int level) eax = 1; do_cpuid(&eax, &ebx, &ecx, &edx); if (!(edx & (1U << 4))) - return 0; + return; /* * Check for constant rate and synced (across cores) TSC */ eax = 0x80000007; do_cpuid(&eax, &ebx, &ecx, &edx); - return edx & (1U << 8); + tsc_reliable = (edx & (1U << 8)) != 0; + + /* + * Check for FDRAND + */ + eax = 0x1; + do_cpuid(&eax, &ebx, &ecx, &edx); + arch_random = (ecx & (1U << 30)) != 0; } -static inline int arch_init_amd(unsigned int level) +static inline void arch_init_amd(unsigned int level) { unsigned int eax, ebx, ecx, edx; cpuid(0x80000000, &eax, &ebx, &ecx, &edx); if (eax < 0x80000007) - return 0; + return; cpuid(0x80000007, &eax, &ebx, &ecx, &edx); - if (edx & (1 << 8)) - return 1; - - return 0; + tsc_reliable = (edx & (1U << 8)) != 0; } -static inline int arch_init(char *envp[]) +static inline void arch_init(char *envp[]) { unsigned int level; char str[13]; + arch_random = tsc_reliable = 0; + cpuid(0, &level, (unsigned int *) &str[0], (unsigned int *) &str[8], (unsigned int *) &str[4]); str[12] = '\0'; if (!strcmp(str, "GenuineIntel")) - tsc_reliable = arch_init_intel(level); + arch_init_intel(level); else if (!strcmp(str, "AuthenticAMD")) - tsc_reliable = arch_init_amd(level); - - return 0; + arch_init_amd(level); } #endif diff --git a/arch/arch-x86_64.h b/arch/arch-x86_64.h index 61ac75ee..8f33fc54 100644 --- a/arch/arch-x86_64.h +++ b/arch/arch-x86_64.h @@ -60,4 +60,34 @@ static inline unsigned long long get_cpu_clock(void) #define ARCH_HAVE_SSE4_2 #define ARCH_HAVE_CPU_CLOCK +#define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0" +#define RDSEED_LONG ".byte 0x48,0x0f,0xc7,0xf8" +#define RDRAND_RETRY 100 + +static inline int arch_rand_long(unsigned long *val) +{ + int ok; + + asm volatile("1: " RDRAND_LONG "\n\t" + "jc 2f\n\t" + "decl %0\n\t" + "jnz 1b\n\t" + "2:" + : "=r" (ok), "=a" (*val) + : "0" (RDRAND_RETRY)); + + return ok; +} + +static inline int arch_rand_seed(unsigned long *seed) +{ + unsigned char ok; + + asm volatile(RDSEED_LONG "\n\t" + "setc %0" + : "=qm" (ok), "=a" (*seed)); + + return 0; +} + #endif diff --git a/lib/rand.c b/lib/rand.c index 185b679e..1d189a27 100644 --- a/lib/rand.c +++ b/lib/rand.c @@ -38,6 +38,8 @@ #include "rand.h" #include "../hash.h" +int arch_random; + static inline int __seed(unsigned int x, unsigned int m) { return (x < m) ? x + m : x; diff --git a/lib/rand.h b/lib/rand.h index 089837db..0a577fd3 100644 --- a/lib/rand.h +++ b/lib/rand.h @@ -1,6 +1,8 @@ #ifndef FIO_RAND_H #define FIO_RAND_H +#include "../arch/arch.h" + #define FRAND_MAX (-1U) struct frand_state { -- 2.25.1