Messages in this thread Patch in this message | | | From | Linus Torvalds <> | Date | Sat, 30 Jul 2011 15:13:27 -1000 | Subject | Re: [PATCH 1/2] random: Add support for architectural random hooks |
| |
So here is my counter-suggestion
NOTE NOTE NOTE! This is completely and utterly untested. I didn't actually check how big the "rdrand" and "setc" instructions are, so the ASM_NOP4 there is just a random "I guess two 'xor' instructions are four bytes shorter than the rdrand/setc instructions are".
So please don't take this as a serious patch that should be applied, but instead take it as a serious alternative *approach*.
Note that with the default inline function in <asm-generic/random.h> is designed so that architectures that use it (this patch does *not* contain the architecture glue to enable it) will compile the loop in random.c entirely away. No test, no nothing.
Comments?
(Btw, even on x86, assuming the concept works and the ASM_NOP4 is corrected to the right length, we'd need to support older assemblers that don't understand the "rdrand" instruction, so it would need to be done as a explicit byte sequence).
Again, TOTALLY UNTESTED. Concept patch only!! There may be seriously stupid bugs here, but the point is that it should make it easy for an architecture to have a "get a word of random data quickly".
Linus commit 218603412aad073a04ea815858b98f6c33ab30d2 Author: Linus Torvalds <torvalds@linux-foundation.org> 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 <asm/alternative.h> + +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 <asm/uaccess.h> #include <asm/irq.h> #include <asm/io.h> +#include <asm/random.h> /* * 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 | |