linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
To: linux-kernel@vger.kernel.org, tytso@mit.edu
Cc: "Jason A. Donenfeld" <Jason@zx2c4.com>
Subject: [PATCH 1/7] random: cleanup poolinfo abstraction
Date: Thu, 13 Jan 2022 16:44:07 +0100	[thread overview]
Message-ID: <20220113154413.29513-2-Jason@zx2c4.com> (raw)
In-Reply-To: <20220113154413.29513-1-Jason@zx2c4.com>

Now that we're only using one polynomial, we can cleanup its
representation into constants, instead of passing around pointers
dynamically to select different polynomials. This improves the codegen
and makes the code a bit more straightforward.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
---
 drivers/char/random.c | 85 ++++++++++++++++++++-----------------------
 1 file changed, 39 insertions(+), 46 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 227fb7802738..c8f05b7551dc 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -430,14 +430,20 @@ static int random_write_wakeup_bits = 28 * OUTPUT_POOL_WORDS;
  * polynomial which improves the resulting TGFSR polynomial to be
  * irreducible, which we have made here.
  */
-static const struct poolinfo {
-	int poolbitshift, poolwords, poolbytes, poolfracbits;
-#define S(x) ilog2(x)+5, (x), (x)*4, (x) << (ENTROPY_SHIFT+5)
-	int tap1, tap2, tap3, tap4, tap5;
-} poolinfo_table[] = {
-	/* was: x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 */
+enum poolinfo {
+	POOL_WORDS = 128,
+	POOL_WORDMASK = POOL_WORDS - 1,
+	POOL_BYTES = POOL_WORDS * sizeof(u32),
+	POOL_BITS = POOL_BYTES * 8,
+	POOL_BITSHIFT = ilog2(POOL_WORDS) + 5,
+	POOL_FRACBITS = POOL_WORDS << (ENTROPY_SHIFT + 5),
+
 	/* x^128 + x^104 + x^76 + x^51 +x^25 + x + 1 */
-	{ S(128),	104,	76,	51,	25,	1 },
+	POOL_TAP1 = 104,
+	POOL_TAP2 = 76,
+	POOL_TAP3 = 51,
+	POOL_TAP4 = 25,
+	POOL_TAP5 = 1
 };
 
 /*
@@ -503,7 +509,6 @@ MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
 struct entropy_store;
 struct entropy_store {
 	/* read-only data: */
-	const struct poolinfo *poolinfo;
 	__u32 *pool;
 	const char *name;
 
@@ -525,7 +530,6 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r);
 static __u32 input_pool_data[INPUT_POOL_WORDS] __latent_entropy;
 
 static struct entropy_store input_pool = {
-	.poolinfo = &poolinfo_table[0],
 	.name = "input",
 	.lock = __SPIN_LOCK_UNLOCKED(input_pool.lock),
 	.pool = input_pool_data
@@ -548,33 +552,26 @@ static __u32 const twist_table[8] = {
 static void _mix_pool_bytes(struct entropy_store *r, const void *in,
 			    int nbytes)
 {
-	unsigned long i, tap1, tap2, tap3, tap4, tap5;
+	unsigned long i;
 	int input_rotate;
-	int wordmask = r->poolinfo->poolwords - 1;
 	const unsigned char *bytes = in;
 	__u32 w;
 
-	tap1 = r->poolinfo->tap1;
-	tap2 = r->poolinfo->tap2;
-	tap3 = r->poolinfo->tap3;
-	tap4 = r->poolinfo->tap4;
-	tap5 = r->poolinfo->tap5;
-
 	input_rotate = r->input_rotate;
 	i = r->add_ptr;
 
 	/* mix one byte at a time to simplify size handling and churn faster */
 	while (nbytes--) {
 		w = rol32(*bytes++, input_rotate);
-		i = (i - 1) & wordmask;
+		i = (i - 1) & POOL_WORDMASK;
 
 		/* XOR in the various taps */
 		w ^= r->pool[i];
-		w ^= r->pool[(i + tap1) & wordmask];
-		w ^= r->pool[(i + tap2) & wordmask];
-		w ^= r->pool[(i + tap3) & wordmask];
-		w ^= r->pool[(i + tap4) & wordmask];
-		w ^= r->pool[(i + tap5) & wordmask];
+		w ^= r->pool[(i + POOL_TAP1) & POOL_WORDMASK];
+		w ^= r->pool[(i + POOL_TAP2) & POOL_WORDMASK];
+		w ^= r->pool[(i + POOL_TAP3) & POOL_WORDMASK];
+		w ^= r->pool[(i + POOL_TAP4) & POOL_WORDMASK];
+		w ^= r->pool[(i + POOL_TAP5) & POOL_WORDMASK];
 
 		/* Mix the result back in with a twist */
 		r->pool[i] = (w >> 3) ^ twist_table[w & 7];
@@ -672,7 +669,6 @@ static void process_random_ready_list(void)
 static void credit_entropy_bits(struct entropy_store *r, int nbits)
 {
 	int entropy_count, orig;
-	const int pool_size = r->poolinfo->poolfracbits;
 	int nfrac = nbits << ENTROPY_SHIFT;
 
 	if (!nbits)
@@ -690,41 +686,41 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
 		 * ideal case of pure Shannon entropy, new contributions
 		 * approach the full value asymptotically:
 		 *
-		 * entropy <- entropy + (pool_size - entropy) *
-		 *	(1 - exp(-add_entropy/pool_size))
+		 * entropy <- entropy + (POOL_FRACBITS - entropy) *
+		 *	(1 - exp(-add_entropy/POOL_FRACBITS))
 		 *
-		 * For add_entropy <= pool_size/2 then
-		 * (1 - exp(-add_entropy/pool_size)) >=
-		 *    (add_entropy/pool_size)*0.7869...
+		 * For add_entropy <= POOL_FRACBITS/2 then
+		 * (1 - exp(-add_entropy/POOL_FRACBITS)) >=
+		 *    (add_entropy/POOL_FRACBITS)*0.7869...
 		 * so we can approximate the exponential with
-		 * 3/4*add_entropy/pool_size and still be on the
-		 * safe side by adding at most pool_size/2 at a time.
+		 * 3/4*add_entropy/POOL_FRACBITS and still be on the
+		 * safe side by adding at most POOL_FRACBITS/2 at a time.
 		 *
-		 * The use of pool_size-2 in the while statement is to
+		 * The use of POOL_FRACBITS-2 in the while statement is to
 		 * prevent rounding artifacts from making the loop
-		 * arbitrarily long; this limits the loop to log2(pool_size)*2
+		 * arbitrarily long; this limits the loop to log2(POOL_FRACBITS)*2
 		 * turns no matter how large nbits is.
 		 */
 		int pnfrac = nfrac;
-		const int s = r->poolinfo->poolbitshift + ENTROPY_SHIFT + 2;
+		const int s = POOL_BITSHIFT + ENTROPY_SHIFT + 2;
 		/* The +2 corresponds to the /4 in the denominator */
 
 		do {
-			unsigned int anfrac = min(pnfrac, pool_size/2);
+			unsigned int anfrac = min(pnfrac, POOL_FRACBITS/2);
 			unsigned int add =
-				((pool_size - entropy_count)*anfrac*3) >> s;
+				((POOL_FRACBITS - entropy_count)*anfrac*3) >> s;
 
 			entropy_count += add;
 			pnfrac -= anfrac;
-		} while (unlikely(entropy_count < pool_size-2 && pnfrac));
+		} while (unlikely(entropy_count < POOL_FRACBITS-2 && pnfrac));
 	}
 
 	if (WARN_ON(entropy_count < 0)) {
 		pr_warn("negative entropy/overflow: pool %s count %d\n",
 			r->name, entropy_count);
 		entropy_count = 0;
-	} else if (entropy_count > pool_size)
-		entropy_count = pool_size;
+	} else if (entropy_count > POOL_FRACBITS)
+		entropy_count = POOL_FRACBITS;
 	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
 		goto retry;
 
@@ -741,13 +737,11 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
 
 static int credit_entropy_bits_safe(struct entropy_store *r, int nbits)
 {
-	const int nbits_max = r->poolinfo->poolwords * 32;
-
 	if (nbits < 0)
 		return -EINVAL;
 
 	/* Cap the value to avoid overflows */
-	nbits = min(nbits,  nbits_max);
+	nbits = min(nbits,  POOL_BITS);
 
 	credit_entropy_bits(r, nbits);
 	return 0;
@@ -1343,7 +1337,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
 	int entropy_count, orig, have_bytes;
 	size_t ibytes, nfrac;
 
-	BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
+	BUG_ON(r->entropy_count > POOL_FRACBITS);
 
 	/* Can we pull enough? */
 retry:
@@ -1409,8 +1403,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
 
 	/* Generate a hash across the pool */
 	spin_lock_irqsave(&r->lock, flags);
-	blake2s_update(&state, (const u8 *)r->pool,
-		       r->poolinfo->poolwords * sizeof(*r->pool));
+	blake2s_update(&state, (const u8 *)r->pool, POOL_BYTES);
 	blake2s_final(&state, hash); /* final zeros out state */
 
 	/*
@@ -1766,7 +1759,7 @@ static void __init init_std_data(struct entropy_store *r)
 	unsigned long rv;
 
 	mix_pool_bytes(r, &now, sizeof(now));
-	for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
+	for (i = POOL_BYTES; i > 0; i -= sizeof(rv)) {
 		if (!arch_get_random_seed_long(&rv) &&
 		    !arch_get_random_long(&rv))
 			rv = random_get_entropy();
-- 
2.34.1


  reply	other threads:[~2022-01-13 15:44 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-13 15:44 [PATCH 0/7] first in overall series of rng code house cleaning Jason A. Donenfeld
2022-01-13 15:44 ` Jason A. Donenfeld [this message]
2022-01-16 13:24   ` [PATCH 1/7] random: cleanup poolinfo abstraction Dominik Brodowski
2022-01-13 15:44 ` [PATCH 2/7] random: cleanup integer types Jason A. Donenfeld
2022-01-16 13:24   ` Dominik Brodowski
2022-01-13 15:44 ` [PATCH 3/7] random: remove incomplete last_data logic Jason A. Donenfeld
2022-01-16 13:24   ` Dominik Brodowski
2022-01-13 15:44 ` [PATCH 4/7] random: remove unused reserved argument Jason A. Donenfeld
2022-01-16 13:24   ` Dominik Brodowski
2022-01-16 16:22     ` Jason A. Donenfeld
2022-01-17 17:28       ` Dominik Brodowski
2022-01-17 17:52         ` [PATCH] random: simplify arithmetic function flow in account() Jason A. Donenfeld
2022-01-17 17:55           ` Jason A. Donenfeld
2022-01-13 15:44 ` [PATCH 5/7] random: rather than entropy_store abstraction, use global Jason A. Donenfeld
2022-01-16 13:24   ` Dominik Brodowski
2022-01-13 15:44 ` [PATCH 6/7] random: remove unused OUTPUT_POOL constants Jason A. Donenfeld
2022-01-16 13:25   ` Dominik Brodowski
2022-01-13 15:44 ` [PATCH 7/7] random: de-duplicate INPUT_POOL constants Jason A. Donenfeld
2022-01-16 13:25   ` Dominik Brodowski
2022-01-14 15:33 ` [PATCH] random: cleanup fractional entropy shift constants Jason A. Donenfeld
2022-01-14 15:39   ` David Laight
2022-01-14 15:46     ` Jason A. Donenfeld
2022-01-16 16:35 ` [PATCH 1/4] random: prepend remaining pool constants with POOL_ Jason A. Donenfeld
2022-01-16 16:35   ` [PATCH 2/4] random: cleanup fractional entropy shift constants Jason A. Donenfeld
2022-01-17 17:31     ` Dominik Brodowski
2022-01-16 16:35   ` [PATCH 3/4] random: access input_pool_data directly rather than through pointer Jason A. Donenfeld
2022-01-17 17:32     ` Dominik Brodowski
2022-01-16 16:35   ` [PATCH 4/4] random: selectively clang-format where it makes sense Jason A. Donenfeld
2022-01-17 17:34     ` Dominik Brodowski
2022-01-17 17:29   ` [PATCH 1/4] random: prepend remaining pool constants with POOL_ Dominik Brodowski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220113154413.29513-2-Jason@zx2c4.com \
    --to=jason@zx2c4.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).