Module Name:    src
Committed By:   riastradh
Date:           Sat Jan 16 02:21:26 UTC 2021

Modified Files:
        src/sys/kern: kern_entropy.c

Log Message:
entropy: Record number of time and data samples for userland.

This more or less follows the semantics of the RNDGETESTNUM and
RNDGETESTNAME ioctls to restore useful `rndctl -lv' output.

Specifically: We count the number of time or data samples entered
with rnd_add_*.  Previously it would count the total number of 32-bit
words in the data, rather than the number of rnd_add_* calls that
enter data, but I think the number of calls makes more sense here.


To generate a diff of this commit:
cvs rdiff -u -r1.27 -r1.28 src/sys/kern/kern_entropy.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_entropy.c
diff -u src/sys/kern/kern_entropy.c:1.27 src/sys/kern/kern_entropy.c:1.28
--- src/sys/kern/kern_entropy.c:1.27	Wed Jan 13 23:53:23 2021
+++ src/sys/kern/kern_entropy.c	Sat Jan 16 02:21:26 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_entropy.c,v 1.27 2021/01/13 23:53:23 riastradh Exp $	*/
+/*	$NetBSD: kern_entropy.c,v 1.28 2021/01/16 02:21:26 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -75,7 +75,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_entropy.c,v 1.27 2021/01/13 23:53:23 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_entropy.c,v 1.28 2021/01/16 02:21:26 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -141,7 +141,9 @@ struct entropy_cpu {
  *	Per-CPU rndsource state.
  */
 struct rndsource_cpu {
-	unsigned		rc_nbits; /* bits of entropy added */
+	unsigned		rc_entropybits;
+	unsigned		rc_timesamples;
+	unsigned		rc_datasamples;
 };
 
 /*
@@ -250,11 +252,12 @@ static void	filt_entropy_read_detach(str
 static int	filt_entropy_read_event(struct knote *, long);
 static void	entropy_request(size_t);
 static void	rnd_add_data_1(struct krndsource *, const void *, uint32_t,
-		    uint32_t);
+		    uint32_t, uint32_t);
 static unsigned	rndsource_entropybits(struct krndsource *);
 static void	rndsource_entropybits_cpu(void *, void *, struct cpu_info *);
 static void	rndsource_to_user(struct krndsource *, rndsource_t *);
 static void	rndsource_to_user_est(struct krndsource *, rndsource_est_t *);
+static void	rndsource_to_user_est_cpu(void *, void *, struct cpu_info *);
 
 /*
  * entropy_timer()
@@ -1545,6 +1548,8 @@ rnd_attach_source(struct krndsource *rs,
 	/* Initialize the random source.  */
 	memset(rs->name, 0, sizeof(rs->name)); /* paranoia */
 	strlcpy(rs->name, name, sizeof(rs->name));
+	memset(&rs->time_delta, 0, sizeof(rs->time_delta));
+	memset(&rs->value_delta, 0, sizeof(rs->value_delta));
 	rs->total = 0;
 	rs->type = type;
 	rs->flags = flags;
@@ -1817,17 +1822,27 @@ rnd_add_data(struct krndsource *rs, cons
 
 	/* If we are collecting data, enter them.  */
 	if (ISSET(flags, RND_FLAG_COLLECT_VALUE))
-		rnd_add_data_1(rs, buf, len, entropybits);
+		rnd_add_data_1(rs, buf, len, entropybits,
+		    RND_FLAG_COLLECT_VALUE);
 
 	/* If we are collecting timings, enter one.  */
 	if (ISSET(flags, RND_FLAG_COLLECT_TIME)) {
 		extra = entropy_timer();
-		rnd_add_data_1(rs, &extra, sizeof extra, 0);
+		rnd_add_data_1(rs, &extra, sizeof extra, 0,
+		    RND_FLAG_COLLECT_TIME);
 	}
 }
 
+static unsigned
+add_sat(unsigned a, unsigned b)
+{
+	unsigned c = a + b;
+
+	return (c < a ? UINT_MAX : c);
+}
+
 /*
- * rnd_add_data_1(rs, buf, len, entropybits)
+ * rnd_add_data_1(rs, buf, len, entropybits, flag)
  *
  *	Internal subroutine to call either entropy_enter_intr, if we're
  *	in interrupt context, or entropy_enter if not, and to count the
@@ -1835,7 +1850,7 @@ rnd_add_data(struct krndsource *rs, cons
  */
 static void
 rnd_add_data_1(struct krndsource *rs, const void *buf, uint32_t len,
-    uint32_t entropybits)
+    uint32_t entropybits, uint32_t flag)
 {
 	bool fullyused;
 
@@ -1859,15 +1874,34 @@ rnd_add_data_1(struct krndsource *rs, co
 		if (E->stage < ENTROPY_HOT) {
 			if (E->stage >= ENTROPY_WARM)
 				mutex_enter(&E->lock);
-			rs->total += MIN(UINT_MAX - rs->total, entropybits);
+			rs->total = add_sat(rs->total, entropybits);
+			switch (flag) {
+			case RND_FLAG_COLLECT_TIME:
+				rs->time_delta.insamples =
+				    add_sat(rs->time_delta.insamples, 1);
+				break;
+			case RND_FLAG_COLLECT_VALUE:
+				rs->value_delta.insamples =
+				    add_sat(rs->value_delta.insamples, 1);
+				break;
+			}
 			if (E->stage >= ENTROPY_WARM)
 				mutex_exit(&E->lock);
 		} else {
 			struct rndsource_cpu *rc = percpu_getref(rs->state);
-			unsigned nbits = rc->rc_nbits;
 
-			nbits += MIN(UINT_MAX - nbits, entropybits);
-			atomic_store_relaxed(&rc->rc_nbits, nbits);
+			atomic_store_relaxed(&rc->rc_entropybits,
+			    add_sat(rc->rc_entropybits, entropybits));
+			switch (flag) {
+			case RND_FLAG_COLLECT_TIME:
+				atomic_store_relaxed(&rc->rc_timesamples,
+				    add_sat(rc->rc_timesamples, 1));
+				break;
+			case RND_FLAG_COLLECT_VALUE:
+				atomic_store_relaxed(&rc->rc_datasamples,
+				    add_sat(rc->rc_datasamples, 1));
+				break;
+			}
 			percpu_putref(rs->state);
 		}
 	}
@@ -1912,7 +1946,7 @@ rndsource_entropybits_cpu(void *ptr, voi
 	unsigned *nbitsp = cookie;
 	unsigned cpu_nbits;
 
-	cpu_nbits = atomic_load_relaxed(&rc->rc_nbits);
+	cpu_nbits = atomic_load_relaxed(&rc->rc_entropybits);
 	*nbitsp += MIN(UINT_MAX - *nbitsp, cpu_nbits);
 }
 
@@ -1957,11 +1991,24 @@ rndsource_to_user_est(struct krndsource 
 	/* Copy out the rndsource description.  */
 	rndsource_to_user(rs, &urse->rt);
 
-	/* Zero out the statistics because we don't do estimation.  */
-	urse->dt_samples = 0;
+	/* Gather the statistics.  */
+	urse->dt_samples = rs->time_delta.insamples;
 	urse->dt_total = 0;
-	urse->dv_samples = 0;
-	urse->dv_total = 0;
+	urse->dv_samples = rs->value_delta.insamples;
+	urse->dv_total = urse->rt.total;
+	percpu_foreach(rs->state, rndsource_to_user_est_cpu, urse);
+}
+
+static void
+rndsource_to_user_est_cpu(void *ptr, void *cookie, struct cpu_info *ci)
+{
+	struct rndsource_cpu *rc = ptr;
+	rndsource_est_t *urse = cookie;
+
+	urse->dt_samples = add_sat(urse->dt_samples,
+	    atomic_load_relaxed(&rc->rc_timesamples));
+	urse->dv_samples = add_sat(urse->dv_samples,
+	    atomic_load_relaxed(&rc->rc_datasamples));
 }
 
 /*

Reply via email to