]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.1
authorSasha Levin <sashal@kernel.org>
Mon, 22 May 2023 18:28:19 +0000 (14:28 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 22 May 2023 18:28:19 +0000 (14:28 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.1/crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch [new file with mode: 0644]
queue-6.1/remoteproc-imx_dsp_rproc-fix-kernel-test-robot-spars.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch b/queue-6.1/crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch
new file mode 100644 (file)
index 0000000..c37aea1
--- /dev/null
@@ -0,0 +1,717 @@
+From fb492c6ef7dc7beb00ffe0b4697d885c873e5020 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 May 2023 22:08:50 -0700
+Subject: crypto: testmgr - fix RNG performance in fuzz tests
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit f900fde28883602b6c5e1027a6c912b673382aaf upstream.
+
+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@vger.kernel.org
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/testmgr.c | 266 ++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 169 insertions(+), 97 deletions(-)
+
+diff --git a/crypto/testmgr.c b/crypto/testmgr.c
+index 814d2dc87d7e8..56c39a0c94952 100644
+--- a/crypto/testmgr.c
++++ b/crypto/testmgr.c
+@@ -852,12 +852,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());
++}
++
++static inline u8 prandom_u8(struct rnd_state *rng)
++{
++      return prandom_u32_state(rng);
++}
++
++static inline u32 prandom_u32_below(struct rnd_state *rng, u32 ceil)
++{
++      /*
++       * This is slightly biased for non-power-of-2 values of 'ceil', but this
++       * isn't important here.
++       */
++      return prandom_u32_state(rng) % ceil;
++}
++
++static inline bool prandom_bool(struct rnd_state *rng)
++{
++      return prandom_u32_below(rng, 2);
++}
++
++static inline u32 prandom_u32_inclusive(struct rnd_state *rng,
++                                      u32 floor, u32 ceil)
++{
++      return floor + prandom_u32_below(rng, ceil - floor + 1);
++}
++
+ /* Generate a random length in range [0, max_len], but prefer smaller values */
+-static unsigned int generate_random_length(unsigned int max_len)
++static unsigned int generate_random_length(struct rnd_state *rng,
++                                         unsigned int max_len)
+ {
+-      unsigned int len = prandom_u32_max(max_len + 1);
++      unsigned int len = prandom_u32_below(rng, max_len + 1);
+-      switch (prandom_u32_max(4)) {
++      switch (prandom_u32_below(rng, 4)) {
+       case 0:
+               return len % 64;
+       case 1:
+@@ -870,43 +908,44 @@ static unsigned int generate_random_length(unsigned int max_len)
+ }
+ /* Flip a random bit in the given nonempty data buffer */
+-static void flip_random_bit(u8 *buf, size_t size)
++static void flip_random_bit(struct rnd_state *rng, u8 *buf, size_t size)
+ {
+       size_t bitpos;
+-      bitpos = prandom_u32_max(size * 8);
++      bitpos = prandom_u32_below(rng, size * 8);
+       buf[bitpos / 8] ^= 1 << (bitpos % 8);
+ }
+ /* Flip a random byte in the given nonempty data buffer */
+-static void flip_random_byte(u8 *buf, size_t size)
++static void flip_random_byte(struct rnd_state *rng, u8 *buf, size_t size)
+ {
+-      buf[prandom_u32_max(size)] ^= 0xff;
++      buf[prandom_u32_below(rng, size)] ^= 0xff;
+ }
+ /* Sometimes make some random changes to the given nonempty data buffer */
+-static void mutate_buffer(u8 *buf, size_t size)
++static void mutate_buffer(struct rnd_state *rng, u8 *buf, size_t size)
+ {
+       size_t num_flips;
+       size_t i;
+       /* Sometimes flip some bits */
+-      if (prandom_u32_max(4) == 0) {
+-              num_flips = min_t(size_t, 1 << prandom_u32_max(8), size * 8);
++      if (prandom_u32_below(rng, 4) == 0) {
++              num_flips = min_t(size_t, 1 << prandom_u32_below(rng, 8),
++                                size * 8);
+               for (i = 0; i < num_flips; i++)
+-                      flip_random_bit(buf, size);
++                      flip_random_bit(rng, buf, size);
+       }
+       /* Sometimes flip some bytes */
+-      if (prandom_u32_max(4) == 0) {
+-              num_flips = min_t(size_t, 1 << prandom_u32_max(8), size);
++      if (prandom_u32_below(rng, 4) == 0) {
++              num_flips = min_t(size_t, 1 << prandom_u32_below(rng, 8), size);
+               for (i = 0; i < num_flips; i++)
+-                      flip_random_byte(buf, size);
++                      flip_random_byte(rng, buf, size);
+       }
+ }
+ /* Randomly generate 'count' bytes, but sometimes make them "interesting" */
+-static void generate_random_bytes(u8 *buf, size_t count)
++static void generate_random_bytes(struct rnd_state *rng, u8 *buf, size_t count)
+ {
+       u8 b;
+       u8 increment;
+@@ -915,11 +954,11 @@ static void generate_random_bytes(u8 *buf, size_t count)
+       if (count == 0)
+               return;
+-      switch (prandom_u32_max(8)) { /* Choose a generation strategy */
++      switch (prandom_u32_below(rng, 8)) { /* Choose a generation strategy */
+       case 0:
+       case 1:
+               /* All the same byte, plus optional mutations */
+-              switch (prandom_u32_max(4)) {
++              switch (prandom_u32_below(rng, 4)) {
+               case 0:
+                       b = 0x00;
+                       break;
+@@ -927,28 +966,28 @@ static void generate_random_bytes(u8 *buf, size_t count)
+                       b = 0xff;
+                       break;
+               default:
+-                      b = get_random_u8();
++                      b = prandom_u8(rng);
+                       break;
+               }
+               memset(buf, b, count);
+-              mutate_buffer(buf, count);
++              mutate_buffer(rng, buf, count);
+               break;
+       case 2:
+               /* Ascending or descending bytes, plus optional mutations */
+-              increment = get_random_u8();
+-              b = get_random_u8();
++              increment = prandom_u8(rng);
++              b = prandom_u8(rng);
+               for (i = 0; i < count; i++, b += increment)
+                       buf[i] = b;
+-              mutate_buffer(buf, count);
++              mutate_buffer(rng, buf, count);
+               break;
+       default:
+               /* Fully random bytes */
+-              for (i = 0; i < count; i++)
+-                      buf[i] = get_random_u8();
++              prandom_bytes_state(rng, buf, count);
+       }
+ }
+-static char *generate_random_sgl_divisions(struct test_sg_division *divs,
++static char *generate_random_sgl_divisions(struct rnd_state *rng,
++                                         struct test_sg_division *divs,
+                                          size_t max_divs, char *p, char *end,
+                                          bool gen_flushes, u32 req_flags)
+ {
+@@ -959,24 +998,26 @@ static char *generate_random_sgl_divisions(struct test_sg_division *divs,
+               unsigned int this_len;
+               const char *flushtype_str;
+-              if (div == &divs[max_divs - 1] || prandom_u32_max(2) == 0)
++              if (div == &divs[max_divs - 1] || prandom_bool(rng))
+                       this_len = remaining;
+               else
+-                      this_len = 1 + prandom_u32_max(remaining);
++                      this_len = prandom_u32_inclusive(rng, 1, remaining);
+               div->proportion_of_total = this_len;
+-              if (prandom_u32_max(4) == 0)
+-                      div->offset = (PAGE_SIZE - 128) + prandom_u32_max(128);
+-              else if (prandom_u32_max(2) == 0)
+-                      div->offset = prandom_u32_max(32);
++              if (prandom_u32_below(rng, 4) == 0)
++                      div->offset = prandom_u32_inclusive(rng,
++                                                          PAGE_SIZE - 128,
++                                                          PAGE_SIZE - 1);
++              else if (prandom_bool(rng))
++                      div->offset = prandom_u32_below(rng, 32);
+               else
+-                      div->offset = prandom_u32_max(PAGE_SIZE);
+-              if (prandom_u32_max(8) == 0)
++                      div->offset = prandom_u32_below(rng, PAGE_SIZE);
++              if (prandom_u32_below(rng, 8) == 0)
+                       div->offset_relative_to_alignmask = true;
+               div->flush_type = FLUSH_TYPE_NONE;
+               if (gen_flushes) {
+-                      switch (prandom_u32_max(4)) {
++                      switch (prandom_u32_below(rng, 4)) {
+                       case 0:
+                               div->flush_type = FLUSH_TYPE_REIMPORT;
+                               break;
+@@ -988,7 +1029,7 @@ static char *generate_random_sgl_divisions(struct test_sg_division *divs,
+               if (div->flush_type != FLUSH_TYPE_NONE &&
+                   !(req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) &&
+-                  prandom_u32_max(2) == 0)
++                  prandom_bool(rng))
+                       div->nosimd = true;
+               switch (div->flush_type) {
+@@ -1023,7 +1064,8 @@ static char *generate_random_sgl_divisions(struct test_sg_division *divs,
+ }
+ /* Generate a random testvec_config for fuzz testing */
+-static void generate_random_testvec_config(struct testvec_config *cfg,
++static void generate_random_testvec_config(struct rnd_state *rng,
++                                         struct testvec_config *cfg,
+                                          char *name, size_t max_namelen)
+ {
+       char *p = name;
+@@ -1035,7 +1077,7 @@ static void generate_random_testvec_config(struct testvec_config *cfg,
+       p += scnprintf(p, end - p, "random:");
+-      switch (prandom_u32_max(4)) {
++      switch (prandom_u32_below(rng, 4)) {
+       case 0:
+       case 1:
+               cfg->inplace_mode = OUT_OF_PLACE;
+@@ -1050,12 +1092,12 @@ static void generate_random_testvec_config(struct testvec_config *cfg,
+               break;
+       }
+-      if (prandom_u32_max(2) == 0) {
++      if (prandom_bool(rng)) {
+               cfg->req_flags |= CRYPTO_TFM_REQ_MAY_SLEEP;
+               p += scnprintf(p, end - p, " may_sleep");
+       }
+-      switch (prandom_u32_max(4)) {
++      switch (prandom_u32_below(rng, 4)) {
+       case 0:
+               cfg->finalization_type = FINALIZATION_TYPE_FINAL;
+               p += scnprintf(p, end - p, " use_final");
+@@ -1070,36 +1112,37 @@ static void generate_random_testvec_config(struct testvec_config *cfg,
+               break;
+       }
+-      if (!(cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) &&
+-          prandom_u32_max(2) == 0) {
++      if (!(cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) && prandom_bool(rng)) {
+               cfg->nosimd = true;
+               p += scnprintf(p, end - p, " nosimd");
+       }
+       p += scnprintf(p, end - p, " src_divs=[");
+-      p = generate_random_sgl_divisions(cfg->src_divs,
++      p = generate_random_sgl_divisions(rng, cfg->src_divs,
+                                         ARRAY_SIZE(cfg->src_divs), p, end,
+                                         (cfg->finalization_type !=
+                                          FINALIZATION_TYPE_DIGEST),
+                                         cfg->req_flags);
+       p += scnprintf(p, end - p, "]");
+-      if (cfg->inplace_mode == OUT_OF_PLACE && prandom_u32_max(2) == 0) {
++      if (cfg->inplace_mode == OUT_OF_PLACE && prandom_bool(rng)) {
+               p += scnprintf(p, end - p, " dst_divs=[");
+-              p = generate_random_sgl_divisions(cfg->dst_divs,
++              p = generate_random_sgl_divisions(rng, cfg->dst_divs,
+                                                 ARRAY_SIZE(cfg->dst_divs),
+                                                 p, end, false,
+                                                 cfg->req_flags);
+               p += scnprintf(p, end - p, "]");
+       }
+-      if (prandom_u32_max(2) == 0) {
+-              cfg->iv_offset = 1 + prandom_u32_max(MAX_ALGAPI_ALIGNMASK);
++      if (prandom_bool(rng)) {
++              cfg->iv_offset = prandom_u32_inclusive(rng, 1,
++                                                     MAX_ALGAPI_ALIGNMASK);
+               p += scnprintf(p, end - p, " iv_offset=%u", cfg->iv_offset);
+       }
+-      if (prandom_u32_max(2) == 0) {
+-              cfg->key_offset = 1 + prandom_u32_max(MAX_ALGAPI_ALIGNMASK);
++      if (prandom_bool(rng)) {
++              cfg->key_offset = prandom_u32_inclusive(rng, 1,
++                                                      MAX_ALGAPI_ALIGNMASK);
+               p += scnprintf(p, end - p, " key_offset=%u", cfg->key_offset);
+       }
+@@ -1612,11 +1655,14 @@ static int test_hash_vec(const struct hash_testvec *vec, unsigned int vec_num,
+ #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
+       if (!noextratests) {
++              struct rnd_state rng;
+               struct testvec_config cfg;
+               char cfgname[TESTVEC_CONFIG_NAMELEN];
++              init_rnd_state(&rng);
++
+               for (i = 0; i < fuzz_iterations; i++) {
+-                      generate_random_testvec_config(&cfg, cfgname,
++                      generate_random_testvec_config(&rng, &cfg, cfgname,
+                                                      sizeof(cfgname));
+                       err = test_hash_vec_cfg(vec, vec_name, &cfg,
+                                               req, desc, tsgl, hashstate);
+@@ -1634,15 +1680,16 @@ static int test_hash_vec(const struct hash_testvec *vec, unsigned int vec_num,
+  * Generate a hash test vector from the given implementation.
+  * Assumes the buffers in 'vec' were already allocated.
+  */
+-static void generate_random_hash_testvec(struct shash_desc *desc,
++static void generate_random_hash_testvec(struct rnd_state *rng,
++                                       struct shash_desc *desc,
+                                        struct hash_testvec *vec,
+                                        unsigned int maxkeysize,
+                                        unsigned int maxdatasize,
+                                        char *name, size_t max_namelen)
+ {
+       /* Data */
+-      vec->psize = generate_random_length(maxdatasize);
+-      generate_random_bytes((u8 *)vec->plaintext, vec->psize);
++      vec->psize = generate_random_length(rng, maxdatasize);
++      generate_random_bytes(rng, (u8 *)vec->plaintext, vec->psize);
+       /*
+        * Key: length in range [1, maxkeysize], but usually choose maxkeysize.
+@@ -1652,9 +1699,9 @@ static void generate_random_hash_testvec(struct shash_desc *desc,
+       vec->ksize = 0;
+       if (maxkeysize) {
+               vec->ksize = maxkeysize;
+-              if (prandom_u32_max(4) == 0)
+-                      vec->ksize = 1 + prandom_u32_max(maxkeysize);
+-              generate_random_bytes((u8 *)vec->key, vec->ksize);
++              if (prandom_u32_below(rng, 4) == 0)
++                      vec->ksize = prandom_u32_inclusive(rng, 1, maxkeysize);
++              generate_random_bytes(rng, (u8 *)vec->key, vec->ksize);
+               vec->setkey_error = crypto_shash_setkey(desc->tfm, vec->key,
+                                                       vec->ksize);
+@@ -1688,6 +1735,7 @@ static int test_hash_vs_generic_impl(const char *generic_driver,
+       const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
+       const char *algname = crypto_hash_alg_common(tfm)->base.cra_name;
+       const char *driver = crypto_ahash_driver_name(tfm);
++      struct rnd_state rng;
+       char _generic_driver[CRYPTO_MAX_ALG_NAME];
+       struct crypto_shash *generic_tfm = NULL;
+       struct shash_desc *generic_desc = NULL;
+@@ -1701,6 +1749,8 @@ static int test_hash_vs_generic_impl(const char *generic_driver,
+       if (noextratests)
+               return 0;
++      init_rnd_state(&rng);
++
+       if (!generic_driver) { /* Use default naming convention? */
+               err = build_generic_driver_name(algname, _generic_driver);
+               if (err)
+@@ -1769,10 +1819,11 @@ static int test_hash_vs_generic_impl(const char *generic_driver,
+       }
+       for (i = 0; i < fuzz_iterations * 8; i++) {
+-              generate_random_hash_testvec(generic_desc, &vec,
++              generate_random_hash_testvec(&rng, generic_desc, &vec,
+                                            maxkeysize, maxdatasize,
+                                            vec_name, sizeof(vec_name));
+-              generate_random_testvec_config(cfg, cfgname, sizeof(cfgname));
++              generate_random_testvec_config(&rng, cfg, cfgname,
++                                             sizeof(cfgname));
+               err = test_hash_vec_cfg(&vec, vec_name, cfg,
+                                       req, desc, tsgl, hashstate);
+@@ -2174,11 +2225,14 @@ static int test_aead_vec(int enc, const struct aead_testvec *vec,
+ #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
+       if (!noextratests) {
++              struct rnd_state rng;
+               struct testvec_config cfg;
+               char cfgname[TESTVEC_CONFIG_NAMELEN];
++              init_rnd_state(&rng);
++
+               for (i = 0; i < fuzz_iterations; i++) {
+-                      generate_random_testvec_config(&cfg, cfgname,
++                      generate_random_testvec_config(&rng, &cfg, cfgname,
+                                                      sizeof(cfgname));
+                       err = test_aead_vec_cfg(enc, vec, vec_name,
+                                               &cfg, req, tsgls);
+@@ -2194,6 +2248,7 @@ static int test_aead_vec(int enc, const struct aead_testvec *vec,
+ #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
+ struct aead_extra_tests_ctx {
++      struct rnd_state rng;
+       struct aead_request *req;
+       struct crypto_aead *tfm;
+       const struct alg_test_desc *test_desc;
+@@ -2212,24 +2267,26 @@ struct aead_extra_tests_ctx {
+  * here means the full ciphertext including the authentication tag.  The
+  * authentication tag (and hence also the ciphertext) is assumed to be nonempty.
+  */
+-static void mutate_aead_message(struct aead_testvec *vec, bool aad_iv,
++static void mutate_aead_message(struct rnd_state *rng,
++                              struct aead_testvec *vec, bool aad_iv,
+                               unsigned int ivsize)
+ {
+       const unsigned int aad_tail_size = aad_iv ? ivsize : 0;
+       const unsigned int authsize = vec->clen - vec->plen;
+-      if (prandom_u32_max(2) == 0 && vec->alen > aad_tail_size) {
++      if (prandom_bool(rng) && vec->alen > aad_tail_size) {
+                /* Mutate the AAD */
+-              flip_random_bit((u8 *)vec->assoc, vec->alen - aad_tail_size);
+-              if (prandom_u32_max(2) == 0)
++              flip_random_bit(rng, (u8 *)vec->assoc,
++                              vec->alen - aad_tail_size);
++              if (prandom_bool(rng))
+                       return;
+       }
+-      if (prandom_u32_max(2) == 0) {
++      if (prandom_bool(rng)) {
+               /* Mutate auth tag (assuming it's at the end of ciphertext) */
+-              flip_random_bit((u8 *)vec->ctext + vec->plen, authsize);
++              flip_random_bit(rng, (u8 *)vec->ctext + vec->plen, authsize);
+       } else {
+               /* Mutate any part of the ciphertext */
+-              flip_random_bit((u8 *)vec->ctext, vec->clen);
++              flip_random_bit(rng, (u8 *)vec->ctext, vec->clen);
+       }
+ }
+@@ -2240,7 +2297,8 @@ static void mutate_aead_message(struct aead_testvec *vec, bool aad_iv,
+  */
+ #define MIN_COLLISION_FREE_AUTHSIZE 8
+-static void generate_aead_message(struct aead_request *req,
++static void generate_aead_message(struct rnd_state *rng,
++                                struct aead_request *req,
+                                 const struct aead_test_suite *suite,
+                                 struct aead_testvec *vec,
+                                 bool prefer_inauthentic)
+@@ -2249,17 +2307,18 @@ static void generate_aead_message(struct aead_request *req,
+       const unsigned int ivsize = crypto_aead_ivsize(tfm);
+       const unsigned int authsize = vec->clen - vec->plen;
+       const bool inauthentic = (authsize >= MIN_COLLISION_FREE_AUTHSIZE) &&
+-                               (prefer_inauthentic || prandom_u32_max(4) == 0);
++                               (prefer_inauthentic ||
++                                prandom_u32_below(rng, 4) == 0);
+       /* Generate the AAD. */
+-      generate_random_bytes((u8 *)vec->assoc, vec->alen);
++      generate_random_bytes(rng, (u8 *)vec->assoc, vec->alen);
+       if (suite->aad_iv && vec->alen >= ivsize)
+               /* Avoid implementation-defined behavior. */
+               memcpy((u8 *)vec->assoc + vec->alen - ivsize, vec->iv, ivsize);
+-      if (inauthentic && prandom_u32_max(2) == 0) {
++      if (inauthentic && prandom_bool(rng)) {
+               /* Generate a random ciphertext. */
+-              generate_random_bytes((u8 *)vec->ctext, vec->clen);
++              generate_random_bytes(rng, (u8 *)vec->ctext, vec->clen);
+       } else {
+               int i = 0;
+               struct scatterlist src[2], dst;
+@@ -2271,7 +2330,7 @@ static void generate_aead_message(struct aead_request *req,
+               if (vec->alen)
+                       sg_set_buf(&src[i++], vec->assoc, vec->alen);
+               if (vec->plen) {
+-                      generate_random_bytes((u8 *)vec->ptext, vec->plen);
++                      generate_random_bytes(rng, (u8 *)vec->ptext, vec->plen);
+                       sg_set_buf(&src[i++], vec->ptext, vec->plen);
+               }
+               sg_init_one(&dst, vec->ctext, vec->alen + vec->clen);
+@@ -2291,7 +2350,7 @@ static void generate_aead_message(struct aead_request *req,
+                * Mutate the authentic (ciphertext, AAD) pair to get an
+                * inauthentic one.
+                */
+-              mutate_aead_message(vec, suite->aad_iv, ivsize);
++              mutate_aead_message(rng, vec, suite->aad_iv, ivsize);
+       }
+       vec->novrfy = 1;
+       if (suite->einval_allowed)
+@@ -2305,7 +2364,8 @@ static void generate_aead_message(struct aead_request *req,
+  * If 'prefer_inauthentic' is true, then this function will generate inauthentic
+  * test vectors (i.e. vectors with 'vec->novrfy=1') more often.
+  */
+-static void generate_random_aead_testvec(struct aead_request *req,
++static void generate_random_aead_testvec(struct rnd_state *rng,
++                                       struct aead_request *req,
+                                        struct aead_testvec *vec,
+                                        const struct aead_test_suite *suite,
+                                        unsigned int maxkeysize,
+@@ -2321,18 +2381,18 @@ static void generate_random_aead_testvec(struct aead_request *req,
+       /* Key: length in [0, maxkeysize], but usually choose maxkeysize */
+       vec->klen = maxkeysize;
+-      if (prandom_u32_max(4) == 0)
+-              vec->klen = prandom_u32_max(maxkeysize + 1);
+-      generate_random_bytes((u8 *)vec->key, vec->klen);
++      if (prandom_u32_below(rng, 4) == 0)
++              vec->klen = prandom_u32_below(rng, maxkeysize + 1);
++      generate_random_bytes(rng, (u8 *)vec->key, vec->klen);
+       vec->setkey_error = crypto_aead_setkey(tfm, vec->key, vec->klen);
+       /* IV */
+-      generate_random_bytes((u8 *)vec->iv, ivsize);
++      generate_random_bytes(rng, (u8 *)vec->iv, ivsize);
+       /* Tag length: in [0, maxauthsize], but usually choose maxauthsize */
+       authsize = maxauthsize;
+-      if (prandom_u32_max(4) == 0)
+-              authsize = prandom_u32_max(maxauthsize + 1);
++      if (prandom_u32_below(rng, 4) == 0)
++              authsize = prandom_u32_below(rng, maxauthsize + 1);
+       if (prefer_inauthentic && authsize < MIN_COLLISION_FREE_AUTHSIZE)
+               authsize = MIN_COLLISION_FREE_AUTHSIZE;
+       if (WARN_ON(authsize > maxdatasize))
+@@ -2341,11 +2401,11 @@ static void generate_random_aead_testvec(struct aead_request *req,
+       vec->setauthsize_error = crypto_aead_setauthsize(tfm, authsize);
+       /* AAD, plaintext, and ciphertext lengths */
+-      total_len = generate_random_length(maxdatasize);
+-      if (prandom_u32_max(4) == 0)
++      total_len = generate_random_length(rng, maxdatasize);
++      if (prandom_u32_below(rng, 4) == 0)
+               vec->alen = 0;
+       else
+-              vec->alen = generate_random_length(total_len);
++              vec->alen = generate_random_length(rng, total_len);
+       vec->plen = total_len - vec->alen;
+       vec->clen = vec->plen + authsize;
+@@ -2356,7 +2416,7 @@ static void generate_random_aead_testvec(struct aead_request *req,
+       vec->novrfy = 0;
+       vec->crypt_error = 0;
+       if (vec->setkey_error == 0 && vec->setauthsize_error == 0)
+-              generate_aead_message(req, suite, vec, prefer_inauthentic);
++              generate_aead_message(rng, req, suite, vec, prefer_inauthentic);
+       snprintf(name, max_namelen,
+                "\"random: alen=%u plen=%u authsize=%u klen=%u novrfy=%d\"",
+                vec->alen, vec->plen, authsize, vec->klen, vec->novrfy);
+@@ -2368,7 +2428,7 @@ static void try_to_generate_inauthentic_testvec(
+       int i;
+       for (i = 0; i < 10; i++) {
+-              generate_random_aead_testvec(ctx->req, &ctx->vec,
++              generate_random_aead_testvec(&ctx->rng, ctx->req, &ctx->vec,
+                                            &ctx->test_desc->suite.aead,
+                                            ctx->maxkeysize, ctx->maxdatasize,
+                                            ctx->vec_name,
+@@ -2399,7 +2459,8 @@ static int test_aead_inauthentic_inputs(struct aead_extra_tests_ctx *ctx)
+                */
+               try_to_generate_inauthentic_testvec(ctx);
+               if (ctx->vec.novrfy) {
+-                      generate_random_testvec_config(&ctx->cfg, ctx->cfgname,
++                      generate_random_testvec_config(&ctx->rng, &ctx->cfg,
++                                                     ctx->cfgname,
+                                                      sizeof(ctx->cfgname));
+                       err = test_aead_vec_cfg(DECRYPT, &ctx->vec,
+                                               ctx->vec_name, &ctx->cfg,
+@@ -2489,12 +2550,13 @@ static int test_aead_vs_generic_impl(struct aead_extra_tests_ctx *ctx)
+        * the other implementation against them.
+        */
+       for (i = 0; i < fuzz_iterations * 8; i++) {
+-              generate_random_aead_testvec(generic_req, &ctx->vec,
++              generate_random_aead_testvec(&ctx->rng, generic_req, &ctx->vec,
+                                            &ctx->test_desc->suite.aead,
+                                            ctx->maxkeysize, ctx->maxdatasize,
+                                            ctx->vec_name,
+                                            sizeof(ctx->vec_name), false);
+-              generate_random_testvec_config(&ctx->cfg, ctx->cfgname,
++              generate_random_testvec_config(&ctx->rng, &ctx->cfg,
++                                             ctx->cfgname,
+                                              sizeof(ctx->cfgname));
+               if (!ctx->vec.novrfy) {
+                       err = test_aead_vec_cfg(ENCRYPT, &ctx->vec,
+@@ -2533,6 +2595,7 @@ static int test_aead_extra(const struct alg_test_desc *test_desc,
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
++      init_rnd_state(&ctx->rng);
+       ctx->req = req;
+       ctx->tfm = crypto_aead_reqtfm(req);
+       ctx->test_desc = test_desc;
+@@ -2922,11 +2985,14 @@ static int test_skcipher_vec(int enc, const struct cipher_testvec *vec,
+ #ifdef CONFIG_CRYPTO_MANAGER_EXTRA_TESTS
+       if (!noextratests) {
++              struct rnd_state rng;
+               struct testvec_config cfg;
+               char cfgname[TESTVEC_CONFIG_NAMELEN];
++              init_rnd_state(&rng);
++
+               for (i = 0; i < fuzz_iterations; i++) {
+-                      generate_random_testvec_config(&cfg, cfgname,
++                      generate_random_testvec_config(&rng, &cfg, cfgname,
+                                                      sizeof(cfgname));
+                       err = test_skcipher_vec_cfg(enc, vec, vec_name,
+                                                   &cfg, req, tsgls);
+@@ -2944,7 +3010,8 @@ static int test_skcipher_vec(int enc, const struct cipher_testvec *vec,
+  * Generate a symmetric cipher test vector from the given implementation.
+  * Assumes the buffers in 'vec' were already allocated.
+  */
+-static void generate_random_cipher_testvec(struct skcipher_request *req,
++static void generate_random_cipher_testvec(struct rnd_state *rng,
++                                         struct skcipher_request *req,
+                                          struct cipher_testvec *vec,
+                                          unsigned int maxdatasize,
+                                          char *name, size_t max_namelen)
+@@ -2958,17 +3025,17 @@ static void generate_random_cipher_testvec(struct skcipher_request *req,
+       /* Key: length in [0, maxkeysize], but usually choose maxkeysize */
+       vec->klen = maxkeysize;
+-      if (prandom_u32_max(4) == 0)
+-              vec->klen = prandom_u32_max(maxkeysize + 1);
+-      generate_random_bytes((u8 *)vec->key, vec->klen);
++      if (prandom_u32_below(rng, 4) == 0)
++              vec->klen = prandom_u32_below(rng, maxkeysize + 1);
++      generate_random_bytes(rng, (u8 *)vec->key, vec->klen);
+       vec->setkey_error = crypto_skcipher_setkey(tfm, vec->key, vec->klen);
+       /* IV */
+-      generate_random_bytes((u8 *)vec->iv, ivsize);
++      generate_random_bytes(rng, (u8 *)vec->iv, ivsize);
+       /* Plaintext */
+-      vec->len = generate_random_length(maxdatasize);
+-      generate_random_bytes((u8 *)vec->ptext, vec->len);
++      vec->len = generate_random_length(rng, maxdatasize);
++      generate_random_bytes(rng, (u8 *)vec->ptext, vec->len);
+       /* If the key couldn't be set, no need to continue to encrypt. */
+       if (vec->setkey_error)
+@@ -3010,6 +3077,7 @@ static int test_skcipher_vs_generic_impl(const char *generic_driver,
+       const unsigned int maxdatasize = (2 * PAGE_SIZE) - TESTMGR_POISON_LEN;
+       const char *algname = crypto_skcipher_alg(tfm)->base.cra_name;
+       const char *driver = crypto_skcipher_driver_name(tfm);
++      struct rnd_state rng;
+       char _generic_driver[CRYPTO_MAX_ALG_NAME];
+       struct crypto_skcipher *generic_tfm = NULL;
+       struct skcipher_request *generic_req = NULL;
+@@ -3027,6 +3095,8 @@ static int test_skcipher_vs_generic_impl(const char *generic_driver,
+       if (strncmp(algname, "kw(", 3) == 0)
+               return 0;
++      init_rnd_state(&rng);
++
+       if (!generic_driver) { /* Use default naming convention? */
+               err = build_generic_driver_name(algname, _generic_driver);
+               if (err)
+@@ -3111,9 +3181,11 @@ static int test_skcipher_vs_generic_impl(const char *generic_driver,
+       }
+       for (i = 0; i < fuzz_iterations * 8; i++) {
+-              generate_random_cipher_testvec(generic_req, &vec, maxdatasize,
++              generate_random_cipher_testvec(&rng, generic_req, &vec,
++                                             maxdatasize,
+                                              vec_name, sizeof(vec_name));
+-              generate_random_testvec_config(cfg, cfgname, sizeof(cfgname));
++              generate_random_testvec_config(&rng, cfg, cfgname,
++                                             sizeof(cfgname));
+               err = test_skcipher_vec_cfg(ENCRYPT, &vec, vec_name,
+                                           cfg, req, tsgls);
+-- 
+2.39.2
+
diff --git a/queue-6.1/remoteproc-imx_dsp_rproc-fix-kernel-test-robot-spars.patch b/queue-6.1/remoteproc-imx_dsp_rproc-fix-kernel-test-robot-spars.patch
new file mode 100644 (file)
index 0000000..af55c6b
--- /dev/null
@@ -0,0 +1,64 @@
+From a9358990aba9f248bb91ee58d28e7979d06b22e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Apr 2023 10:14:29 -0600
+Subject: remoteproc: imx_dsp_rproc: Fix kernel test robot sparse warning
+
+From: Mathieu Poirier <mathieu.poirier@linaro.org>
+
+[ Upstream commit 3c497f624d40171ebead1a6705793100d92ecb85 ]
+
+This patch fixes the kernel test robot warning reported here:
+
+https://lore.kernel.org/bpf/642f916b.pPIKZ%2Fl%2F%2Fbw8tvIH%25lkp@intel.com/T/
+
+Fixes: 408ec1ff0caa ("remoteproc: imx_dsp_rproc: Add custom memory copy implementation for i.MX DSP Cores")
+Link: https://lore.kernel.org/r/20230407161429.3973177-1-mathieu.poirier@linaro.org
+Tested-by: Iuliana Prodan <iuliana.prodan@nxp.com>
+Reviewed-by: Iuliana Prodan <iuliana.prodan@nxp.com>
+Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/remoteproc/imx_dsp_rproc.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
+index e8e23f6b85563..dcd07a6a5e945 100644
+--- a/drivers/remoteproc/imx_dsp_rproc.c
++++ b/drivers/remoteproc/imx_dsp_rproc.c
+@@ -727,12 +727,12 @@ static void imx_dsp_rproc_kick(struct rproc *rproc, int vqid)
+  * The IRAM is part of the HiFi DSP.
+  * According to hw specs only 32-bits writes are allowed.
+  */
+-static int imx_dsp_rproc_memcpy(void *dest, const void *src, size_t size)
++static int imx_dsp_rproc_memcpy(void *dst, const void *src, size_t size)
+ {
++      void __iomem *dest = (void __iomem *)dst;
+       const u8 *src_byte = src;
+       const u32 *source = src;
+       u32 affected_mask;
+-      u32 *dst = dest;
+       int i, q, r;
+       u32 tmp;
+@@ -745,7 +745,7 @@ static int imx_dsp_rproc_memcpy(void *dest, const void *src, size_t size)
+       /* copy data in units of 32 bits at a time */
+       for (i = 0; i < q; i++)
+-              writel(source[i], &dst[i]);
++              writel(source[i], dest + i * 4);
+       if (r) {
+               affected_mask = GENMASK(8 * r, 0);
+@@ -776,8 +776,8 @@ static int imx_dsp_rproc_memcpy(void *dest, const void *src, size_t size)
+  */
+ static int imx_dsp_rproc_memset(void *addr, u8 value, size_t size)
+ {
++      void __iomem *tmp_dst = (void __iomem *)addr;
+       u32 tmp_val = value;
+-      u32 *tmp_dst = addr;
+       u32 affected_mask;
+       int q, r;
+       u32 tmp;
+-- 
+2.39.2
+
index 809250bbaea3d1d74d54d7b3712acc95e9351bfc..636c107e428130ac5d09199a33c93eaf1fcae11c 100644 (file)
@@ -285,3 +285,5 @@ s390-qdio-fix-do_sqbs-inline-assembly-constraint.patch
 arm64-mte-do-not-set-pg_mte_tagged-if-tags-were-not-initialized.patch
 rethook-use-preempt_-disable-enable-_notrace-in-rethook_trampoline_handler.patch
 rethook-fprobe-do-not-trace-rethook-related-functions.patch
+remoteproc-imx_dsp_rproc-fix-kernel-test-robot-spars.patch
+crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch