On Mon, Feb 27, 2023 at 7:30 PM Eric Biggers <ebiggers@xxxxxxxxxx> wrote: > > From: Eric Biggers <ebiggers@xxxxxxxxxx> > > The performance of the crypto fuzz tests has greatly regressed since > v5.18. When booting a kernel on an arm64 dev board with all software > crypto algorithms and CONFIG_CRYPTO_MANAGER_EXTRA_TESTS enabled, the > fuzz tests now take about 200 seconds to run, or about 325 seconds with > lockdep enabled, compared to about 5 seconds before. > > The root cause is that the random number generation has become much > slower due to commit d4150779e60f ("random32: use real rng for > non-deterministic randomness"). On my same arm64 dev board, at the time > the fuzz tests are run, get_random_u8() is about 345x slower than > prandom_u32_state(), or about 469x if lockdep is enabled. > > Lockdep makes a big difference, but much of the rest comes from the > get_random_*() functions taking a *very* slow path when the CRNG is not > yet initialized. Since the crypto self-tests run early during boot, > even having a hardware RNG driver enabled (CONFIG_CRYPTO_DEV_QCOM_RNG in > my case) doesn't prevent this. x86 systems don't have this issue, but > they still see a significant regression if lockdep is enabled. > > Converting the "Fully random bytes" case in generate_random_bytes() to > use get_random_bytes() helps significantly, improving the test time to > about 27 seconds. But that's still over 5x slower than before. > > This is all a bit silly, though, since the fuzz tests don't actually > need cryptographically secure random numbers. So let's just make them > use a non-cryptographically-secure RNG as they did before. The original > prandom_u32() is gone now, so let's use prandom_u32_state() instead, > with an explicitly managed state, like various other self-tests in the > kernel source tree (rbtree_test.c, test_scanf.c, etc.) already do. This > also has the benefit that no locking is required anymore, so performance > should be even better than the original version that used prandom_u32(). > > Fixes: d4150779e60f ("random32: use real rng for non-deterministic randomness") > Cc: stable@xxxxxxxxxxxxxxx > Signed-off-by: Eric Biggers <ebiggers@xxxxxxxxxx> > --- > > v2: made init_rnd_state() use get_random_u64() > > crypto/testmgr.c | 266 ++++++++++++++++++++++++++++++----------------- > 1 file changed, 169 insertions(+), 97 deletions(-) > > diff --git a/crypto/testmgr.c b/crypto/testmgr.c > index c91e93ece20b..b160eeb12c8e 100644 > --- a/crypto/testmgr.c > +++ b/crypto/testmgr.c > @@ -860,12 +860,50 @@ static int prepare_keybuf(const u8 *key, unsigned int ksize, > > #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS > > +/* > + * The fuzz tests use prandom instead of the normal Linux RNG since they don't > + * need cryptographically secure random numbers. This greatly improves the > + * performance of these tests, especially if they are run before the Linux RNG > + * has been initialized or if they are run on a lockdep-enabled kernel. > + */ > + > +static inline void init_rnd_state(struct rnd_state *rng) > +{ > + prandom_seed_state(rng, get_random_u64()); i915 does something similar and prints it out with `kunit_info(suite, "Testing DRM buddy manager, with random_seed=0x%x\n", random_seed);`, so that you can repeat the test if necessary. Not saying you have to do this now, but it may be a cool feature to keep in mind for the future. Jason