summaryrefslogtreecommitdiffstats
path: root/sys/dev/random
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-10-17 07:57:58 +0000
committerkib <kib@FreeBSD.org>2013-10-17 07:57:58 +0000
commit8a6197609b0e4765b6e07d6fc04974459371b0a0 (patch)
tree8a19d80069be1524f295a8408ee00fc6db9c775d /sys/dev/random
parent8028e6e368b37c2bcef7362d331eec478886dab4 (diff)
downloadFreeBSD-src-8a6197609b0e4765b6e07d6fc04974459371b0a0.zip
FreeBSD-src-8a6197609b0e4765b6e07d6fc04974459371b0a0.tar.gz
Utilize the stronger guarantees on the call arguments from the
harvester, which now always calls hwrngs with the buffer length multiple of the word size. This allows to remove the excessive memory accesses to temporary buffer when saving the entropy word. Streamline the assembly and unify it between i386 and amd64. Reviewed by: markm, des Approved by: so (des) Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
Diffstat (limited to 'sys/dev/random')
-rw-r--r--sys/dev/random/ivy.c57
1 files changed, 25 insertions, 32 deletions
diff --git a/sys/dev/random/ivy.c b/sys/dev/random/ivy.c
index 7784e8b..9b40016 100644
--- a/sys/dev/random/ivy.c
+++ b/sys/dev/random/ivy.c
@@ -1,8 +1,12 @@
/*-
+ * Copyright (c) 2013 The FreeBSD Foundation
* Copyright (c) 2013 David E. O'Brien <obrien@NUXI.org>
* Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org>
* All rights reserved.
*
+ * Portions of this software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -58,26 +62,25 @@ static struct random_hardware_source random_ivy = {
};
static inline int
-ivy_rng_store(uint64_t *tmp)
+ivy_rng_store(long *buf)
{
#ifdef __GNUCLIKE_ASM
- uint32_t count;
+ long tmp;
+ int retry;
+ retry = RETRY_COUNT;
__asm __volatile(
-#ifdef __amd64__
- "rdrand\t%%rax\n\t"
- "jnc\t1f\n\t"
- "movq\t%%rax,%1\n\t"
- "movl\t$8,%%eax\n"
-#else /* i386 */
- "rdrand\t%%eax\n\t"
- "jnc\t1f\n\t"
- "movl\t%%eax,%1\n\t"
- "movl\t$4,%%eax\n"
-#endif
- "1:\n" /* %eax is cleared by processor on failure */
- : "=a" (count), "=g" (*tmp) : "a" (0) : "cc");
- return (count);
+ "1:\n\t"
+ "rdrand %2\n\t" /* read randomness into tmp */
+ "jb 2f\n\t" /* CF is set on success, exit retry loop */
+ "dec %0\n\t" /* otherwise, retry-- */
+ "jne 1b\n\t" /* and loop if retries are not exhausted */
+ "jmp 3f\n" /* failure, retry is 0, used as return value */
+ "2:\n\t"
+ "mov %2,%1\n\t" /* *buf = tmp */
+ "3:"
+ : "+q" (retry), "=m" (*buf), "=q" (tmp) : : "cc");
+ return (retry);
#else /* __GNUCLIKE_ASM */
return (0);
#endif
@@ -86,23 +89,13 @@ ivy_rng_store(uint64_t *tmp)
static int
random_ivy_read(void *buf, int c)
{
- uint8_t *b;
- int count, ret, retry;
- uint64_t tmp;
-
- b = buf;
- for (count = c; count > 0; count -= ret) {
- for (retry = 0; retry < RETRY_COUNT; retry++) {
- ret = ivy_rng_store(&tmp);
- if (ret != 0)
- break;
- }
- if (ret == 0)
+ long *b;
+ int count;
+
+ KASSERT(c % sizeof(long) == 0, ("partial read %d", c));
+ for (b = buf, count = c; count > 0; count -= sizeof(long), b++) {
+ if (ivy_rng_store(b) == 0)
break;
- if (ret > count)
- ret = count;
- memcpy(b, &tmp, ret);
- b += ret;
}
return (c - count);
}
OpenPOWER on IntegriCloud