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)); } /*