As requested - here's just "cpu_rng" itself for review.  I believe this
version addresses all comments received so far except that I _like_ the
construct "size_t cnt = <constant>; type_t foo[x]" so I've retained
that.

On the other hand, I _dislike_ needless forward declarations so I've
moved a small amount of code in kern_rndq.c to avoid another one of
those.

If this looks OK, I'll commit it and the next thing for review will be
the RDRAND backend; then RDSEED, then VIA.  I have no hardware with RDSEED
nor a VIA RNG to test, so I'd appreciate help with that.

The RDRAND backend (unsurprisingly) passes the in-kernel statistical
test on both i386 and amd64.

Thor
Index: arch/amd64/include/Makefile
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/amd64/include/Makefile,v
retrieving revision 1.18
diff -u -p -r1.18 Makefile
--- arch/amd64/include/Makefile 23 Jul 2014 18:19:43 -0000      1.18
+++ arch/amd64/include/Makefile 8 Jan 2016 13:50:42 -0000
@@ -4,7 +4,7 @@ INCSDIR= /usr/include/amd64
 
 INCS=  ansi.h aout_machdep.h asm.h \
        bootinfo.h bswap.h byte_swap.h \
-       cdefs.h cpu.h \
+       cdefs.h cpu.h cpu_rng.h\
        disklabel.h \
        elf_machdep.h endian.h endian_machdep.h \
        float.h fpu.h frame.h frame_regs.h \
Index: arch/amd64/include/types.h
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/amd64/include/types.h,v
retrieving revision 1.48
diff -u -p -r1.48 types.h
--- arch/amd64/include/types.h  27 Aug 2015 12:30:50 -0000      1.48
+++ arch/amd64/include/types.h  8 Jan 2016 13:50:42 -0000
@@ -93,6 +93,7 @@ typedef       unsigned char           __cpu_simple_lock
 #define        __HAVE_TLS_VARIANT_II
 #define        __HAVE_COMMON___TLS_GET_ADDR
 #define        __HAVE_INTR_CONTROL
+#define        __HAVE_CPU_RNG
 
 #ifdef _KERNEL_OPT
 #define        __HAVE_RAS
Index: arch/i386/include/Makefile
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/i386/include/Makefile,v
retrieving revision 1.43
diff -u -p -r1.43 Makefile
--- arch/i386/include/Makefile  23 Jul 2014 18:19:44 -0000      1.43
+++ arch/i386/include/Makefile  8 Jan 2016 13:50:42 -0000
@@ -4,7 +4,7 @@ INCSDIR= /usr/include/i386
 
 INCS=  ansi.h aout_machdep.h apmvar.h asm.h \
        bioscall.h bootinfo.h bswap.h byte_swap.h \
-       cdefs.h cpu.h cputypes.h \
+       cdefs.h cpu.h cpu_rng.h cputypes.h \
        disklabel.h \
        elf_machdep.h endian.h endian_machdep.h \
        fenv.h float.h frame.h freebsd_machdep.h \
Index: arch/i386/include/types.h
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/i386/include/types.h,v
retrieving revision 1.83
diff -u -p -r1.83 types.h
--- arch/i386/include/types.h   27 Aug 2015 12:30:51 -0000      1.83
+++ arch/i386/include/types.h   8 Jan 2016 13:50:42 -0000
@@ -109,6 +109,8 @@ typedef     unsigned char           __cpu_simple_lock
 #define        __HAVE_SYSCALL_INTERN
 #define        __HAVE_MINIMAL_EMUL
 #define        __HAVE_OLD_DISKLABEL
+#define        __HAVE_CPU_RNG
+
 #if defined(_KERNEL)
 /*
  * Processors < i586 do not have cmpxchg8b, and we compile for i486
Index: arch/x86/conf/files.x86
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/x86/conf/files.x86,v
retrieving revision 1.85
diff -u -p -r1.85 files.x86
--- arch/x86/conf/files.x86     11 Nov 2015 08:20:22 -0000      1.85
+++ arch/x86/conf/files.x86     8 Jan 2016 13:50:42 -0000
@@ -27,6 +27,7 @@ define  ipmibus {}
 device cpu: cpufeaturebus
 attach cpu at cpubus
 file   arch/x86/x86/cpu.c              cpu
+file   arch/x86/x86/cpu_rng.c          cpu
 
 device acpicpu: acpi
 attach acpicpu at cpufeaturebus
Index: arch/x86/include/Makefile
===================================================================
RCS file: /Volumes/NB/repo/src/sys/arch/x86/include/Makefile,v
retrieving revision 1.19
diff -u -p -r1.19 Makefile
--- arch/x86/include/Makefile   11 Feb 2014 20:17:16 -0000      1.19
+++ arch/x86/include/Makefile   8 Jan 2016 13:50:42 -0000
@@ -7,6 +7,7 @@ INCS=   aout_machdep.h \
        cacheinfo.h \
        cpu.h \
        cpu_extended_state.h \
+       cpu_rng.h \
        cpu_ucode.h \
        cputypes.h \
        cpuvar.h \
Index: kern/kern_rndq.c
===================================================================
RCS file: /Volumes/NB/repo/src/sys/kern/kern_rndq.c,v
retrieving revision 1.74
diff -u -p -r1.74 kern_rndq.c
--- kern/kern_rndq.c    1 Jan 2016 16:09:00 -0000       1.74
+++ kern/kern_rndq.c    8 Jan 2016 13:50:42 -0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_rndq.c,v 1.72 2015/08/05 16:51:09 riastradh Exp $ */
+/*     $NetBSD: kern_rndq.c,v 1.74 2016/01/01 16:09:00 tls Exp $       */
 
 /*-
  * Copyright (c) 1997-2013 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.72 2015/08/05 16:51:09 riastradh 
Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,v 1.74 2016/01/01 16:09:00 tls Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -59,6 +59,10 @@ __KERNEL_RCSID(0, "$NetBSD: kern_rndq.c,
 #include <compat/sys/rnd.h>
 #endif
 
+#if defined(__HAVE_CPU_RNG)
+#include <machine/cpu_rng.h>
+#endif
+
 #if defined(__HAVE_CPU_COUNTER)
 #include <machine/cpu_counter.h>
 #endif
@@ -189,17 +193,6 @@ rnd_printf(const char *fmt, ...)
        rnd_printing = 0;
 }
 
-void
-rnd_init_softint(void)
-{
-
-       rnd_process = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE,
-           rnd_intr, NULL);
-       rnd_wakeup = softint_establish(SOFTINT_CLOCK|SOFTINT_MPSAFE,
-           rnd_wake, NULL);
-       rnd_schedule_process();
-}
-
 /*
  * Generate a 32-bit counter.
  */
@@ -404,6 +397,49 @@ rnd_dv_estimate(krndsource_t *rs, uint32
        return ret;
 }
 
+#if defined(__HAVE_CPU_RNG)
+static struct {
+       kmutex_t        lock;   /* unfortunately, must protect krndsource */
+       void *          intr;
+       krndsource_t    source;
+} rnd_cpu __cacheline_aligned;
+       
+static void
+rnd_cpu_get(size_t bytes, void *priv)
+{
+       krndsource_t *cpusrcp = priv;
+       KASSERT(cpusrcp == &rnd_cpu.source);
+
+       if (__predict_true(rnd_cpu.intr != NULL)) {
+               rnd_schedule_softint(rnd_cpu.intr);
+       }
+}
+
+static void
+rnd_cpu_intr(void *priv)
+{
+       size_t entropy = 0;
+       size_t cnt = 2 * RND_ENTROPY_THRESHOLD / sizeof(cpu_rng_t);
+       cpu_rng_t buf[cnt];
+       krndsource_t *cpusrcp = &rnd_cpu.source;
+
+        if (RND_ENABLED(cpusrcp)) {
+               cpu_rng_t *bufp;
+
+               mutex_spin_enter(&rnd_cpu.lock);
+               for (bufp = buf; bufp < buf + cnt; bufp++) {
+                       entropy += cpu_rng(bufp);
+               }
+               if (__predict_true(entropy)) {
+                       rnd_add_data(cpusrcp, buf, sizeof(buf), entropy);
+                       explicit_memset(buf, 0, sizeof(buf));
+               }
+               mutex_spin_exit(&rnd_cpu.lock);
+        }
+}
+
+#endif
+
 #if defined(__HAVE_CPU_COUNTER)
 static struct {
        kmutex_t        lock;
@@ -463,6 +499,21 @@ rnd_skew_intr(void *arg)
 }
 #endif
 
+void
+rnd_init_softint(void)
+{
+
+       rnd_process = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE,
+           rnd_intr, NULL);
+       rnd_wakeup = softint_establish(SOFTINT_CLOCK|SOFTINT_MPSAFE,
+           rnd_wake, NULL);
+#ifdef __HAVE_CPU_RNG
+       rnd_cpu.intr = softint_establish(SOFTINT_SERIAL|SOFTINT_MPSAFE,
+           rnd_cpu_intr, NULL);
+#endif
+       rnd_schedule_process();
+}
+
 /*
  * Entropy was just added to the pool.  If we crossed the threshold for
  * the first time, set rnd_initial_entropy = 1.
@@ -542,6 +593,21 @@ rnd_init(void)
        }
 
        /*
+        * Attach CPU RNG if available.
+        */
+#if defined(__HAVE_CPU_RNG)
+       if (cpu_rng_init()) {
+               /* IPL_VM because taken while rnd_global.lock is held.  */
+               mutex_init(&rnd_cpu.lock, MUTEX_DEFAULT, IPL_VM);
+               rndsource_setcb(&rnd_cpu.source, rnd_cpu_get, &rnd_cpu.source);
+               rnd_attach_source(&rnd_cpu.source, "cpurng",
+                   RND_TYPE_RNG, RND_FLAG_COLLECT_VALUE|
+                   RND_FLAG_HASCB|RND_FLAG_HASENABLE);
+               rnd_cpu_intr(NULL);
+       }
+#endif
+
+       /*
         * If we have a cycle counter, take its error with respect
         * to the callout mechanism as a source of entropy, ala
         * TrueRand.
@@ -572,7 +638,7 @@ rnd_init(void)
                mutex_spin_exit(&rnd_global.lock);
                rnd_printf("rnd: seeded with %d bits\n",
                    MIN(boot_rsp->entropy, RND_POOLBITS / 2));
-               memset(boot_rsp, 0, sizeof(*boot_rsp));
+               explicit_memset(boot_rsp, 0, sizeof(*boot_rsp));
        }
        rnd_attach_source(&rnd_printf_source, "printf", RND_TYPE_UNKNOWN,
                          RND_FLAG_NO_ESTIMATE);
@@ -621,7 +687,7 @@ static void
 rnd_sample_free(rnd_sample_t *c)
 {
 
-       memset(c, 0, sizeof(*c));
+       explicit_memset(c, 0, sizeof(*c));
        pool_cache_put(rnd_mempc, c);
 }
 
@@ -996,7 +1062,7 @@ rnd_hwrng_test(rnd_sample_t *sample)
                        return 1;
                }
                source->test_cnt = -1;
-               memset(source->test, 0, sizeof(*source->test));
+               explicit_memset(source->test, 0, sizeof(*source->test));
        }
        return 0;
 }
@@ -1201,10 +1267,10 @@ rnd_extract_data(void *p, uint32_t len, 
                            "STATISTICAL TEST!\n");
                        continue;
                }
-               memset(&rnd_rt, 0, sizeof(rnd_rt));
+               explicit_memset(&rnd_rt, 0, sizeof(rnd_rt));
                rndpool_add_data(&rnd_global.pool, rnd_testbits,
                    sizeof(rnd_testbits), entropy_count);
-               memset(rnd_testbits, 0, sizeof(rnd_testbits));
+               explicit_memset(rnd_testbits, 0, sizeof(rnd_testbits));
                rnd_printf_verbose("rnd: statistical RNG test done,"
                    " entropy = %d.\n",
                    rndpool_get_entropy_count(&rnd_global.pool));
@@ -1319,7 +1385,7 @@ rnd_seed(void *base, size_t len)
                rndpool_add_data(&rnd_global.pool, boot_rsp->data,
                    sizeof(boot_rsp->data),
                    MIN(boot_rsp->entropy, RND_POOLBITS / 2));
-               memset(boot_rsp, 0, sizeof(*boot_rsp));
+               explicit_memset(boot_rsp, 0, sizeof(*boot_rsp));
                mutex_spin_exit(&rnd_global.lock);
        } else {
                rnd_printf_verbose("rnd: not ready, deferring seed feed.\n");

Reply via email to