tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Patch: CPU RNG framework with stub x86 implementation



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");


Home | Main Index | Thread Index | Old Index