commit 218603412aad073a04ea815858b98f6c33ab30d2 Author: Linus Torvalds Date: Sat Jul 30 15:06:16 2011 -1000 EXAMPLE 'RDRAND' PATCH NOT FOR REAL CONSUMPTION! --- arch/x86/include/asm/random.h | 23 +++++++++++++++++++++++ drivers/char/random.c | 15 +++++++++++++++ include/asm-generic/random.h | 13 +++++++++++++ 3 files changed, 51 insertions(+), 0 deletions(-) diff --git a/arch/x86/include/asm/random.h b/arch/x86/include/asm/random.h new file mode 100644 index 000000000000..f6fbd3340608 --- /dev/null +++ b/arch/x86/include/asm/random.h @@ -0,0 +1,23 @@ +#ifndef _X86_RANDOM_H +#define _X86_RANDOM_H + +#include + +static inline int arch_get_random_word(unsigned long *word) +{ + int ret; + + alternative_io("xor %0,%0; xor %1,%1" ASM_NOP4, + "rdrand %1; setcc %0", + X86_FEATURE_PERFCTR_CORE, + ASM_OUTPUT2("=a" (ret), "=d" (*word)), + "i" (0) /* fake input */); + /* + * We return 0 if CF is clear of if the CPU + * doesn't support RDRAND, otherwise we return + * 8 (for 8 bytes of data). + */ + return ret & 8; +} + +#endif diff --git a/drivers/char/random.c b/drivers/char/random.c index 729281961f22..e335ec96bf88 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -257,6 +257,7 @@ #include #include #include +#include /* * Configuration information @@ -865,6 +866,20 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, xfer_secondary_pool(r, nbytes); nbytes = account(r, nbytes, min, reserved); + /* Use fast CPU random words if available */ + while (nbytes) { + unsigned long word; + int bytes = arch_get_random_word(&word); + if (!bytes) + break; + if (bytes > nbytes) + bytes = nbytes; + memcpy(buf, &word, bytes); + nbytes -= bytes; + buf += bytes; + ret += bytes; + } + while (nbytes) { extract_buf(r, tmp); diff --git a/include/asm-generic/random.h b/include/asm-generic/random.h new file mode 100644 index 000000000000..e9be12ba86fa --- /dev/null +++ b/include/asm-generic/random.h @@ -0,0 +1,13 @@ +#ifndef _ASM_RANDOM_H +#define _ASM_RANDOM_H + +/* + * Architecture random data in low bytes of "word", return how + * many bytes were filled in. Default implementation: none. + */ +static inline int arch_get_random_word(unsigned long *word) +{ + return 0; +} + +#endif