]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.3-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 6 May 2023 02:34:12 +0000 (11:34 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 6 May 2023 02:34:12 +0000 (11:34 +0900)
added patches:
cpufreq-qcom-cpufreq-hw-fix-double-io-unmap-and-resource-release-on-exit.patch
crypto-api-demote-bug_on-in-crypto_unregister_alg-to-a-warn_on.patch
crypto-arm64-aes-neonbs-fix-crash-with-cfi-enabled.patch
crypto-ccp-don-t-initialize-ccp-for-psp-0x1649.patch
crypto-safexcel-cleanup-ring-irq-workqueues-on-load-failure.patch
crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch
kvm-arm64-avoid-lock-inversion-when-setting-the-vm-register-width.patch
kvm-arm64-avoid-vcpu-mutex-v.-kvm-lock-inversion-in-cpu_on.patch
kvm-arm64-use-config_lock-to-protect-data-ordered-against-kvm_run.patch
kvm-arm64-use-config_lock-to-protect-vgic-state.patch
kvm-arm64-vgic-don-t-acquire-its_lock-before-config_lock.patch
kvm-nvmx-emulate-nops-in-l2-and-pause-if-it-s-not-intercepted.patch
kvm-x86-pmu-disallow-legacy-lbrs-if-architectural-lbrs-are-available.patch
pinctrl-qcom-lpass-lpi-set-output-value-before-enabling-output.patch
pwm-meson-fix-axg-ao-mux-parents.patch
pwm-meson-fix-g12a-ao-clk81-name.patch
rcu-avoid-stack-overflow-due-to-__rcu_irq_enter_check_tick-being-kprobe-ed.patch
reiserfs-add-security-prefix-to-xattr-name-in-reiserfs_security_write.patch
relayfs-fix-out-of-bounds-access-in-relay_file_read.patch
ring-buffer-ensure-proper-resetting-of-atomic-variables-in-ring_buffer_reset_online_cpus.patch
ring-buffer-sync-irq-works-before-buffer-destruction.patch
soundwire-qcom-correct-setting-ignore-bit-on-v1.5.1.patch

23 files changed:
queue-6.3/cpufreq-qcom-cpufreq-hw-fix-double-io-unmap-and-resource-release-on-exit.patch [new file with mode: 0644]
queue-6.3/crypto-api-demote-bug_on-in-crypto_unregister_alg-to-a-warn_on.patch [new file with mode: 0644]
queue-6.3/crypto-arm64-aes-neonbs-fix-crash-with-cfi-enabled.patch [new file with mode: 0644]
queue-6.3/crypto-ccp-don-t-initialize-ccp-for-psp-0x1649.patch [new file with mode: 0644]
queue-6.3/crypto-safexcel-cleanup-ring-irq-workqueues-on-load-failure.patch [new file with mode: 0644]
queue-6.3/crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch [new file with mode: 0644]
queue-6.3/kvm-arm64-avoid-lock-inversion-when-setting-the-vm-register-width.patch [new file with mode: 0644]
queue-6.3/kvm-arm64-avoid-vcpu-mutex-v.-kvm-lock-inversion-in-cpu_on.patch [new file with mode: 0644]
queue-6.3/kvm-arm64-use-config_lock-to-protect-data-ordered-against-kvm_run.patch [new file with mode: 0644]
queue-6.3/kvm-arm64-use-config_lock-to-protect-vgic-state.patch [new file with mode: 0644]
queue-6.3/kvm-arm64-vgic-don-t-acquire-its_lock-before-config_lock.patch [new file with mode: 0644]
queue-6.3/kvm-nvmx-emulate-nops-in-l2-and-pause-if-it-s-not-intercepted.patch [new file with mode: 0644]
queue-6.3/kvm-x86-pmu-disallow-legacy-lbrs-if-architectural-lbrs-are-available.patch [new file with mode: 0644]
queue-6.3/pinctrl-qcom-lpass-lpi-set-output-value-before-enabling-output.patch [new file with mode: 0644]
queue-6.3/pwm-meson-fix-axg-ao-mux-parents.patch [new file with mode: 0644]
queue-6.3/pwm-meson-fix-g12a-ao-clk81-name.patch [new file with mode: 0644]
queue-6.3/rcu-avoid-stack-overflow-due-to-__rcu_irq_enter_check_tick-being-kprobe-ed.patch [new file with mode: 0644]
queue-6.3/reiserfs-add-security-prefix-to-xattr-name-in-reiserfs_security_write.patch [new file with mode: 0644]
queue-6.3/relayfs-fix-out-of-bounds-access-in-relay_file_read.patch [new file with mode: 0644]
queue-6.3/ring-buffer-ensure-proper-resetting-of-atomic-variables-in-ring_buffer_reset_online_cpus.patch [new file with mode: 0644]
queue-6.3/ring-buffer-sync-irq-works-before-buffer-destruction.patch [new file with mode: 0644]
queue-6.3/series
queue-6.3/soundwire-qcom-correct-setting-ignore-bit-on-v1.5.1.patch [new file with mode: 0644]

diff --git a/queue-6.3/cpufreq-qcom-cpufreq-hw-fix-double-io-unmap-and-resource-release-on-exit.patch b/queue-6.3/cpufreq-qcom-cpufreq-hw-fix-double-io-unmap-and-resource-release-on-exit.patch
new file mode 100644 (file)
index 0000000..f1e4b28
--- /dev/null
@@ -0,0 +1,101 @@
+From ba5e770c9698782bc203bbf5cf3b36a77720bdbe Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Date: Thu, 23 Mar 2023 18:40:26 +0100
+Subject: cpufreq: qcom-cpufreq-hw: fix double IO unmap and resource release on exit
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+commit ba5e770c9698782bc203bbf5cf3b36a77720bdbe upstream.
+
+Commit 054a3ef683a1 ("cpufreq: qcom-hw: Allocate qcom_cpufreq_data
+during probe") moved getting memory resource and iomap from
+qcom_cpufreq_hw_cpu_init() to the probe function, however it left
+untouched cleanup in qcom_cpufreq_hw_cpu_exit().
+
+During device unbind this will lead to doule release of resource and
+double iounmap(), first by qcom_cpufreq_hw_cpu_exit() and second via
+managed resources:
+
+  resource: Trying to free nonexistent resource <0x0000000018593000-0x0000000018593fff>
+  Trying to vunmap() nonexistent vm area (0000000088a7d4dc)
+  ...
+  vunmap (mm/vmalloc.c:2771 (discriminator 1))
+  iounmap (mm/ioremap.c:60)
+  devm_ioremap_release (lib/devres.c:19)
+  devres_release_all (drivers/base/devres.c:506 drivers/base/devres.c:535)
+  device_unbind_cleanup (drivers/base/dd.c:523)
+  device_release_driver_internal (drivers/base/dd.c:1248 drivers/base/dd.c:1263)
+  device_driver_detach (drivers/base/dd.c:1300)
+  unbind_store (drivers/base/bus.c:243)
+  drv_attr_store (drivers/base/bus.c:127)
+  sysfs_kf_write (fs/sysfs/file.c:137)
+  kernfs_fop_write_iter (fs/kernfs/file.c:334)
+  vfs_write (include/linux/fs.h:1851 fs/read_write.c:491 fs/read_write.c:584)
+  ksys_write (fs/read_write.c:637)
+  __arm64_sys_write (fs/read_write.c:646)
+  invoke_syscall (arch/arm64/include/asm/current.h:19 arch/arm64/kernel/syscall.c:57)
+  el0_svc_common.constprop.0 (arch/arm64/include/asm/daifflags.h:28 arch/arm64/kernel/syscall.c:150)
+  do_el0_svc (arch/arm64/kernel/syscall.c:194)
+  el0_svc (arch/arm64/include/asm/daifflags.h:28 arch/arm64/kernel/entry-common.c:133 arch/arm64/kernel/entry-common.c:142 arch/arm64/kernel/entry-common.c:638)
+  el0t_64_sync_handler (arch/arm64/kernel/entry-common.c:656)
+  el0t_64_sync (arch/arm64/kernel/entry.S:591)
+
+Fixes: 054a3ef683a1 ("cpufreq: qcom-hw: Allocate qcom_cpufreq_data during probe")
+Cc: <stable@vger.kernel.org>
+Cc: Manivannan Sadhasivam <mani@kernel.org>
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
+Reviewed-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/cpufreq/qcom-cpufreq-hw.c |   11 ++---------
+ 1 file changed, 2 insertions(+), 9 deletions(-)
+
+--- a/drivers/cpufreq/qcom-cpufreq-hw.c
++++ b/drivers/cpufreq/qcom-cpufreq-hw.c
+@@ -43,7 +43,6 @@ struct qcom_cpufreq_soc_data {
+ struct qcom_cpufreq_data {
+       void __iomem *base;
+-      struct resource *res;
+       /*
+        * Mutex to synchronize between de-init sequence and re-starting LMh
+@@ -590,16 +589,12 @@ static int qcom_cpufreq_hw_cpu_exit(stru
+ {
+       struct device *cpu_dev = get_cpu_device(policy->cpu);
+       struct qcom_cpufreq_data *data = policy->driver_data;
+-      struct resource *res = data->res;
+-      void __iomem *base = data->base;
+       dev_pm_opp_remove_all_dynamic(cpu_dev);
+       dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
+       qcom_cpufreq_hw_lmh_exit(data);
+       kfree(policy->freq_table);
+       kfree(data);
+-      iounmap(base);
+-      release_mem_region(res->start, resource_size(res));
+       return 0;
+ }
+@@ -718,17 +713,15 @@ static int qcom_cpufreq_hw_driver_probe(
+       for (i = 0; i < num_domains; i++) {
+               struct qcom_cpufreq_data *data = &qcom_cpufreq.data[i];
+               struct clk_init_data clk_init = {};
+-              struct resource *res;
+               void __iomem *base;
+-              base = devm_platform_get_and_ioremap_resource(pdev, i, &res);
++              base = devm_platform_ioremap_resource(pdev, i);
+               if (IS_ERR(base)) {
+-                      dev_err(dev, "Failed to map resource %pR\n", res);
++                      dev_err(dev, "Failed to map resource index %d\n", i);
+                       return PTR_ERR(base);
+               }
+               data->base = base;
+-              data->res = res;
+               /* Register CPU clock for each frequency domain */
+               clk_init.name = kasprintf(GFP_KERNEL, "qcom_cpufreq%d", i);
diff --git a/queue-6.3/crypto-api-demote-bug_on-in-crypto_unregister_alg-to-a-warn_on.patch b/queue-6.3/crypto-api-demote-bug_on-in-crypto_unregister_alg-to-a-warn_on.patch
new file mode 100644 (file)
index 0000000..79c83b2
--- /dev/null
@@ -0,0 +1,45 @@
+From a543ada7db729514ddd3ba4efa45f4c7b802ad85 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@redhat.com>
+Date: Mon, 13 Mar 2023 10:17:24 +0100
+Subject: crypto: api - Demote BUG_ON() in crypto_unregister_alg() to a WARN_ON()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Toke Høiland-Jørgensen <toke@redhat.com>
+
+commit a543ada7db729514ddd3ba4efa45f4c7b802ad85 upstream.
+
+The crypto_unregister_alg() function expects callers to ensure that any
+algorithm that is unregistered has a refcnt of exactly 1, and issues a
+BUG_ON() if this is not the case. However, there are in fact drivers that
+will call crypto_unregister_alg() without ensuring that the refcnt has been
+lowered first, most notably on system shutdown. This causes the BUG_ON() to
+trigger, which prevents a clean shutdown and hangs the system.
+
+To avoid such hangs on shutdown, demote the BUG_ON() in
+crypto_unregister_alg() to a WARN_ON() with early return. Cc stable because
+this problem was observed on a 6.2 kernel, cf the link below.
+
+Link: https://lore.kernel.org/r/87r0tyq8ph.fsf@toke.dk
+Cc: stable@vger.kernel.org
+Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ crypto/algapi.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/crypto/algapi.c
++++ b/crypto/algapi.c
+@@ -493,7 +493,9 @@ void crypto_unregister_alg(struct crypto
+       if (WARN(ret, "Algorithm %s is not registered", alg->cra_driver_name))
+               return;
+-      BUG_ON(refcount_read(&alg->cra_refcnt) != 1);
++      if (WARN_ON(refcount_read(&alg->cra_refcnt) != 1))
++              return;
++
+       if (alg->cra_destroy)
+               alg->cra_destroy(alg);
diff --git a/queue-6.3/crypto-arm64-aes-neonbs-fix-crash-with-cfi-enabled.patch b/queue-6.3/crypto-arm64-aes-neonbs-fix-crash-with-cfi-enabled.patch
new file mode 100644 (file)
index 0000000..f8e3fa9
--- /dev/null
@@ -0,0 +1,65 @@
+From 47446d7cd42358ca7d7a544f2f7823db03f616ff Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Sun, 26 Feb 2023 22:32:23 -0800
+Subject: crypto: arm64/aes-neonbs - fix crash with CFI enabled
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 47446d7cd42358ca7d7a544f2f7823db03f616ff upstream.
+
+aesbs_ecb_encrypt(), aesbs_ecb_decrypt(), aesbs_xts_encrypt(), and
+aesbs_xts_decrypt() are called via indirect function calls.  Therefore
+they need to use SYM_TYPED_FUNC_START instead of SYM_FUNC_START to cause
+their type hashes to be emitted when the kernel is built with
+CONFIG_CFI_CLANG=y.  Otherwise, the code crashes with a CFI failure if
+the compiler doesn't happen to optimize out the indirect calls.
+
+Fixes: c50d32859e70 ("arm64: Add types to indirect called assembly functions")
+Cc: stable@vger.kernel.org
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/crypto/aes-neonbs-core.S |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/arch/arm64/crypto/aes-neonbs-core.S
++++ b/arch/arm64/crypto/aes-neonbs-core.S
+@@ -15,6 +15,7 @@
+  */
+ #include <linux/linkage.h>
++#include <linux/cfi_types.h>
+ #include <asm/assembler.h>
+       .text
+@@ -620,12 +621,12 @@ SYM_FUNC_END(aesbs_decrypt8)
+       .endm
+       .align          4
+-SYM_FUNC_START(aesbs_ecb_encrypt)
++SYM_TYPED_FUNC_START(aesbs_ecb_encrypt)
+       __ecb_crypt     aesbs_encrypt8, v0, v1, v4, v6, v3, v7, v2, v5
+ SYM_FUNC_END(aesbs_ecb_encrypt)
+       .align          4
+-SYM_FUNC_START(aesbs_ecb_decrypt)
++SYM_TYPED_FUNC_START(aesbs_ecb_decrypt)
+       __ecb_crypt     aesbs_decrypt8, v0, v1, v6, v4, v2, v7, v3, v5
+ SYM_FUNC_END(aesbs_ecb_decrypt)
+@@ -799,11 +800,11 @@ SYM_FUNC_END(__xts_crypt8)
+       ret
+       .endm
+-SYM_FUNC_START(aesbs_xts_encrypt)
++SYM_TYPED_FUNC_START(aesbs_xts_encrypt)
+       __xts_crypt     aesbs_encrypt8, v0, v1, v4, v6, v3, v7, v2, v5
+ SYM_FUNC_END(aesbs_xts_encrypt)
+-SYM_FUNC_START(aesbs_xts_decrypt)
++SYM_TYPED_FUNC_START(aesbs_xts_decrypt)
+       __xts_crypt     aesbs_decrypt8, v0, v1, v6, v4, v2, v7, v3, v5
+ SYM_FUNC_END(aesbs_xts_decrypt)
diff --git a/queue-6.3/crypto-ccp-don-t-initialize-ccp-for-psp-0x1649.patch b/queue-6.3/crypto-ccp-don-t-initialize-ccp-for-psp-0x1649.patch
new file mode 100644 (file)
index 0000000..9e6093d
--- /dev/null
@@ -0,0 +1,37 @@
+From c79a3169b9f3633c215b55857eba5921e5b49217 Mon Sep 17 00:00:00 2001
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Mon, 3 Apr 2023 12:38:01 -0500
+Subject: crypto: ccp - Don't initialize CCP for PSP 0x1649
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+commit c79a3169b9f3633c215b55857eba5921e5b49217 upstream.
+
+A number of platforms are emitting the error:
+```ccp: unable to access the device: you might be running a broken BIOS.```
+
+This is expected behavior as CCP is no longer accessible from the PSP's
+PCIe BAR so stop trying to probe CCP for 0x1649.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/ccp/sp-pci.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/crypto/ccp/sp-pci.c
++++ b/drivers/crypto/ccp/sp-pci.c
+@@ -451,9 +451,9 @@ static const struct pci_device_id sp_pci
+       { PCI_VDEVICE(AMD, 0x1468), (kernel_ulong_t)&dev_vdata[2] },
+       { PCI_VDEVICE(AMD, 0x1486), (kernel_ulong_t)&dev_vdata[3] },
+       { PCI_VDEVICE(AMD, 0x15DF), (kernel_ulong_t)&dev_vdata[4] },
+-      { PCI_VDEVICE(AMD, 0x1649), (kernel_ulong_t)&dev_vdata[4] },
+       { PCI_VDEVICE(AMD, 0x14CA), (kernel_ulong_t)&dev_vdata[5] },
+       { PCI_VDEVICE(AMD, 0x15C7), (kernel_ulong_t)&dev_vdata[6] },
++      { PCI_VDEVICE(AMD, 0x1649), (kernel_ulong_t)&dev_vdata[6] },
+       /* Last entry must be zero */
+       { 0, }
+ };
diff --git a/queue-6.3/crypto-safexcel-cleanup-ring-irq-workqueues-on-load-failure.patch b/queue-6.3/crypto-safexcel-cleanup-ring-irq-workqueues-on-load-failure.patch
new file mode 100644 (file)
index 0000000..48eb6f8
--- /dev/null
@@ -0,0 +1,154 @@
+From ca25c00ccbc5f942c63897ed23584cfc66e8ec81 Mon Sep 17 00:00:00 2001
+From: Jonathan McDowell <noodles@earth.li>
+Date: Tue, 28 Feb 2023 18:28:58 +0000
+Subject: crypto: safexcel - Cleanup ring IRQ workqueues on load failure
+
+From: Jonathan McDowell <noodles@earth.li>
+
+commit ca25c00ccbc5f942c63897ed23584cfc66e8ec81 upstream.
+
+A failure loading the safexcel driver results in the following warning
+on boot, because the IRQ affinity has not been correctly cleaned up.
+Ensure we clean up the affinity and workqueues on a failure to load the
+driver.
+
+crypto-safexcel: probe of f2800000.crypto failed with error -2
+------------[ cut here ]------------
+WARNING: CPU: 1 PID: 232 at kernel/irq/manage.c:1913 free_irq+0x300/0x340
+Modules linked in: hwmon mdio_i2c crypto_safexcel(+) md5 sha256_generic libsha256 authenc libdes omap_rng rng_core nft_masq nft_nat nft_chain_nat nf_nat nft_ct nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables libcrc32c nfnetlink fuse autofs4
+CPU: 1 PID: 232 Comm: systemd-udevd Tainted: G        W          6.1.6-00002-g9d4898824677 #3
+Hardware name: MikroTik RB5009 (DT)
+pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+pc : free_irq+0x300/0x340
+lr : free_irq+0x2e0/0x340
+sp : ffff800008fa3890
+x29: ffff800008fa3890 x28: 0000000000000000 x27: 0000000000000000
+x26: ffff8000008e6dc0 x25: ffff000009034cac x24: ffff000009034d50
+x23: 0000000000000000 x22: 000000000000004a x21: ffff0000093e0d80
+x20: ffff000009034c00 x19: ffff00000615fc00 x18: 0000000000000000
+x17: 0000000000000000 x16: 0000000000000000 x15: 000075f5c1584c5e
+x14: 0000000000000017 x13: 0000000000000000 x12: 0000000000000040
+x11: ffff000000579b60 x10: ffff000000579b62 x9 : ffff800008bbe370
+x8 : ffff000000579dd0 x7 : 0000000000000000 x6 : ffff000000579e18
+x5 : ffff000000579da8 x4 : ffff800008ca0000 x3 : ffff800008ca0188
+x2 : 0000000013033204 x1 : ffff000009034c00 x0 : ffff8000087eadf0
+Call trace:
+ free_irq+0x300/0x340
+ devm_irq_release+0x14/0x20
+ devres_release_all+0xa0/0x100
+ device_unbind_cleanup+0x14/0x60
+ really_probe+0x198/0x2d4
+ __driver_probe_device+0x74/0xdc
+ driver_probe_device+0x3c/0x110
+ __driver_attach+0x8c/0x190
+ bus_for_each_dev+0x6c/0xc0
+ driver_attach+0x20/0x30
+ bus_add_driver+0x148/0x1fc
+ driver_register+0x74/0x120
+ __platform_driver_register+0x24/0x30
+ safexcel_init+0x48/0x1000 [crypto_safexcel]
+ do_one_initcall+0x4c/0x1b0
+ do_init_module+0x44/0x1cc
+ load_module+0x1724/0x1be4
+ __do_sys_finit_module+0xbc/0x110
+ __arm64_sys_finit_module+0x1c/0x24
+ invoke_syscall+0x44/0x110
+ el0_svc_common.constprop.0+0xc0/0xe0
+ do_el0_svc+0x20/0x80
+ el0_svc+0x14/0x4c
+ el0t_64_sync_handler+0xb0/0xb4
+ el0t_64_sync+0x148/0x14c
+---[ end trace 0000000000000000 ]---
+
+Fixes: 1b44c5a60c13 ("inside-secure - add SafeXcel EIP197 crypto engine driver")
+Signed-off-by: Jonathan McDowell <noodles@earth.li>
+Cc: stable@vger.kernel.org
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/inside-secure/safexcel.c |   37 +++++++++++++++++++++++---------
+ 1 file changed, 27 insertions(+), 10 deletions(-)
+
+--- a/drivers/crypto/inside-secure/safexcel.c
++++ b/drivers/crypto/inside-secure/safexcel.c
+@@ -1628,19 +1628,23 @@ static int safexcel_probe_generic(void *
+                                                    &priv->ring[i].rdr);
+               if (ret) {
+                       dev_err(dev, "Failed to initialize rings\n");
+-                      return ret;
++                      goto err_cleanup_rings;
+               }
+               priv->ring[i].rdr_req = devm_kcalloc(dev,
+                       EIP197_DEFAULT_RING_SIZE,
+                       sizeof(*priv->ring[i].rdr_req),
+                       GFP_KERNEL);
+-              if (!priv->ring[i].rdr_req)
+-                      return -ENOMEM;
++              if (!priv->ring[i].rdr_req) {
++                      ret = -ENOMEM;
++                      goto err_cleanup_rings;
++              }
+               ring_irq = devm_kzalloc(dev, sizeof(*ring_irq), GFP_KERNEL);
+-              if (!ring_irq)
+-                      return -ENOMEM;
++              if (!ring_irq) {
++                      ret = -ENOMEM;
++                      goto err_cleanup_rings;
++              }
+               ring_irq->priv = priv;
+               ring_irq->ring = i;
+@@ -1654,7 +1658,8 @@ static int safexcel_probe_generic(void *
+                                               ring_irq);
+               if (irq < 0) {
+                       dev_err(dev, "Failed to get IRQ ID for ring %d\n", i);
+-                      return irq;
++                      ret = irq;
++                      goto err_cleanup_rings;
+               }
+               priv->ring[i].irq = irq;
+@@ -1666,8 +1671,10 @@ static int safexcel_probe_generic(void *
+               snprintf(wq_name, 9, "wq_ring%d", i);
+               priv->ring[i].workqueue =
+                       create_singlethread_workqueue(wq_name);
+-              if (!priv->ring[i].workqueue)
+-                      return -ENOMEM;
++              if (!priv->ring[i].workqueue) {
++                      ret = -ENOMEM;
++                      goto err_cleanup_rings;
++              }
+               priv->ring[i].requests = 0;
+               priv->ring[i].busy = false;
+@@ -1684,16 +1691,26 @@ static int safexcel_probe_generic(void *
+       ret = safexcel_hw_init(priv);
+       if (ret) {
+               dev_err(dev, "HW init failed (%d)\n", ret);
+-              return ret;
++              goto err_cleanup_rings;
+       }
+       ret = safexcel_register_algorithms(priv);
+       if (ret) {
+               dev_err(dev, "Failed to register algorithms (%d)\n", ret);
+-              return ret;
++              goto err_cleanup_rings;
+       }
+       return 0;
++
++err_cleanup_rings:
++      for (i = 0; i < priv->config.rings; i++) {
++              if (priv->ring[i].irq)
++                      irq_set_affinity_hint(priv->ring[i].irq, NULL);
++              if (priv->ring[i].workqueue)
++                      destroy_workqueue(priv->ring[i].workqueue);
++      }
++
++      return ret;
+ }
+ static void safexcel_hw_reset_rings(struct safexcel_crypto_priv *priv)
diff --git a/queue-6.3/crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch b/queue-6.3/crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch
new file mode 100644 (file)
index 0000000..9ae24ab
--- /dev/null
@@ -0,0 +1,712 @@
+From f900fde28883602b6c5e1027a6c912b673382aaf Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Mon, 27 Feb 2023 10:29:47 -0800
+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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ crypto/testmgr.c |  266 ++++++++++++++++++++++++++++++++++---------------------
+ 1 file changed, 169 insertions(+), 97 deletions(-)
+
+--- a/crypto/testmgr.c
++++ b/crypto/testmgr.c
+@@ -860,12 +860,50 @@ static int prepare_keybuf(const u8 *key,
+ #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 = get_random_u32_below(max_len + 1);
++      unsigned int len = prandom_u32_below(rng, max_len + 1);
+-      switch (get_random_u32_below(4)) {
++      switch (prandom_u32_below(rng, 4)) {
+       case 0:
+               return len % 64;
+       case 1:
+@@ -878,43 +916,44 @@ static unsigned int generate_random_leng
+ }
+ /* 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 = get_random_u32_below(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[get_random_u32_below(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 (get_random_u32_below(4) == 0) {
+-              num_flips = min_t(size_t, 1 << get_random_u32_below(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 (get_random_u32_below(4) == 0) {
+-              num_flips = min_t(size_t, 1 << get_random_u32_below(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;
+@@ -923,11 +962,11 @@ static void generate_random_bytes(u8 *bu
+       if (count == 0)
+               return;
+-      switch (get_random_u32_below(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 (get_random_u32_below(4)) {
++              switch (prandom_u32_below(rng, 4)) {
+               case 0:
+                       b = 0x00;
+                       break;
+@@ -935,28 +974,28 @@ static void generate_random_bytes(u8 *bu
+                       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)
+ {
+@@ -967,24 +1006,26 @@ static char *generate_random_sgl_divisio
+               unsigned int this_len;
+               const char *flushtype_str;
+-              if (div == &divs[max_divs - 1] || get_random_u32_below(2) == 0)
++              if (div == &divs[max_divs - 1] || prandom_bool(rng))
+                       this_len = remaining;
+               else
+-                      this_len = get_random_u32_inclusive(1, remaining);
++                      this_len = prandom_u32_inclusive(rng, 1, remaining);
+               div->proportion_of_total = this_len;
+-              if (get_random_u32_below(4) == 0)
+-                      div->offset = get_random_u32_inclusive(PAGE_SIZE - 128, PAGE_SIZE - 1);
+-              else if (get_random_u32_below(2) == 0)
+-                      div->offset = get_random_u32_below(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 = get_random_u32_below(PAGE_SIZE);
+-              if (get_random_u32_below(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 (get_random_u32_below(4)) {
++                      switch (prandom_u32_below(rng, 4)) {
+                       case 0:
+                               div->flush_type = FLUSH_TYPE_REIMPORT;
+                               break;
+@@ -996,7 +1037,7 @@ static char *generate_random_sgl_divisio
+               if (div->flush_type != FLUSH_TYPE_NONE &&
+                   !(req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) &&
+-                  get_random_u32_below(2) == 0)
++                  prandom_bool(rng))
+                       div->nosimd = true;
+               switch (div->flush_type) {
+@@ -1031,7 +1072,8 @@ static char *generate_random_sgl_divisio
+ }
+ /* 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;
+@@ -1043,7 +1085,7 @@ static void generate_random_testvec_conf
+       p += scnprintf(p, end - p, "random:");
+-      switch (get_random_u32_below(4)) {
++      switch (prandom_u32_below(rng, 4)) {
+       case 0:
+       case 1:
+               cfg->inplace_mode = OUT_OF_PLACE;
+@@ -1058,12 +1100,12 @@ static void generate_random_testvec_conf
+               break;
+       }
+-      if (get_random_u32_below(2) == 0) {
++      if (prandom_bool(rng)) {
+               cfg->req_flags |= CRYPTO_TFM_REQ_MAY_SLEEP;
+               p += scnprintf(p, end - p, " may_sleep");
+       }
+-      switch (get_random_u32_below(4)) {
++      switch (prandom_u32_below(rng, 4)) {
+       case 0:
+               cfg->finalization_type = FINALIZATION_TYPE_FINAL;
+               p += scnprintf(p, end - p, " use_final");
+@@ -1078,36 +1120,37 @@ static void generate_random_testvec_conf
+               break;
+       }
+-      if (!(cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) &&
+-          get_random_u32_below(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 && get_random_u32_below(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 (get_random_u32_below(2) == 0) {
+-              cfg->iv_offset = get_random_u32_inclusive(1, 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 (get_random_u32_below(2) == 0) {
+-              cfg->key_offset = get_random_u32_inclusive(1, 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);
+       }
+@@ -1620,11 +1663,14 @@ static int test_hash_vec(const struct ha
+ #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);
+@@ -1642,15 +1688,16 @@ static int test_hash_vec(const struct ha
+  * 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.
+@@ -1660,9 +1707,9 @@ static void generate_random_hash_testvec
+       vec->ksize = 0;
+       if (maxkeysize) {
+               vec->ksize = maxkeysize;
+-              if (get_random_u32_below(4) == 0)
+-                      vec->ksize = get_random_u32_inclusive(1, 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);
+@@ -1696,6 +1743,7 @@ static int test_hash_vs_generic_impl(con
+       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;
+@@ -1709,6 +1757,8 @@ static int test_hash_vs_generic_impl(con
+       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)
+@@ -1777,10 +1827,11 @@ static int test_hash_vs_generic_impl(con
+       }
+       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);
+@@ -2182,11 +2233,14 @@ static int test_aead_vec(int enc, const
+ #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);
+@@ -2202,6 +2256,7 @@ static int test_aead_vec(int enc, const
+ #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;
+@@ -2220,24 +2275,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 (get_random_u32_below(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 (get_random_u32_below(2) == 0)
++              flip_random_bit(rng, (u8 *)vec->assoc,
++                              vec->alen - aad_tail_size);
++              if (prandom_bool(rng))
+                       return;
+       }
+-      if (get_random_u32_below(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);
+       }
+ }
+@@ -2248,7 +2305,8 @@ static void mutate_aead_message(struct a
+  */
+ #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)
+@@ -2257,17 +2315,18 @@ static void generate_aead_message(struct
+       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 || get_random_u32_below(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 && get_random_u32_below(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;
+@@ -2279,7 +2338,7 @@ static void generate_aead_message(struct
+               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);
+@@ -2299,7 +2358,7 @@ static void generate_aead_message(struct
+                * 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)
+@@ -2313,7 +2372,8 @@ static void generate_aead_message(struct
+  * 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,
+@@ -2329,18 +2389,18 @@ static void generate_random_aead_testvec
+       /* Key: length in [0, maxkeysize], but usually choose maxkeysize */
+       vec->klen = maxkeysize;
+-      if (get_random_u32_below(4) == 0)
+-              vec->klen = get_random_u32_below(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 (get_random_u32_below(4) == 0)
+-              authsize = get_random_u32_below(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))
+@@ -2349,11 +2409,11 @@ static void generate_random_aead_testvec
+       vec->setauthsize_error = crypto_aead_setauthsize(tfm, authsize);
+       /* AAD, plaintext, and ciphertext lengths */
+-      total_len = generate_random_length(maxdatasize);
+-      if (get_random_u32_below(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;
+@@ -2364,7 +2424,7 @@ static void generate_random_aead_testvec
+       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);
+@@ -2376,7 +2436,7 @@ static void try_to_generate_inauthentic_
+       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,
+@@ -2407,7 +2467,8 @@ static int test_aead_inauthentic_inputs(
+                */
+               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,
+@@ -2497,12 +2558,13 @@ static int test_aead_vs_generic_impl(str
+        * 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,
+@@ -2541,6 +2603,7 @@ static int test_aead_extra(const struct
+       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;
+@@ -2930,11 +2993,14 @@ static int test_skcipher_vec(int enc, co
+ #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);
+@@ -2952,7 +3018,8 @@ static int test_skcipher_vec(int enc, co
+  * 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)
+@@ -2966,17 +3033,17 @@ static void generate_random_cipher_testv
+       /* Key: length in [0, maxkeysize], but usually choose maxkeysize */
+       vec->klen = maxkeysize;
+-      if (get_random_u32_below(4) == 0)
+-              vec->klen = get_random_u32_below(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)
+@@ -3018,6 +3085,7 @@ static int test_skcipher_vs_generic_impl
+       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;
+@@ -3035,6 +3103,8 @@ static int test_skcipher_vs_generic_impl
+       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)
+@@ -3119,9 +3189,11 @@ static int test_skcipher_vs_generic_impl
+       }
+       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);
diff --git a/queue-6.3/kvm-arm64-avoid-lock-inversion-when-setting-the-vm-register-width.patch b/queue-6.3/kvm-arm64-avoid-lock-inversion-when-setting-the-vm-register-width.patch
new file mode 100644 (file)
index 0000000..d0c0b63
--- /dev/null
@@ -0,0 +1,118 @@
+From c43120afb5c66a3465c7468f5cf9806a26484cde Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oliver.upton@linux.dev>
+Date: Mon, 27 Mar 2023 16:47:45 +0000
+Subject: KVM: arm64: Avoid lock inversion when setting the VM register width
+
+From: Oliver Upton <oliver.upton@linux.dev>
+
+commit c43120afb5c66a3465c7468f5cf9806a26484cde upstream.
+
+kvm->lock must be taken outside of the vcpu->mutex. Of course, the
+locking documentation for KVM makes this abundantly clear. Nonetheless,
+the locking order in KVM/arm64 has been wrong for quite a while; we
+acquire the kvm->lock while holding the vcpu->mutex all over the shop.
+
+All was seemingly fine until commit 42a90008f890 ("KVM: Ensure lockdep
+knows about kvm->lock vs. vcpu->mutex ordering rule") caught us with our
+pants down, leading to lockdep barfing:
+
+ ======================================================
+ WARNING: possible circular locking dependency detected
+ 6.2.0-rc7+ #19 Not tainted
+ ------------------------------------------------------
+ qemu-system-aar/859 is trying to acquire lock:
+ ffff5aa69269eba0 (&host_kvm->lock){+.+.}-{3:3}, at: kvm_reset_vcpu+0x34/0x274
+
+ but task is already holding lock:
+ ffff5aa68768c0b8 (&vcpu->mutex){+.+.}-{3:3}, at: kvm_vcpu_ioctl+0x8c/0xba0
+
+ which lock already depends on the new lock.
+
+Add a dedicated lock to serialize writes to VM-scoped configuration from
+the context of a vCPU. Protect the register width flags with the new
+lock, thus avoiding the need to grab the kvm->lock while holding
+vcpu->mutex in kvm_reset_vcpu().
+
+Cc: stable@vger.kernel.org
+Reported-by: Jeremy Linton <jeremy.linton@arm.com>
+Link: https://lore.kernel.org/kvmarm/f6452cdd-65ff-34b8-bab0-5c06416da5f6@arm.com/
+Tested-by: Jeremy Linton <jeremy.linton@arm.com>
+Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230327164747.2466958-3-oliver.upton@linux.dev
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/include/asm/kvm_host.h |    3 +++
+ arch/arm64/kvm/arm.c              |   18 ++++++++++++++++++
+ arch/arm64/kvm/reset.c            |    6 +++---
+ 3 files changed, 24 insertions(+), 3 deletions(-)
+
+--- a/arch/arm64/include/asm/kvm_host.h
++++ b/arch/arm64/include/asm/kvm_host.h
+@@ -199,6 +199,9 @@ struct kvm_arch {
+       /* Mandated version of PSCI */
+       u32 psci_version;
++      /* Protects VM-scoped configuration data */
++      struct mutex config_lock;
++
+       /*
+        * If we encounter a data abort without valid instruction syndrome
+        * information, report this to user space.  User space can (and
+--- a/arch/arm64/kvm/arm.c
++++ b/arch/arm64/kvm/arm.c
+@@ -128,6 +128,16 @@ int kvm_arch_init_vm(struct kvm *kvm, un
+ {
+       int ret;
++      mutex_init(&kvm->arch.config_lock);
++
++#ifdef CONFIG_LOCKDEP
++      /* Clue in lockdep that the config_lock must be taken inside kvm->lock */
++      mutex_lock(&kvm->lock);
++      mutex_lock(&kvm->arch.config_lock);
++      mutex_unlock(&kvm->arch.config_lock);
++      mutex_unlock(&kvm->lock);
++#endif
++
+       ret = kvm_share_hyp(kvm, kvm + 1);
+       if (ret)
+               return ret;
+@@ -329,6 +339,14 @@ int kvm_arch_vcpu_create(struct kvm_vcpu
+       spin_lock_init(&vcpu->arch.mp_state_lock);
++#ifdef CONFIG_LOCKDEP
++      /* Inform lockdep that the config_lock is acquired after vcpu->mutex */
++      mutex_lock(&vcpu->mutex);
++      mutex_lock(&vcpu->kvm->arch.config_lock);
++      mutex_unlock(&vcpu->kvm->arch.config_lock);
++      mutex_unlock(&vcpu->mutex);
++#endif
++
+       /* Force users to call KVM_ARM_VCPU_INIT */
+       vcpu->arch.target = -1;
+       bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES);
+--- a/arch/arm64/kvm/reset.c
++++ b/arch/arm64/kvm/reset.c
+@@ -205,7 +205,7 @@ static int kvm_set_vm_width(struct kvm_v
+       is32bit = vcpu_has_feature(vcpu, KVM_ARM_VCPU_EL1_32BIT);
+-      lockdep_assert_held(&kvm->lock);
++      lockdep_assert_held(&kvm->arch.config_lock);
+       if (test_bit(KVM_ARCH_FLAG_REG_WIDTH_CONFIGURED, &kvm->arch.flags)) {
+               /*
+@@ -262,9 +262,9 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu
+       bool loaded;
+       u32 pstate;
+-      mutex_lock(&vcpu->kvm->lock);
++      mutex_lock(&vcpu->kvm->arch.config_lock);
+       ret = kvm_set_vm_width(vcpu);
+-      mutex_unlock(&vcpu->kvm->lock);
++      mutex_unlock(&vcpu->kvm->arch.config_lock);
+       if (ret)
+               return ret;
diff --git a/queue-6.3/kvm-arm64-avoid-vcpu-mutex-v.-kvm-lock-inversion-in-cpu_on.patch b/queue-6.3/kvm-arm64-avoid-vcpu-mutex-v.-kvm-lock-inversion-in-cpu_on.patch
new file mode 100644 (file)
index 0000000..7d319ec
--- /dev/null
@@ -0,0 +1,268 @@
+From 0acc7239c20a8401b8968c2adace8f7c9b0295ae Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oliver.upton@linux.dev>
+Date: Mon, 27 Mar 2023 16:47:44 +0000
+Subject: KVM: arm64: Avoid vcpu->mutex v. kvm->lock inversion in CPU_ON
+
+From: Oliver Upton <oliver.upton@linux.dev>
+
+commit 0acc7239c20a8401b8968c2adace8f7c9b0295ae upstream.
+
+KVM/arm64 had the lock ordering backwards on vcpu->mutex and kvm->lock
+from the very beginning. One such example is the way vCPU resets are
+handled: the kvm->lock is acquired while handling a guest CPU_ON PSCI
+call.
+
+Add a dedicated lock to serialize writes to kvm_vcpu_arch::{mp_state,
+reset_state}. Promote all accessors of mp_state to {READ,WRITE}_ONCE()
+as readers do not acquire the mp_state_lock. While at it, plug yet
+another race by taking the mp_state_lock in the KVM_SET_MP_STATE ioctl
+handler.
+
+As changes to MP state are now guarded with a dedicated lock, drop the
+kvm->lock acquisition from the PSCI CPU_ON path. Similarly, move the
+reader of reset_state outside of the kvm->lock and instead protect it
+with the mp_state_lock. Note that writes to reset_state::reset have been
+demoted to regular stores as both readers and writers acquire the
+mp_state_lock.
+
+While the kvm->lock inversion still exists in kvm_reset_vcpu(), at least
+now PSCI CPU_ON no longer depends on it for serializing vCPU reset.
+
+Cc: stable@vger.kernel.org
+Tested-by: Jeremy Linton <jeremy.linton@arm.com>
+Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230327164747.2466958-2-oliver.upton@linux.dev
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/include/asm/kvm_host.h |    1 +
+ arch/arm64/kvm/arm.c              |   31 ++++++++++++++++++++++---------
+ arch/arm64/kvm/psci.c             |   28 ++++++++++++++++------------
+ arch/arm64/kvm/reset.c            |    9 +++++----
+ 4 files changed, 44 insertions(+), 25 deletions(-)
+
+--- a/arch/arm64/include/asm/kvm_host.h
++++ b/arch/arm64/include/asm/kvm_host.h
+@@ -522,6 +522,7 @@ struct kvm_vcpu_arch {
+       /* vcpu power state */
+       struct kvm_mp_state mp_state;
++      spinlock_t mp_state_lock;
+       /* Cache some mmu pages needed inside spinlock regions */
+       struct kvm_mmu_memory_cache mmu_page_cache;
+--- a/arch/arm64/kvm/arm.c
++++ b/arch/arm64/kvm/arm.c
+@@ -327,6 +327,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu
+ {
+       int err;
++      spin_lock_init(&vcpu->arch.mp_state_lock);
++
+       /* Force users to call KVM_ARM_VCPU_INIT */
+       vcpu->arch.target = -1;
+       bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES);
+@@ -444,34 +446,41 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *
+       vcpu->cpu = -1;
+ }
+-void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu)
++static void __kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu)
+ {
+-      vcpu->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
++      WRITE_ONCE(vcpu->arch.mp_state.mp_state, KVM_MP_STATE_STOPPED);
+       kvm_make_request(KVM_REQ_SLEEP, vcpu);
+       kvm_vcpu_kick(vcpu);
+ }
++void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu)
++{
++      spin_lock(&vcpu->arch.mp_state_lock);
++      __kvm_arm_vcpu_power_off(vcpu);
++      spin_unlock(&vcpu->arch.mp_state_lock);
++}
++
+ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
+ {
+-      return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_STOPPED;
++      return READ_ONCE(vcpu->arch.mp_state.mp_state) == KVM_MP_STATE_STOPPED;
+ }
+ static void kvm_arm_vcpu_suspend(struct kvm_vcpu *vcpu)
+ {
+-      vcpu->arch.mp_state.mp_state = KVM_MP_STATE_SUSPENDED;
++      WRITE_ONCE(vcpu->arch.mp_state.mp_state, KVM_MP_STATE_SUSPENDED);
+       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
+       kvm_vcpu_kick(vcpu);
+ }
+ static bool kvm_arm_vcpu_suspended(struct kvm_vcpu *vcpu)
+ {
+-      return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_SUSPENDED;
++      return READ_ONCE(vcpu->arch.mp_state.mp_state) == KVM_MP_STATE_SUSPENDED;
+ }
+ int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+                                   struct kvm_mp_state *mp_state)
+ {
+-      *mp_state = vcpu->arch.mp_state;
++      *mp_state = READ_ONCE(vcpu->arch.mp_state);
+       return 0;
+ }
+@@ -481,12 +490,14 @@ int kvm_arch_vcpu_ioctl_set_mpstate(stru
+ {
+       int ret = 0;
++      spin_lock(&vcpu->arch.mp_state_lock);
++
+       switch (mp_state->mp_state) {
+       case KVM_MP_STATE_RUNNABLE:
+-              vcpu->arch.mp_state = *mp_state;
++              WRITE_ONCE(vcpu->arch.mp_state, *mp_state);
+               break;
+       case KVM_MP_STATE_STOPPED:
+-              kvm_arm_vcpu_power_off(vcpu);
++              __kvm_arm_vcpu_power_off(vcpu);
+               break;
+       case KVM_MP_STATE_SUSPENDED:
+               kvm_arm_vcpu_suspend(vcpu);
+@@ -495,6 +506,8 @@ int kvm_arch_vcpu_ioctl_set_mpstate(stru
+               ret = -EINVAL;
+       }
++      spin_unlock(&vcpu->arch.mp_state_lock);
++
+       return ret;
+ }
+@@ -1214,7 +1227,7 @@ static int kvm_arch_vcpu_ioctl_vcpu_init
+       if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features))
+               kvm_arm_vcpu_power_off(vcpu);
+       else
+-              vcpu->arch.mp_state.mp_state = KVM_MP_STATE_RUNNABLE;
++              WRITE_ONCE(vcpu->arch.mp_state.mp_state, KVM_MP_STATE_RUNNABLE);
+       return 0;
+ }
+--- a/arch/arm64/kvm/psci.c
++++ b/arch/arm64/kvm/psci.c
+@@ -62,6 +62,7 @@ static unsigned long kvm_psci_vcpu_on(st
+       struct vcpu_reset_state *reset_state;
+       struct kvm *kvm = source_vcpu->kvm;
+       struct kvm_vcpu *vcpu = NULL;
++      int ret = PSCI_RET_SUCCESS;
+       unsigned long cpu_id;
+       cpu_id = smccc_get_arg1(source_vcpu);
+@@ -76,11 +77,15 @@ static unsigned long kvm_psci_vcpu_on(st
+        */
+       if (!vcpu)
+               return PSCI_RET_INVALID_PARAMS;
++
++      spin_lock(&vcpu->arch.mp_state_lock);
+       if (!kvm_arm_vcpu_stopped(vcpu)) {
+               if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1)
+-                      return PSCI_RET_ALREADY_ON;
++                      ret = PSCI_RET_ALREADY_ON;
+               else
+-                      return PSCI_RET_INVALID_PARAMS;
++                      ret = PSCI_RET_INVALID_PARAMS;
++
++              goto out_unlock;
+       }
+       reset_state = &vcpu->arch.reset_state;
+@@ -96,7 +101,7 @@ static unsigned long kvm_psci_vcpu_on(st
+        */
+       reset_state->r0 = smccc_get_arg3(source_vcpu);
+-      WRITE_ONCE(reset_state->reset, true);
++      reset_state->reset = true;
+       kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
+       /*
+@@ -108,7 +113,9 @@ static unsigned long kvm_psci_vcpu_on(st
+       vcpu->arch.mp_state.mp_state = KVM_MP_STATE_RUNNABLE;
+       kvm_vcpu_wake_up(vcpu);
+-      return PSCI_RET_SUCCESS;
++out_unlock:
++      spin_unlock(&vcpu->arch.mp_state_lock);
++      return ret;
+ }
+ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
+@@ -168,8 +175,11 @@ static void kvm_prepare_system_event(str
+        * after this call is handled and before the VCPUs have been
+        * re-initialized.
+        */
+-      kvm_for_each_vcpu(i, tmp, vcpu->kvm)
+-              tmp->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
++      kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
++              spin_lock(&tmp->arch.mp_state_lock);
++              WRITE_ONCE(tmp->arch.mp_state.mp_state, KVM_MP_STATE_STOPPED);
++              spin_unlock(&tmp->arch.mp_state_lock);
++      }
+       kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
+       memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
+@@ -229,7 +239,6 @@ static unsigned long kvm_psci_check_allo
+ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
+ {
+-      struct kvm *kvm = vcpu->kvm;
+       u32 psci_fn = smccc_get_function(vcpu);
+       unsigned long val;
+       int ret = 1;
+@@ -254,9 +263,7 @@ static int kvm_psci_0_2_call(struct kvm_
+               kvm_psci_narrow_to_32bit(vcpu);
+               fallthrough;
+       case PSCI_0_2_FN64_CPU_ON:
+-              mutex_lock(&kvm->lock);
+               val = kvm_psci_vcpu_on(vcpu);
+-              mutex_unlock(&kvm->lock);
+               break;
+       case PSCI_0_2_FN_AFFINITY_INFO:
+               kvm_psci_narrow_to_32bit(vcpu);
+@@ -395,7 +402,6 @@ static int kvm_psci_1_x_call(struct kvm_
+ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
+ {
+-      struct kvm *kvm = vcpu->kvm;
+       u32 psci_fn = smccc_get_function(vcpu);
+       unsigned long val;
+@@ -405,9 +411,7 @@ static int kvm_psci_0_1_call(struct kvm_
+               val = PSCI_RET_SUCCESS;
+               break;
+       case KVM_PSCI_FN_CPU_ON:
+-              mutex_lock(&kvm->lock);
+               val = kvm_psci_vcpu_on(vcpu);
+-              mutex_unlock(&kvm->lock);
+               break;
+       default:
+               val = PSCI_RET_NOT_SUPPORTED;
+--- a/arch/arm64/kvm/reset.c
++++ b/arch/arm64/kvm/reset.c
+@@ -264,15 +264,16 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu
+       mutex_lock(&vcpu->kvm->lock);
+       ret = kvm_set_vm_width(vcpu);
+-      if (!ret) {
+-              reset_state = vcpu->arch.reset_state;
+-              WRITE_ONCE(vcpu->arch.reset_state.reset, false);
+-      }
+       mutex_unlock(&vcpu->kvm->lock);
+       if (ret)
+               return ret;
++      spin_lock(&vcpu->arch.mp_state_lock);
++      reset_state = vcpu->arch.reset_state;
++      vcpu->arch.reset_state.reset = false;
++      spin_unlock(&vcpu->arch.mp_state_lock);
++
+       /* Reset PMU outside of the non-preemptible section */
+       kvm_pmu_vcpu_reset(vcpu);
diff --git a/queue-6.3/kvm-arm64-use-config_lock-to-protect-data-ordered-against-kvm_run.patch b/queue-6.3/kvm-arm64-use-config_lock-to-protect-data-ordered-against-kvm_run.patch
new file mode 100644 (file)
index 0000000..67c1fc9
--- /dev/null
@@ -0,0 +1,162 @@
+From 4bba7f7def6f278266dadf845da472cfbfed784e Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oliver.upton@linux.dev>
+Date: Mon, 27 Mar 2023 16:47:46 +0000
+Subject: KVM: arm64: Use config_lock to protect data ordered against KVM_RUN
+
+From: Oliver Upton <oliver.upton@linux.dev>
+
+commit 4bba7f7def6f278266dadf845da472cfbfed784e upstream.
+
+There are various bits of VM-scoped data that can only be configured
+before the first call to KVM_RUN, such as the hypercall bitmaps and
+the PMU. As these fields are protected by the kvm->lock and accessed
+while holding vcpu->mutex, this is yet another example of lock
+inversion.
+
+Change out the kvm->lock for kvm->arch.config_lock in all of these
+instances. Opportunistically simplify the locking mechanics of the
+PMU configuration by holding the config_lock for the entirety of
+kvm_arm_pmu_v3_set_attr().
+
+Note that this also addresses a couple of bugs. There is an unguarded
+read of the PMU version in KVM_ARM_VCPU_PMU_V3_FILTER which could race
+with KVM_ARM_VCPU_PMU_V3_SET_PMU. Additionally, until now writes to the
+per-vCPU vPMU irq were not serialized VM-wide, meaning concurrent calls
+to KVM_ARM_VCPU_PMU_V3_IRQ could lead to a false positive in
+pmu_irq_is_valid().
+
+Cc: stable@vger.kernel.org
+Tested-by: Jeremy Linton <jeremy.linton@arm.com>
+Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230327164747.2466958-4-oliver.upton@linux.dev
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/arm.c        |    4 ++--
+ arch/arm64/kvm/guest.c      |    2 ++
+ arch/arm64/kvm/hypercalls.c |    4 ++--
+ arch/arm64/kvm/pmu-emul.c   |   23 ++++++-----------------
+ 4 files changed, 12 insertions(+), 21 deletions(-)
+
+--- a/arch/arm64/kvm/arm.c
++++ b/arch/arm64/kvm/arm.c
+@@ -625,9 +625,9 @@ int kvm_arch_vcpu_run_pid_change(struct
+       if (kvm_vm_is_protected(kvm))
+               kvm_call_hyp_nvhe(__pkvm_vcpu_init_traps, vcpu);
+-      mutex_lock(&kvm->lock);
++      mutex_lock(&kvm->arch.config_lock);
+       set_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags);
+-      mutex_unlock(&kvm->lock);
++      mutex_unlock(&kvm->arch.config_lock);
+       return ret;
+ }
+--- a/arch/arm64/kvm/guest.c
++++ b/arch/arm64/kvm/guest.c
+@@ -957,7 +957,9 @@ int kvm_arm_vcpu_arch_set_attr(struct kv
+       switch (attr->group) {
+       case KVM_ARM_VCPU_PMU_V3_CTRL:
++              mutex_lock(&vcpu->kvm->arch.config_lock);
+               ret = kvm_arm_pmu_v3_set_attr(vcpu, attr);
++              mutex_unlock(&vcpu->kvm->arch.config_lock);
+               break;
+       case KVM_ARM_VCPU_TIMER_CTRL:
+               ret = kvm_arm_timer_set_attr(vcpu, attr);
+--- a/arch/arm64/kvm/hypercalls.c
++++ b/arch/arm64/kvm/hypercalls.c
+@@ -377,7 +377,7 @@ static int kvm_arm_set_fw_reg_bmap(struc
+       if (val & ~fw_reg_features)
+               return -EINVAL;
+-      mutex_lock(&kvm->lock);
++      mutex_lock(&kvm->arch.config_lock);
+       if (test_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags) &&
+           val != *fw_reg_bmap) {
+@@ -387,7 +387,7 @@ static int kvm_arm_set_fw_reg_bmap(struc
+       WRITE_ONCE(*fw_reg_bmap, val);
+ out:
+-      mutex_unlock(&kvm->lock);
++      mutex_unlock(&kvm->arch.config_lock);
+       return ret;
+ }
+--- a/arch/arm64/kvm/pmu-emul.c
++++ b/arch/arm64/kvm/pmu-emul.c
+@@ -876,7 +876,7 @@ static int kvm_arm_pmu_v3_set_pmu(struct
+       struct arm_pmu *arm_pmu;
+       int ret = -ENXIO;
+-      mutex_lock(&kvm->lock);
++      lockdep_assert_held(&kvm->arch.config_lock);
+       mutex_lock(&arm_pmus_lock);
+       list_for_each_entry(entry, &arm_pmus, entry) {
+@@ -896,7 +896,6 @@ static int kvm_arm_pmu_v3_set_pmu(struct
+       }
+       mutex_unlock(&arm_pmus_lock);
+-      mutex_unlock(&kvm->lock);
+       return ret;
+ }
+@@ -904,22 +903,20 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_v
+ {
+       struct kvm *kvm = vcpu->kvm;
++      lockdep_assert_held(&kvm->arch.config_lock);
++
+       if (!kvm_vcpu_has_pmu(vcpu))
+               return -ENODEV;
+       if (vcpu->arch.pmu.created)
+               return -EBUSY;
+-      mutex_lock(&kvm->lock);
+       if (!kvm->arch.arm_pmu) {
+               /* No PMU set, get the default one */
+               kvm->arch.arm_pmu = kvm_pmu_probe_armpmu();
+-              if (!kvm->arch.arm_pmu) {
+-                      mutex_unlock(&kvm->lock);
++              if (!kvm->arch.arm_pmu)
+                       return -ENODEV;
+-              }
+       }
+-      mutex_unlock(&kvm->lock);
+       switch (attr->attr) {
+       case KVM_ARM_VCPU_PMU_V3_IRQ: {
+@@ -963,19 +960,13 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_v
+                    filter.action != KVM_PMU_EVENT_DENY))
+                       return -EINVAL;
+-              mutex_lock(&kvm->lock);
+-
+-              if (test_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags)) {
+-                      mutex_unlock(&kvm->lock);
++              if (test_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags))
+                       return -EBUSY;
+-              }
+               if (!kvm->arch.pmu_filter) {
+                       kvm->arch.pmu_filter = bitmap_alloc(nr_events, GFP_KERNEL_ACCOUNT);
+-                      if (!kvm->arch.pmu_filter) {
+-                              mutex_unlock(&kvm->lock);
++                      if (!kvm->arch.pmu_filter)
+                               return -ENOMEM;
+-                      }
+                       /*
+                        * The default depends on the first applied filter.
+@@ -994,8 +985,6 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_v
+               else
+                       bitmap_clear(kvm->arch.pmu_filter, filter.base_event, filter.nevents);
+-              mutex_unlock(&kvm->lock);
+-
+               return 0;
+       }
+       case KVM_ARM_VCPU_PMU_V3_SET_PMU: {
diff --git a/queue-6.3/kvm-arm64-use-config_lock-to-protect-vgic-state.patch b/queue-6.3/kvm-arm64-use-config_lock-to-protect-vgic-state.patch
new file mode 100644 (file)
index 0000000..f68bbca
--- /dev/null
@@ -0,0 +1,531 @@
+From f00327731131d1b5aa6a1aa9f50bcf8d620ace4c Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oliver.upton@linux.dev>
+Date: Mon, 27 Mar 2023 16:47:47 +0000
+Subject: KVM: arm64: Use config_lock to protect vgic state
+
+From: Oliver Upton <oliver.upton@linux.dev>
+
+commit f00327731131d1b5aa6a1aa9f50bcf8d620ace4c upstream.
+
+Almost all of the vgic state is VM-scoped but accessed from the context
+of a vCPU. These accesses were serialized on the kvm->lock which cannot
+be nested within a vcpu->mutex critical section.
+
+Move over the vgic state to using the config_lock. Tweak the lock
+ordering where necessary to ensure that the config_lock is acquired
+after the vcpu->mutex. Acquire the config_lock in kvm_vgic_create() to
+avoid a race between the converted flows and GIC creation. Where
+necessary, continue to acquire kvm->lock to avoid a race with vCPU
+creation (i.e. flows that use lock_all_vcpus()).
+
+Finally, promote the locking expectations in comments to lockdep
+assertions and update the locking documentation for the config_lock as
+well as vcpu->mutex.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230327164747.2466958-5-oliver.upton@linux.dev
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/vgic/vgic-debug.c      |    8 ++---
+ arch/arm64/kvm/vgic/vgic-init.c       |   36 ++++++++++++++++----------
+ arch/arm64/kvm/vgic/vgic-its.c        |   18 ++++++++-----
+ arch/arm64/kvm/vgic/vgic-kvm-device.c |   47 ++++++++++++++++++++--------------
+ arch/arm64/kvm/vgic/vgic-mmio-v3.c    |    4 +-
+ arch/arm64/kvm/vgic/vgic-mmio.c       |   12 ++++----
+ arch/arm64/kvm/vgic/vgic-v4.c         |   11 ++++---
+ arch/arm64/kvm/vgic/vgic.c            |   12 +++++---
+ 8 files changed, 88 insertions(+), 60 deletions(-)
+
+--- a/arch/arm64/kvm/vgic/vgic-debug.c
++++ b/arch/arm64/kvm/vgic/vgic-debug.c
+@@ -85,7 +85,7 @@ static void *vgic_debug_start(struct seq
+       struct kvm *kvm = s->private;
+       struct vgic_state_iter *iter;
+-      mutex_lock(&kvm->lock);
++      mutex_lock(&kvm->arch.config_lock);
+       iter = kvm->arch.vgic.iter;
+       if (iter) {
+               iter = ERR_PTR(-EBUSY);
+@@ -104,7 +104,7 @@ static void *vgic_debug_start(struct seq
+       if (end_of_vgic(iter))
+               iter = NULL;
+ out:
+-      mutex_unlock(&kvm->lock);
++      mutex_unlock(&kvm->arch.config_lock);
+       return iter;
+ }
+@@ -132,12 +132,12 @@ static void vgic_debug_stop(struct seq_f
+       if (IS_ERR(v))
+               return;
+-      mutex_lock(&kvm->lock);
++      mutex_lock(&kvm->arch.config_lock);
+       iter = kvm->arch.vgic.iter;
+       kfree(iter->lpi_array);
+       kfree(iter);
+       kvm->arch.vgic.iter = NULL;
+-      mutex_unlock(&kvm->lock);
++      mutex_unlock(&kvm->arch.config_lock);
+ }
+ static void print_dist_state(struct seq_file *s, struct vgic_dist *dist)
+--- a/arch/arm64/kvm/vgic/vgic-init.c
++++ b/arch/arm64/kvm/vgic/vgic-init.c
+@@ -74,9 +74,6 @@ int kvm_vgic_create(struct kvm *kvm, u32
+       unsigned long i;
+       int ret;
+-      if (irqchip_in_kernel(kvm))
+-              return -EEXIST;
+-
+       /*
+        * This function is also called by the KVM_CREATE_IRQCHIP handler,
+        * which had no chance yet to check the availability of the GICv2
+@@ -87,10 +84,20 @@ int kvm_vgic_create(struct kvm *kvm, u32
+               !kvm_vgic_global_state.can_emulate_gicv2)
+               return -ENODEV;
++      /* Must be held to avoid race with vCPU creation */
++      lockdep_assert_held(&kvm->lock);
++
+       ret = -EBUSY;
+       if (!lock_all_vcpus(kvm))
+               return ret;
++      mutex_lock(&kvm->arch.config_lock);
++
++      if (irqchip_in_kernel(kvm)) {
++              ret = -EEXIST;
++              goto out_unlock;
++      }
++
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               if (vcpu_has_run_once(vcpu))
+                       goto out_unlock;
+@@ -118,6 +125,7 @@ int kvm_vgic_create(struct kvm *kvm, u32
+               INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
+ out_unlock:
++      mutex_unlock(&kvm->arch.config_lock);
+       unlock_all_vcpus(kvm);
+       return ret;
+ }
+@@ -227,9 +235,9 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *
+        * KVM io device for the redistributor that belongs to this VCPU.
+        */
+       if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
+-              mutex_lock(&vcpu->kvm->lock);
++              mutex_lock(&vcpu->kvm->arch.config_lock);
+               ret = vgic_register_redist_iodev(vcpu);
+-              mutex_unlock(&vcpu->kvm->lock);
++              mutex_unlock(&vcpu->kvm->arch.config_lock);
+       }
+       return ret;
+ }
+@@ -250,7 +258,6 @@ static void kvm_vgic_vcpu_enable(struct
+  * The function is generally called when nr_spis has been explicitly set
+  * by the guest through the KVM DEVICE API. If not nr_spis is set to 256.
+  * vgic_initialized() returns true when this function has succeeded.
+- * Must be called with kvm->lock held!
+  */
+ int vgic_init(struct kvm *kvm)
+ {
+@@ -259,6 +266,8 @@ int vgic_init(struct kvm *kvm)
+       int ret = 0, i;
+       unsigned long idx;
++      lockdep_assert_held(&kvm->arch.config_lock);
++
+       if (vgic_initialized(kvm))
+               return 0;
+@@ -373,12 +382,13 @@ void kvm_vgic_vcpu_destroy(struct kvm_vc
+       vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF;
+ }
+-/* To be called with kvm->lock held */
+ static void __kvm_vgic_destroy(struct kvm *kvm)
+ {
+       struct kvm_vcpu *vcpu;
+       unsigned long i;
++      lockdep_assert_held(&kvm->arch.config_lock);
++
+       vgic_debug_destroy(kvm);
+       kvm_for_each_vcpu(i, vcpu, kvm)
+@@ -389,9 +399,9 @@ static void __kvm_vgic_destroy(struct kv
+ void kvm_vgic_destroy(struct kvm *kvm)
+ {
+-      mutex_lock(&kvm->lock);
++      mutex_lock(&kvm->arch.config_lock);
+       __kvm_vgic_destroy(kvm);
+-      mutex_unlock(&kvm->lock);
++      mutex_unlock(&kvm->arch.config_lock);
+ }
+ /**
+@@ -414,9 +424,9 @@ int vgic_lazy_init(struct kvm *kvm)
+               if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2)
+                       return -EBUSY;
+-              mutex_lock(&kvm->lock);
++              mutex_lock(&kvm->arch.config_lock);
+               ret = vgic_init(kvm);
+-              mutex_unlock(&kvm->lock);
++              mutex_unlock(&kvm->arch.config_lock);
+       }
+       return ret;
+@@ -441,7 +451,7 @@ int kvm_vgic_map_resources(struct kvm *k
+       if (likely(vgic_ready(kvm)))
+               return 0;
+-      mutex_lock(&kvm->lock);
++      mutex_lock(&kvm->arch.config_lock);
+       if (vgic_ready(kvm))
+               goto out;
+@@ -459,7 +469,7 @@ int kvm_vgic_map_resources(struct kvm *k
+               dist->ready = true;
+ out:
+-      mutex_unlock(&kvm->lock);
++      mutex_unlock(&kvm->arch.config_lock);
+       return ret;
+ }
+--- a/arch/arm64/kvm/vgic/vgic-its.c
++++ b/arch/arm64/kvm/vgic/vgic-its.c
+@@ -2045,6 +2045,13 @@ static int vgic_its_attr_regs_access(str
+       mutex_lock(&dev->kvm->lock);
++      if (!lock_all_vcpus(dev->kvm)) {
++              mutex_unlock(&dev->kvm->lock);
++              return -EBUSY;
++      }
++
++      mutex_lock(&dev->kvm->arch.config_lock);
++
+       if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base)) {
+               ret = -ENXIO;
+               goto out;
+@@ -2058,11 +2065,6 @@ static int vgic_its_attr_regs_access(str
+               goto out;
+       }
+-      if (!lock_all_vcpus(dev->kvm)) {
+-              ret = -EBUSY;
+-              goto out;
+-      }
+-
+       addr = its->vgic_its_base + offset;
+       len = region->access_flags & VGIC_ACCESS_64bit ? 8 : 4;
+@@ -2076,8 +2078,9 @@ static int vgic_its_attr_regs_access(str
+       } else {
+               *reg = region->its_read(dev->kvm, its, addr, len);
+       }
+-      unlock_all_vcpus(dev->kvm);
+ out:
++      mutex_unlock(&dev->kvm->arch.config_lock);
++      unlock_all_vcpus(dev->kvm);
+       mutex_unlock(&dev->kvm->lock);
+       return ret;
+ }
+@@ -2757,6 +2760,8 @@ static int vgic_its_ctrl(struct kvm *kvm
+               return -EBUSY;
+       }
++      mutex_lock(&kvm->arch.config_lock);
++
+       switch (attr) {
+       case KVM_DEV_ARM_ITS_CTRL_RESET:
+               vgic_its_reset(kvm, its);
+@@ -2769,6 +2774,7 @@ static int vgic_its_ctrl(struct kvm *kvm
+               break;
+       }
++      mutex_unlock(&kvm->arch.config_lock);
+       unlock_all_vcpus(kvm);
+       mutex_unlock(&its->its_lock);
+       mutex_unlock(&kvm->lock);
+--- a/arch/arm64/kvm/vgic/vgic-kvm-device.c
++++ b/arch/arm64/kvm/vgic/vgic-kvm-device.c
+@@ -46,7 +46,7 @@ int kvm_set_legacy_vgic_v2_addr(struct k
+       struct vgic_dist *vgic = &kvm->arch.vgic;
+       int r;
+-      mutex_lock(&kvm->lock);
++      mutex_lock(&kvm->arch.config_lock);
+       switch (FIELD_GET(KVM_ARM_DEVICE_TYPE_MASK, dev_addr->id)) {
+       case KVM_VGIC_V2_ADDR_TYPE_DIST:
+               r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
+@@ -68,7 +68,7 @@ int kvm_set_legacy_vgic_v2_addr(struct k
+               r = -ENODEV;
+       }
+-      mutex_unlock(&kvm->lock);
++      mutex_unlock(&kvm->arch.config_lock);
+       return r;
+ }
+@@ -102,7 +102,7 @@ static int kvm_vgic_addr(struct kvm *kvm
+               if (get_user(addr, uaddr))
+                       return -EFAULT;
+-      mutex_lock(&kvm->lock);
++      mutex_lock(&kvm->arch.config_lock);
+       switch (attr->attr) {
+       case KVM_VGIC_V2_ADDR_TYPE_DIST:
+               r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
+@@ -191,7 +191,7 @@ static int kvm_vgic_addr(struct kvm *kvm
+       }
+ out:
+-      mutex_unlock(&kvm->lock);
++      mutex_unlock(&kvm->arch.config_lock);
+       if (!r && !write)
+               r =  put_user(addr, uaddr);
+@@ -227,7 +227,7 @@ static int vgic_set_common_attr(struct k
+                   (val & 31))
+                       return -EINVAL;
+-              mutex_lock(&dev->kvm->lock);
++              mutex_lock(&dev->kvm->arch.config_lock);
+               if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis)
+                       ret = -EBUSY;
+@@ -235,16 +235,16 @@ static int vgic_set_common_attr(struct k
+                       dev->kvm->arch.vgic.nr_spis =
+                               val - VGIC_NR_PRIVATE_IRQS;
+-              mutex_unlock(&dev->kvm->lock);
++              mutex_unlock(&dev->kvm->arch.config_lock);
+               return ret;
+       }
+       case KVM_DEV_ARM_VGIC_GRP_CTRL: {
+               switch (attr->attr) {
+               case KVM_DEV_ARM_VGIC_CTRL_INIT:
+-                      mutex_lock(&dev->kvm->lock);
++                      mutex_lock(&dev->kvm->arch.config_lock);
+                       r = vgic_init(dev->kvm);
+-                      mutex_unlock(&dev->kvm->lock);
++                      mutex_unlock(&dev->kvm->arch.config_lock);
+                       return r;
+               case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES:
+                       /*
+@@ -260,7 +260,10 @@ static int vgic_set_common_attr(struct k
+                               mutex_unlock(&dev->kvm->lock);
+                               return -EBUSY;
+                       }
++
++                      mutex_lock(&dev->kvm->arch.config_lock);
+                       r = vgic_v3_save_pending_tables(dev->kvm);
++                      mutex_unlock(&dev->kvm->arch.config_lock);
+                       unlock_all_vcpus(dev->kvm);
+                       mutex_unlock(&dev->kvm->lock);
+                       return r;
+@@ -411,15 +414,17 @@ static int vgic_v2_attr_regs_access(stru
+       mutex_lock(&dev->kvm->lock);
++      if (!lock_all_vcpus(dev->kvm)) {
++              mutex_unlock(&dev->kvm->lock);
++              return -EBUSY;
++      }
++
++      mutex_lock(&dev->kvm->arch.config_lock);
++
+       ret = vgic_init(dev->kvm);
+       if (ret)
+               goto out;
+-      if (!lock_all_vcpus(dev->kvm)) {
+-              ret = -EBUSY;
+-              goto out;
+-      }
+-
+       switch (attr->group) {
+       case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+               ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, &val);
+@@ -432,8 +437,9 @@ static int vgic_v2_attr_regs_access(stru
+               break;
+       }
+-      unlock_all_vcpus(dev->kvm);
+ out:
++      mutex_unlock(&dev->kvm->arch.config_lock);
++      unlock_all_vcpus(dev->kvm);
+       mutex_unlock(&dev->kvm->lock);
+       if (!ret && !is_write)
+@@ -569,12 +575,14 @@ static int vgic_v3_attr_regs_access(stru
+       mutex_lock(&dev->kvm->lock);
+-      if (unlikely(!vgic_initialized(dev->kvm))) {
+-              ret = -EBUSY;
+-              goto out;
++      if (!lock_all_vcpus(dev->kvm)) {
++              mutex_unlock(&dev->kvm->lock);
++              return -EBUSY;
+       }
+-      if (!lock_all_vcpus(dev->kvm)) {
++      mutex_lock(&dev->kvm->arch.config_lock);
++
++      if (unlikely(!vgic_initialized(dev->kvm))) {
+               ret = -EBUSY;
+               goto out;
+       }
+@@ -609,8 +617,9 @@ static int vgic_v3_attr_regs_access(stru
+               break;
+       }
+-      unlock_all_vcpus(dev->kvm);
+ out:
++      mutex_unlock(&dev->kvm->arch.config_lock);
++      unlock_all_vcpus(dev->kvm);
+       mutex_unlock(&dev->kvm->lock);
+       if (!ret && uaccess && !is_write) {
+--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
++++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
+@@ -111,7 +111,7 @@ static void vgic_mmio_write_v3_misc(stru
+       case GICD_CTLR: {
+               bool was_enabled, is_hwsgi;
+-              mutex_lock(&vcpu->kvm->lock);
++              mutex_lock(&vcpu->kvm->arch.config_lock);
+               was_enabled = dist->enabled;
+               is_hwsgi = dist->nassgireq;
+@@ -139,7 +139,7 @@ static void vgic_mmio_write_v3_misc(stru
+               else if (!was_enabled && dist->enabled)
+                       vgic_kick_vcpus(vcpu->kvm);
+-              mutex_unlock(&vcpu->kvm->lock);
++              mutex_unlock(&vcpu->kvm->arch.config_lock);
+               break;
+       }
+       case GICD_TYPER:
+--- a/arch/arm64/kvm/vgic/vgic-mmio.c
++++ b/arch/arm64/kvm/vgic/vgic-mmio.c
+@@ -530,13 +530,13 @@ unsigned long vgic_mmio_read_active(stru
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+       u32 val;
+-      mutex_lock(&vcpu->kvm->lock);
++      mutex_lock(&vcpu->kvm->arch.config_lock);
+       vgic_access_active_prepare(vcpu, intid);
+       val = __vgic_mmio_read_active(vcpu, addr, len);
+       vgic_access_active_finish(vcpu, intid);
+-      mutex_unlock(&vcpu->kvm->lock);
++      mutex_unlock(&vcpu->kvm->arch.config_lock);
+       return val;
+ }
+@@ -625,13 +625,13 @@ void vgic_mmio_write_cactive(struct kvm_
+ {
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+-      mutex_lock(&vcpu->kvm->lock);
++      mutex_lock(&vcpu->kvm->arch.config_lock);
+       vgic_access_active_prepare(vcpu, intid);
+       __vgic_mmio_write_cactive(vcpu, addr, len, val);
+       vgic_access_active_finish(vcpu, intid);
+-      mutex_unlock(&vcpu->kvm->lock);
++      mutex_unlock(&vcpu->kvm->arch.config_lock);
+ }
+ int vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu,
+@@ -662,13 +662,13 @@ void vgic_mmio_write_sactive(struct kvm_
+ {
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+-      mutex_lock(&vcpu->kvm->lock);
++      mutex_lock(&vcpu->kvm->arch.config_lock);
+       vgic_access_active_prepare(vcpu, intid);
+       __vgic_mmio_write_sactive(vcpu, addr, len, val);
+       vgic_access_active_finish(vcpu, intid);
+-      mutex_unlock(&vcpu->kvm->lock);
++      mutex_unlock(&vcpu->kvm->arch.config_lock);
+ }
+ int vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu,
+--- a/arch/arm64/kvm/vgic/vgic-v4.c
++++ b/arch/arm64/kvm/vgic/vgic-v4.c
+@@ -232,9 +232,8 @@ int vgic_v4_request_vpe_irq(struct kvm_v
+  * @kvm:      Pointer to the VM being initialized
+  *
+  * We may be called each time a vITS is created, or when the
+- * vgic is initialized. This relies on kvm->lock to be
+- * held. In both cases, the number of vcpus should now be
+- * fixed.
++ * vgic is initialized. In both cases, the number of vcpus
++ * should now be fixed.
+  */
+ int vgic_v4_init(struct kvm *kvm)
+ {
+@@ -243,6 +242,8 @@ int vgic_v4_init(struct kvm *kvm)
+       int nr_vcpus, ret;
+       unsigned long i;
++      lockdep_assert_held(&kvm->arch.config_lock);
++
+       if (!kvm_vgic_global_state.has_gicv4)
+               return 0; /* Nothing to see here... move along. */
+@@ -309,14 +310,14 @@ int vgic_v4_init(struct kvm *kvm)
+ /**
+  * vgic_v4_teardown - Free the GICv4 data structures
+  * @kvm:      Pointer to the VM being destroyed
+- *
+- * Relies on kvm->lock to be held.
+  */
+ void vgic_v4_teardown(struct kvm *kvm)
+ {
+       struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
+       int i;
++      lockdep_assert_held(&kvm->arch.config_lock);
++
+       if (!its_vm->vpes)
+               return;
+--- a/arch/arm64/kvm/vgic/vgic.c
++++ b/arch/arm64/kvm/vgic/vgic.c
+@@ -24,11 +24,13 @@ struct vgic_global kvm_vgic_global_state
+ /*
+  * Locking order is always:
+  * kvm->lock (mutex)
+- *   its->cmd_lock (mutex)
+- *     its->its_lock (mutex)
+- *       vgic_cpu->ap_list_lock               must be taken with IRQs disabled
+- *         kvm->lpi_list_lock         must be taken with IRQs disabled
+- *           vgic_irq->irq_lock               must be taken with IRQs disabled
++ *   vcpu->mutex (mutex)
++ *     kvm->arch.config_lock (mutex)
++ *       its->cmd_lock (mutex)
++ *         its->its_lock (mutex)
++ *           vgic_cpu->ap_list_lock           must be taken with IRQs disabled
++ *             kvm->lpi_list_lock             must be taken with IRQs disabled
++ *               vgic_irq->irq_lock           must be taken with IRQs disabled
+  *
+  * As the ap_list_lock might be taken from the timer interrupt handler,
+  * we have to disable IRQs before taking this lock and everything lower
diff --git a/queue-6.3/kvm-arm64-vgic-don-t-acquire-its_lock-before-config_lock.patch b/queue-6.3/kvm-arm64-vgic-don-t-acquire-its_lock-before-config_lock.patch
new file mode 100644 (file)
index 0000000..da3a162
--- /dev/null
@@ -0,0 +1,78 @@
+From 49e5d16b6fc003407a33a9961b4bcbb970bd1c76 Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oliver.upton@linux.dev>
+Date: Wed, 12 Apr 2023 06:27:33 +0000
+Subject: KVM: arm64: vgic: Don't acquire its_lock before config_lock
+
+From: Oliver Upton <oliver.upton@linux.dev>
+
+commit 49e5d16b6fc003407a33a9961b4bcbb970bd1c76 upstream.
+
+commit f00327731131 ("KVM: arm64: Use config_lock to protect vgic
+state") was meant to rectify a longstanding lock ordering issue in KVM
+where the kvm->lock is taken while holding vcpu->mutex. As it so
+happens, the aforementioned commit introduced yet another locking issue
+by acquiring the its_lock before acquiring the config lock.
+
+This is obviously wrong, especially considering that the lock ordering
+is well documented in vgic.c. Reshuffle the locks once more to take the
+config_lock before the its_lock. While at it, sprinkle in the lockdep
+hinting that has become popular as of late to keep lockdep apprised of
+our ordering.
+
+Cc: stable@vger.kernel.org
+Fixes: f00327731131 ("KVM: arm64: Use config_lock to protect vgic state")
+Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20230412062733.988229-1-oliver.upton@linux.dev
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/vgic/vgic-its.c |   15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/arch/arm64/kvm/vgic/vgic-its.c
++++ b/arch/arm64/kvm/vgic/vgic-its.c
+@@ -1958,6 +1958,16 @@ static int vgic_its_create(struct kvm_de
+       mutex_init(&its->its_lock);
+       mutex_init(&its->cmd_lock);
++      /* Yep, even more trickery for lock ordering... */
++#ifdef CONFIG_LOCKDEP
++      mutex_lock(&dev->kvm->arch.config_lock);
++      mutex_lock(&its->cmd_lock);
++      mutex_lock(&its->its_lock);
++      mutex_unlock(&its->its_lock);
++      mutex_unlock(&its->cmd_lock);
++      mutex_unlock(&dev->kvm->arch.config_lock);
++#endif
++
+       its->vgic_its_base = VGIC_ADDR_UNDEF;
+       INIT_LIST_HEAD(&its->device_list);
+@@ -2752,15 +2762,14 @@ static int vgic_its_ctrl(struct kvm *kvm
+               return 0;
+       mutex_lock(&kvm->lock);
+-      mutex_lock(&its->its_lock);
+       if (!lock_all_vcpus(kvm)) {
+-              mutex_unlock(&its->its_lock);
+               mutex_unlock(&kvm->lock);
+               return -EBUSY;
+       }
+       mutex_lock(&kvm->arch.config_lock);
++      mutex_lock(&its->its_lock);
+       switch (attr) {
+       case KVM_DEV_ARM_ITS_CTRL_RESET:
+@@ -2774,9 +2783,9 @@ static int vgic_its_ctrl(struct kvm *kvm
+               break;
+       }
++      mutex_unlock(&its->its_lock);
+       mutex_unlock(&kvm->arch.config_lock);
+       unlock_all_vcpus(kvm);
+-      mutex_unlock(&its->its_lock);
+       mutex_unlock(&kvm->lock);
+       return ret;
+ }
diff --git a/queue-6.3/kvm-nvmx-emulate-nops-in-l2-and-pause-if-it-s-not-intercepted.patch b/queue-6.3/kvm-nvmx-emulate-nops-in-l2-and-pause-if-it-s-not-intercepted.patch
new file mode 100644 (file)
index 0000000..16cba38
--- /dev/null
@@ -0,0 +1,68 @@
+From 4984563823f0034d3533854c1b50e729f5191089 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Tue, 4 Apr 2023 17:23:59 -0700
+Subject: KVM: nVMX: Emulate NOPs in L2, and PAUSE if it's not intercepted
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 4984563823f0034d3533854c1b50e729f5191089 upstream.
+
+Extend VMX's nested intercept logic for emulated instructions to handle
+"pause" interception, in quotes because KVM's emulator doesn't filter out
+NOPs when checking for nested intercepts.  Failure to allow emulation of
+NOPs results in KVM injecting a #UD into L2 on any NOP that collides with
+the emulator's definition of PAUSE, i.e. on all single-byte NOPs.
+
+For PAUSE itself, honor L1's PAUSE-exiting control, but ignore PLE to
+avoid unnecessarily injecting a #UD into L2.  Per the SDM, the first
+execution of PAUSE after VM-Entry is treated as the beginning of a new
+loop, i.e. will never trigger a PLE VM-Exit, and so L1 can't expect any
+given execution of PAUSE to deterministically exit.
+
+  ... the processor considers this execution to be the first execution of
+  PAUSE in a loop. (It also does so for the first execution of PAUSE at
+  CPL 0 after VM entry.)
+
+All that said, the PLE side of things is currently a moot point, as KVM
+doesn't expose PLE to L1.
+
+Note, vmx_check_intercept() is still wildly broken when L1 wants to
+intercept an instruction, as KVM injects a #UD instead of synthesizing a
+nested VM-Exit.  That issue extends far beyond NOP/PAUSE and needs far
+more effort to fix, i.e. is a problem for the future.
+
+Fixes: 07721feee46b ("KVM: nVMX: Don't emulate instructions in guest mode")
+Cc: Mathias Krause <minipli@grsecurity.net>
+Cc: stable@vger.kernel.org
+Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
+Link: https://lore.kernel.org/r/20230405002359.418138-1-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/vmx/vmx.c |   15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -7920,6 +7920,21 @@ static int vmx_check_intercept(struct kv
+               /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED.  */
+               break;
++      case x86_intercept_pause:
++              /*
++               * PAUSE is a single-byte NOP with a REPE prefix, i.e. collides
++               * with vanilla NOPs in the emulator.  Apply the interception
++               * check only to actual PAUSE instructions.  Don't check
++               * PAUSE-loop-exiting, software can't expect a given PAUSE to
++               * exit, i.e. KVM is within its rights to allow L2 to execute
++               * the PAUSE.
++               */
++              if ((info->rep_prefix != REPE_PREFIX) ||
++                  !nested_cpu_has2(vmcs12, CPU_BASED_PAUSE_EXITING))
++                      return X86EMUL_CONTINUE;
++
++              break;
++
+       /* TODO: check more intercepts... */
+       default:
+               break;
diff --git a/queue-6.3/kvm-x86-pmu-disallow-legacy-lbrs-if-architectural-lbrs-are-available.patch b/queue-6.3/kvm-x86-pmu-disallow-legacy-lbrs-if-architectural-lbrs-are-available.patch
new file mode 100644 (file)
index 0000000..301da15
--- /dev/null
@@ -0,0 +1,44 @@
+From 098f4c061ea10b777033b71c10bd9fd706820ee9 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Sat, 28 Jan 2023 00:14:27 +0000
+Subject: KVM: x86/pmu: Disallow legacy LBRs if architectural LBRs are available
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 098f4c061ea10b777033b71c10bd9fd706820ee9 upstream.
+
+Disallow enabling LBR support if the CPU supports architectural LBRs.
+Traditional LBR support is absent on CPU models that have architectural
+LBRs, and KVM doesn't yet support arch LBRs, i.e. KVM will pass through
+non-existent MSRs if userspace enables LBRs for the guest.
+
+Cc: stable@vger.kernel.org
+Cc: Yang Weijiang <weijiang.yang@intel.com>
+Cc: Like Xu <like.xu.linux@gmail.com>
+Reported-by: Paolo Bonzini <pbonzini@redhat.com>
+Fixes: be635e34c284 ("KVM: vmx/pmu: Expose LBR_FMT in the MSR_IA32_PERF_CAPABILITIES")
+Tested-by: Like Xu <likexu@tencent.com>
+Link: https://lore.kernel.org/r/20230128001427.2548858-1-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/vmx/vmx.c |    8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -7776,9 +7776,11 @@ static u64 vmx_get_perf_capabilities(voi
+       if (boot_cpu_has(X86_FEATURE_PDCM))
+               rdmsrl(MSR_IA32_PERF_CAPABILITIES, host_perf_cap);
+-      x86_perf_get_lbr(&lbr);
+-      if (lbr.nr)
+-              perf_cap |= host_perf_cap & PMU_CAP_LBR_FMT;
++      if (!cpu_feature_enabled(X86_FEATURE_ARCH_LBR)) {
++              x86_perf_get_lbr(&lbr);
++              if (lbr.nr)
++                      perf_cap |= host_perf_cap & PMU_CAP_LBR_FMT;
++      }
+       if (vmx_pebs_supported()) {
+               perf_cap |= host_perf_cap & PERF_CAP_PEBS_MASK;
diff --git a/queue-6.3/pinctrl-qcom-lpass-lpi-set-output-value-before-enabling-output.patch b/queue-6.3/pinctrl-qcom-lpass-lpi-set-output-value-before-enabling-output.patch
new file mode 100644 (file)
index 0000000..1257bb1
--- /dev/null
@@ -0,0 +1,54 @@
+From 163bfb0cb1f6fbf961cf912cbde57399ea1ae0e8 Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Date: Thu, 9 Mar 2023 16:49:46 +0100
+Subject: pinctrl: qcom: lpass-lpi: set output value before enabling output
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+commit 163bfb0cb1f6fbf961cf912cbde57399ea1ae0e8 upstream.
+
+As per Hardware Programming Guide, when configuring pin as output,
+set the pin value before setting output-enable (OE).  Similar approach
+is in main SoC TLMM pin controller.
+
+Cc: <stable@vger.kernel.org>
+Fixes: 6e261d1090d6 ("pinctrl: qcom: Add sm8250 lpass lpi pinctrl driver")
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230309154949.658380-1-krzysztof.kozlowski@linaro.org
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pinctrl/qcom/pinctrl-lpass-lpi.c |   14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+--- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c
++++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c
+@@ -221,6 +221,15 @@ static int lpi_config_set(struct pinctrl
+               }
+       }
++      /*
++       * As per Hardware Programming Guide, when configuring pin as output,
++       * set the pin value before setting output-enable (OE).
++       */
++      if (output_enabled) {
++              val = u32_encode_bits(value ? 1 : 0, LPI_GPIO_VALUE_OUT_MASK);
++              lpi_gpio_write(pctrl, group, LPI_GPIO_VALUE_REG, val);
++      }
++
+       val = lpi_gpio_read(pctrl, group, LPI_GPIO_CFG_REG);
+       u32p_replace_bits(&val, pullup, LPI_GPIO_PULL_MASK);
+@@ -230,11 +239,6 @@ static int lpi_config_set(struct pinctrl
+       lpi_gpio_write(pctrl, group, LPI_GPIO_CFG_REG, val);
+-      if (output_enabled) {
+-              val = u32_encode_bits(value ? 1 : 0, LPI_GPIO_VALUE_OUT_MASK);
+-              lpi_gpio_write(pctrl, group, LPI_GPIO_VALUE_REG, val);
+-      }
+-
+       return 0;
+ }
diff --git a/queue-6.3/pwm-meson-fix-axg-ao-mux-parents.patch b/queue-6.3/pwm-meson-fix-axg-ao-mux-parents.patch
new file mode 100644 (file)
index 0000000..74839bf
--- /dev/null
@@ -0,0 +1,36 @@
+From eb411c0cf59ae6344b34bc6f0d298a22b300627e Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Sun, 9 Apr 2023 17:15:52 +0200
+Subject: pwm: meson: Fix axg ao mux parents
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+commit eb411c0cf59ae6344b34bc6f0d298a22b300627e upstream.
+
+This fix is basically the same as 9bce02ef0dfa ("pwm: meson: Fix the
+G12A AO clock parents order"). Vendor driver referenced there has
+xtal as first parent also for axg ao. In addition fix the name
+of the aoclk81 clock. Apparently name aoclk81 as used by the vendor
+driver was changed when mainlining the axg clock driver.
+
+Fixes: bccaa3f917c9 ("pwm: meson: Add clock source configuration for Meson-AXG")
+Cc: stable@vger.kernel.org
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pwm/pwm-meson.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pwm/pwm-meson.c
++++ b/drivers/pwm/pwm-meson.c
+@@ -418,7 +418,7 @@ static const struct meson_pwm_data pwm_a
+ };
+ static const char * const pwm_axg_ao_parent_names[] = {
+-      "aoclk81", "xtal", "fclk_div4", "fclk_div5"
++      "xtal", "axg_ao_clk81", "fclk_div4", "fclk_div5"
+ };
+ static const struct meson_pwm_data pwm_axg_ao_data = {
diff --git a/queue-6.3/pwm-meson-fix-g12a-ao-clk81-name.patch b/queue-6.3/pwm-meson-fix-g12a-ao-clk81-name.patch
new file mode 100644 (file)
index 0000000..e8a2b60
--- /dev/null
@@ -0,0 +1,42 @@
+From 9e4fa80ab7ef9eb4f7b1ea9fc31e0eb040e85e25 Mon Sep 17 00:00:00 2001
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Tue, 11 Apr 2023 07:34:11 +0200
+Subject: pwm: meson: Fix g12a ao clk81 name
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+commit 9e4fa80ab7ef9eb4f7b1ea9fc31e0eb040e85e25 upstream.
+
+Fix the name of the aoclk81 clock. Apparently name aoclk81 as used by
+the vendor driver was changed when mainlining the g12a clock driver.
+
+Fixes: f41efceb46e6 ("pwm: meson: Add clock source configuration for Meson G12A")
+Cc: stable@vger.kernel.org
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pwm/pwm-meson.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/pwm/pwm-meson.c
++++ b/drivers/pwm/pwm-meson.c
+@@ -427,7 +427,7 @@ static const struct meson_pwm_data pwm_a
+ };
+ static const char * const pwm_g12a_ao_ab_parent_names[] = {
+-      "xtal", "aoclk81", "fclk_div4", "fclk_div5"
++      "xtal", "g12a_ao_clk81", "fclk_div4", "fclk_div5"
+ };
+ static const struct meson_pwm_data pwm_g12a_ao_ab_data = {
+@@ -436,7 +436,7 @@ static const struct meson_pwm_data pwm_g
+ };
+ static const char * const pwm_g12a_ao_cd_parent_names[] = {
+-      "xtal", "aoclk81",
++      "xtal", "g12a_ao_clk81",
+ };
+ static const struct meson_pwm_data pwm_g12a_ao_cd_data = {
diff --git a/queue-6.3/rcu-avoid-stack-overflow-due-to-__rcu_irq_enter_check_tick-being-kprobe-ed.patch b/queue-6.3/rcu-avoid-stack-overflow-due-to-__rcu_irq_enter_check_tick-being-kprobe-ed.patch
new file mode 100644 (file)
index 0000000..4e7cf39
--- /dev/null
@@ -0,0 +1,130 @@
+From 7a29fb4a4771124bc61de397dbfc1554dbbcc19c Mon Sep 17 00:00:00 2001
+From: Zheng Yejian <zhengyejian1@huawei.com>
+Date: Fri, 6 Jan 2023 15:09:34 +0800
+Subject: rcu: Avoid stack overflow due to __rcu_irq_enter_check_tick() being kprobe-ed
+
+From: Zheng Yejian <zhengyejian1@huawei.com>
+
+commit 7a29fb4a4771124bc61de397dbfc1554dbbcc19c upstream.
+
+Registering a kprobe on __rcu_irq_enter_check_tick() can cause kernel
+stack overflow as shown below. This issue can be reproduced by enabling
+CONFIG_NO_HZ_FULL and booting the kernel with argument "nohz_full=",
+and then giving the following commands at the shell prompt:
+
+  # cd /sys/kernel/tracing/
+  # echo 'p:mp1 __rcu_irq_enter_check_tick' >> kprobe_events
+  # echo 1 > events/kprobes/enable
+
+This commit therefore adds __rcu_irq_enter_check_tick() to the kprobes
+blacklist using NOKPROBE_SYMBOL().
+
+Insufficient stack space to handle exception!
+ESR: 0x00000000f2000004 -- BRK (AArch64)
+FAR: 0x0000ffffccf3e510
+Task stack:     [0xffff80000ad30000..0xffff80000ad38000]
+IRQ stack:      [0xffff800008050000..0xffff800008058000]
+Overflow stack: [0xffff089c36f9f310..0xffff089c36fa0310]
+CPU: 5 PID: 190 Comm: bash Not tainted 6.2.0-rc2-00320-g1f5abbd77e2c #19
+Hardware name: linux,dummy-virt (DT)
+pstate: 400003c5 (nZcv DAIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+pc : __rcu_irq_enter_check_tick+0x0/0x1b8
+lr : ct_nmi_enter+0x11c/0x138
+sp : ffff80000ad30080
+x29: ffff80000ad30080 x28: ffff089c82e20000 x27: 0000000000000000
+x26: 0000000000000000 x25: ffff089c02a8d100 x24: 0000000000000000
+x23: 00000000400003c5 x22: 0000ffffccf3e510 x21: ffff089c36fae148
+x20: ffff80000ad30120 x19: ffffa8da8fcce148 x18: 0000000000000000
+x17: 0000000000000000 x16: 0000000000000000 x15: ffffa8da8e44ea6c
+x14: ffffa8da8e44e968 x13: ffffa8da8e03136c x12: 1fffe113804d6809
+x11: ffff6113804d6809 x10: 0000000000000a60 x9 : dfff800000000000
+x8 : ffff089c026b404f x7 : 00009eec7fb297f7 x6 : 0000000000000001
+x5 : ffff80000ad30120 x4 : dfff800000000000 x3 : ffffa8da8e3016f4
+x2 : 0000000000000003 x1 : 0000000000000000 x0 : 0000000000000000
+Kernel panic - not syncing: kernel stack overflow
+CPU: 5 PID: 190 Comm: bash Not tainted 6.2.0-rc2-00320-g1f5abbd77e2c #19
+Hardware name: linux,dummy-virt (DT)
+Call trace:
+ dump_backtrace+0xf8/0x108
+ show_stack+0x20/0x30
+ dump_stack_lvl+0x68/0x84
+ dump_stack+0x1c/0x38
+ panic+0x214/0x404
+ add_taint+0x0/0xf8
+ panic_bad_stack+0x144/0x160
+ handle_bad_stack+0x38/0x58
+ __bad_stack+0x78/0x7c
+ __rcu_irq_enter_check_tick+0x0/0x1b8
+ arm64_enter_el1_dbg.isra.0+0x14/0x20
+ el1_dbg+0x2c/0x90
+ el1h_64_sync_handler+0xcc/0xe8
+ el1h_64_sync+0x64/0x68
+ __rcu_irq_enter_check_tick+0x0/0x1b8
+ arm64_enter_el1_dbg.isra.0+0x14/0x20
+ el1_dbg+0x2c/0x90
+ el1h_64_sync_handler+0xcc/0xe8
+ el1h_64_sync+0x64/0x68
+ __rcu_irq_enter_check_tick+0x0/0x1b8
+ arm64_enter_el1_dbg.isra.0+0x14/0x20
+ el1_dbg+0x2c/0x90
+ el1h_64_sync_handler+0xcc/0xe8
+ el1h_64_sync+0x64/0x68
+ __rcu_irq_enter_check_tick+0x0/0x1b8
+ [...]
+ el1_dbg+0x2c/0x90
+ el1h_64_sync_handler+0xcc/0xe8
+ el1h_64_sync+0x64/0x68
+ __rcu_irq_enter_check_tick+0x0/0x1b8
+ arm64_enter_el1_dbg.isra.0+0x14/0x20
+ el1_dbg+0x2c/0x90
+ el1h_64_sync_handler+0xcc/0xe8
+ el1h_64_sync+0x64/0x68
+ __rcu_irq_enter_check_tick+0x0/0x1b8
+ arm64_enter_el1_dbg.isra.0+0x14/0x20
+ el1_dbg+0x2c/0x90
+ el1h_64_sync_handler+0xcc/0xe8
+ el1h_64_sync+0x64/0x68
+ __rcu_irq_enter_check_tick+0x0/0x1b8
+ el1_interrupt+0x28/0x60
+ el1h_64_irq_handler+0x18/0x28
+ el1h_64_irq+0x64/0x68
+ __ftrace_set_clr_event_nolock+0x98/0x198
+ __ftrace_set_clr_event+0x58/0x80
+ system_enable_write+0x144/0x178
+ vfs_write+0x174/0x738
+ ksys_write+0xd0/0x188
+ __arm64_sys_write+0x4c/0x60
+ invoke_syscall+0x64/0x180
+ el0_svc_common.constprop.0+0x84/0x160
+ do_el0_svc+0x48/0xe8
+ el0_svc+0x34/0xd0
+ el0t_64_sync_handler+0xb8/0xc0
+ el0t_64_sync+0x190/0x194
+SMP: stopping secondary CPUs
+Kernel Offset: 0x28da86000000 from 0xffff800008000000
+PHYS_OFFSET: 0xfffff76600000000
+CPU features: 0x00000,01a00100,0000421b
+Memory Limit: none
+
+Acked-by: Joel Fernandes (Google) <joel@joelfernandes.org>
+Link: https://lore.kernel.org/all/20221119040049.795065-1-zhengyejian1@huawei.com/
+Fixes: aaf2bc50df1f ("rcu: Abstract out rcu_irq_enter_check_tick() from rcu_nmi_enter()")
+Signed-off-by: Zheng Yejian <zhengyejian1@huawei.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/rcu/tree.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/kernel/rcu/tree.c
++++ b/kernel/rcu/tree.c
+@@ -640,6 +640,7 @@ void __rcu_irq_enter_check_tick(void)
+       }
+       raw_spin_unlock_rcu_node(rdp->mynode);
+ }
++NOKPROBE_SYMBOL(__rcu_irq_enter_check_tick);
+ #endif /* CONFIG_NO_HZ_FULL */
+ /*
diff --git a/queue-6.3/reiserfs-add-security-prefix-to-xattr-name-in-reiserfs_security_write.patch b/queue-6.3/reiserfs-add-security-prefix-to-xattr-name-in-reiserfs_security_write.patch
new file mode 100644 (file)
index 0000000..c3377df
--- /dev/null
@@ -0,0 +1,54 @@
+From d82dcd9e21b77d338dc4875f3d4111f0db314a7c Mon Sep 17 00:00:00 2001
+From: Roberto Sassu <roberto.sassu@huawei.com>
+Date: Fri, 31 Mar 2023 14:32:18 +0200
+Subject: reiserfs: Add security prefix to xattr name in reiserfs_security_write()
+
+From: Roberto Sassu <roberto.sassu@huawei.com>
+
+commit d82dcd9e21b77d338dc4875f3d4111f0db314a7c upstream.
+
+Reiserfs sets a security xattr at inode creation time in two stages: first,
+it calls reiserfs_security_init() to obtain the xattr from active LSMs;
+then, it calls reiserfs_security_write() to actually write that xattr.
+
+Unfortunately, it seems there is a wrong expectation that LSMs provide the
+full xattr name in the form 'security.<suffix>'. However, LSMs always
+provided just the suffix, causing reiserfs to not write the xattr at all
+(if the suffix is shorter than the prefix), or to write an xattr with the
+wrong name.
+
+Add a temporary buffer in reiserfs_security_write(), and write to it the
+full xattr name, before passing it to reiserfs_xattr_set_handle().
+
+Also replace the name length check with a check that the full xattr name is
+not larger than XATTR_NAME_MAX.
+
+Cc: stable@vger.kernel.org # v2.6.x
+Fixes: 57fe60df6241 ("reiserfs: add atomic addition of selinux attributes during inode creation")
+Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/reiserfs/xattr_security.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/fs/reiserfs/xattr_security.c
++++ b/fs/reiserfs/xattr_security.c
+@@ -82,11 +82,15 @@ int reiserfs_security_write(struct reise
+                           struct inode *inode,
+                           struct reiserfs_security_handle *sec)
+ {
++      char xattr_name[XATTR_NAME_MAX + 1] = XATTR_SECURITY_PREFIX;
+       int error;
+-      if (strlen(sec->name) < sizeof(XATTR_SECURITY_PREFIX))
++
++      if (XATTR_SECURITY_PREFIX_LEN + strlen(sec->name) > XATTR_NAME_MAX)
+               return -EINVAL;
+-      error = reiserfs_xattr_set_handle(th, inode, sec->name, sec->value,
++      strlcat(xattr_name, sec->name, sizeof(xattr_name));
++
++      error = reiserfs_xattr_set_handle(th, inode, xattr_name, sec->value,
+                                         sec->length, XATTR_CREATE);
+       if (error == -ENODATA || error == -EOPNOTSUPP)
+               error = 0;
diff --git a/queue-6.3/relayfs-fix-out-of-bounds-access-in-relay_file_read.patch b/queue-6.3/relayfs-fix-out-of-bounds-access-in-relay_file_read.patch
new file mode 100644 (file)
index 0000000..3a7dfac
--- /dev/null
@@ -0,0 +1,77 @@
+From 43ec16f1450f4936025a9bdf1a273affdb9732c1 Mon Sep 17 00:00:00 2001
+From: Zhang Zhengming <zhang.zhengming@h3c.com>
+Date: Wed, 19 Apr 2023 12:02:03 +0800
+Subject: relayfs: fix out-of-bounds access in relay_file_read
+
+From: Zhang Zhengming <zhang.zhengming@h3c.com>
+
+commit 43ec16f1450f4936025a9bdf1a273affdb9732c1 upstream.
+
+There is a crash in relay_file_read, as the var from
+point to the end of last subbuf.
+
+The oops looks something like:
+pc : __arch_copy_to_user+0x180/0x310
+lr : relay_file_read+0x20c/0x2c8
+Call trace:
+ __arch_copy_to_user+0x180/0x310
+ full_proxy_read+0x68/0x98
+ vfs_read+0xb0/0x1d0
+ ksys_read+0x6c/0xf0
+ __arm64_sys_read+0x20/0x28
+ el0_svc_common.constprop.3+0x84/0x108
+ do_el0_svc+0x74/0x90
+ el0_svc+0x1c/0x28
+ el0_sync_handler+0x88/0xb0
+ el0_sync+0x148/0x180
+
+We get the condition by analyzing the vmcore:
+
+1). The last produced byte and last consumed byte
+    both at the end of the last subbuf
+
+2). A softirq calls function(e.g __blk_add_trace)
+    to write relay buffer occurs when an program is calling
+    relay_file_read_avail().
+
+        relay_file_read
+                relay_file_read_avail
+                        relay_file_read_consume(buf, 0, 0);
+                        //interrupted by softirq who will write subbuf
+                        ....
+                        return 1;
+                //read_start point to the end of the last subbuf
+                read_start = relay_file_read_start_pos
+                //avail is equal to subsize
+                avail = relay_file_read_subbuf_avail
+                //from  points to an invalid memory address
+                from = buf->start + read_start
+                //system is crashed
+                copy_to_user(buffer, from, avail)
+
+Link: https://lkml.kernel.org/r/20230419040203.37676-1-zhang.zhengming@h3c.com
+Fixes: 8d62fdebdaf9 ("relay file read: start-pos fix")
+Signed-off-by: Zhang Zhengming <zhang.zhengming@h3c.com>
+Reviewed-by: Zhao Lei <zhao_lei1@hoperun.com>
+Reviewed-by: Zhou Kete <zhou.kete@h3c.com>
+Reviewed-by: Pengcheng Yang <yangpc@wangsu.com>
+Cc: Jens Axboe <axboe@kernel.dk>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/relay.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/kernel/relay.c
++++ b/kernel/relay.c
+@@ -989,7 +989,8 @@ static size_t relay_file_read_start_pos(
+       size_t subbuf_size = buf->chan->subbuf_size;
+       size_t n_subbufs = buf->chan->n_subbufs;
+       size_t consumed = buf->subbufs_consumed % n_subbufs;
+-      size_t read_pos = consumed * subbuf_size + buf->bytes_consumed;
++      size_t read_pos = (consumed * subbuf_size + buf->bytes_consumed)
++                      % (n_subbufs * subbuf_size);
+       read_subbuf = read_pos / subbuf_size;
+       padding = buf->padding[read_subbuf];
diff --git a/queue-6.3/ring-buffer-ensure-proper-resetting-of-atomic-variables-in-ring_buffer_reset_online_cpus.patch b/queue-6.3/ring-buffer-ensure-proper-resetting-of-atomic-variables-in-ring_buffer_reset_online_cpus.patch
new file mode 100644 (file)
index 0000000..286bd50
--- /dev/null
@@ -0,0 +1,81 @@
+From 7c339fb4d8577792378136c15fde773cfb863cb8 Mon Sep 17 00:00:00 2001
+From: Tze-nan Wu <Tze-nan.Wu@mediatek.com>
+Date: Wed, 26 Apr 2023 14:20:23 +0800
+Subject: ring-buffer: Ensure proper resetting of atomic variables in ring_buffer_reset_online_cpus
+
+From: Tze-nan Wu <Tze-nan.Wu@mediatek.com>
+
+commit 7c339fb4d8577792378136c15fde773cfb863cb8 upstream.
+
+In ring_buffer_reset_online_cpus, the buffer_size_kb write operation
+may permanently fail if the cpu_online_mask changes between two
+for_each_online_buffer_cpu loops. The number of increases and decreases
+on both cpu_buffer->resize_disabled and cpu_buffer->record_disabled may be
+inconsistent, causing some CPUs to have non-zero values for these atomic
+variables after the function returns.
+
+This issue can be reproduced by "echo 0 > trace" while hotplugging cpu.
+After reproducing success, we can find out buffer_size_kb will not be
+functional anymore.
+
+To prevent leaving 'resize_disabled' and 'record_disabled' non-zero after
+ring_buffer_reset_online_cpus returns, we ensure that each atomic variable
+has been set up before atomic_sub() to it.
+
+Link: https://lore.kernel.org/linux-trace-kernel/20230426062027.17451-1-Tze-nan.Wu@mediatek.com
+
+Cc: stable@vger.kernel.org
+Cc: <mhiramat@kernel.org>
+Cc: npiggin@gmail.com
+Fixes: b23d7a5f4a07 ("ring-buffer: speed up buffer resets by avoiding synchronize_rcu for each CPU")
+Reviewed-by: Cheng-Jui Wang <cheng-jui.wang@mediatek.com>
+Signed-off-by: Tze-nan Wu <Tze-nan.Wu@mediatek.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/ring_buffer.c |   16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -5345,6 +5345,9 @@ void ring_buffer_reset_cpu(struct trace_
+ }
+ EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu);
++/* Flag to ensure proper resetting of atomic variables */
++#define RESET_BIT     (1 << 30)
++
+ /**
+  * ring_buffer_reset_online_cpus - reset a ring buffer per CPU buffer
+  * @buffer: The ring buffer to reset a per cpu buffer of
+@@ -5361,20 +5364,27 @@ void ring_buffer_reset_online_cpus(struc
+       for_each_online_buffer_cpu(buffer, cpu) {
+               cpu_buffer = buffer->buffers[cpu];
+-              atomic_inc(&cpu_buffer->resize_disabled);
++              atomic_add(RESET_BIT, &cpu_buffer->resize_disabled);
+               atomic_inc(&cpu_buffer->record_disabled);
+       }
+       /* Make sure all commits have finished */
+       synchronize_rcu();
+-      for_each_online_buffer_cpu(buffer, cpu) {
++      for_each_buffer_cpu(buffer, cpu) {
+               cpu_buffer = buffer->buffers[cpu];
++              /*
++               * If a CPU came online during the synchronize_rcu(), then
++               * ignore it.
++               */
++              if (!(atomic_read(&cpu_buffer->resize_disabled) & RESET_BIT))
++                      continue;
++
+               reset_disabled_cpu_buffer(cpu_buffer);
+               atomic_dec(&cpu_buffer->record_disabled);
+-              atomic_dec(&cpu_buffer->resize_disabled);
++              atomic_sub(RESET_BIT, &cpu_buffer->resize_disabled);
+       }
+       mutex_unlock(&buffer->mutex);
diff --git a/queue-6.3/ring-buffer-sync-irq-works-before-buffer-destruction.patch b/queue-6.3/ring-buffer-sync-irq-works-before-buffer-destruction.patch
new file mode 100644 (file)
index 0000000..c40eff9
--- /dev/null
@@ -0,0 +1,94 @@
+From 675751bb20634f981498c7d66161584080cc061e Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Thu, 27 Apr 2023 17:59:20 +0200
+Subject: ring-buffer: Sync IRQ works before buffer destruction
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 675751bb20634f981498c7d66161584080cc061e upstream.
+
+If something was written to the buffer just before destruction,
+it may be possible (maybe not in a real system, but it did
+happen in ARCH=um with time-travel) to destroy the ringbuffer
+before the IRQ work ran, leading this KASAN report (or a crash
+without KASAN):
+
+    BUG: KASAN: slab-use-after-free in irq_work_run_list+0x11a/0x13a
+    Read of size 8 at addr 000000006d640a48 by task swapper/0
+
+    CPU: 0 PID: 0 Comm: swapper Tainted: G        W  O       6.3.0-rc1 #7
+    Stack:
+     60c4f20f 0c203d48 41b58ab3 60f224fc
+     600477fa 60f35687 60c4f20f 601273dd
+     00000008 6101eb00 6101eab0 615be548
+    Call Trace:
+     [<60047a58>] show_stack+0x25e/0x282
+     [<60c609e0>] dump_stack_lvl+0x96/0xfd
+     [<60c50d4c>] print_report+0x1a7/0x5a8
+     [<603078d3>] kasan_report+0xc1/0xe9
+     [<60308950>] __asan_report_load8_noabort+0x1b/0x1d
+     [<60232844>] irq_work_run_list+0x11a/0x13a
+     [<602328b4>] irq_work_tick+0x24/0x34
+     [<6017f9dc>] update_process_times+0x162/0x196
+     [<6019f335>] tick_sched_handle+0x1a4/0x1c3
+     [<6019fd9e>] tick_sched_timer+0x79/0x10c
+     [<601812b9>] __hrtimer_run_queues.constprop.0+0x425/0x695
+     [<60182913>] hrtimer_interrupt+0x16c/0x2c4
+     [<600486a3>] um_timer+0x164/0x183
+     [...]
+
+    Allocated by task 411:
+     save_stack_trace+0x99/0xb5
+     stack_trace_save+0x81/0x9b
+     kasan_save_stack+0x2d/0x54
+     kasan_set_track+0x34/0x3e
+     kasan_save_alloc_info+0x25/0x28
+     ____kasan_kmalloc+0x8b/0x97
+     __kasan_kmalloc+0x10/0x12
+     __kmalloc+0xb2/0xe8
+     load_elf_phdrs+0xee/0x182
+     [...]
+
+    The buggy address belongs to the object at 000000006d640800
+     which belongs to the cache kmalloc-1k of size 1024
+    The buggy address is located 584 bytes inside of
+     freed 1024-byte region [000000006d640800, 000000006d640c00)
+
+Add the appropriate irq_work_sync() so the work finishes before
+the buffers are destroyed.
+
+Prior to the commit in the Fixes tag below, there was only a
+single global IRQ work, so this issue didn't exist.
+
+Link: https://lore.kernel.org/linux-trace-kernel/20230427175920.a76159263122.I8295e405c44362a86c995e9c2c37e3e03810aa56@changeid
+
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Fixes: 15693458c4bc ("tracing/ring-buffer: Move poll wake ups into ring buffer code")
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/ring_buffer.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -1774,6 +1774,8 @@ static void rb_free_cpu_buffer(struct ri
+       struct list_head *head = cpu_buffer->pages;
+       struct buffer_page *bpage, *tmp;
++      irq_work_sync(&cpu_buffer->irq_work.work);
++
+       free_buffer_page(cpu_buffer->reader_page);
+       if (head) {
+@@ -1880,6 +1882,8 @@ ring_buffer_free(struct trace_buffer *bu
+       cpuhp_state_remove_instance(CPUHP_TRACE_RB_PREPARE, &buffer->node);
++      irq_work_sync(&buffer->irq_work.work);
++
+       for_each_buffer_cpu(buffer, cpu)
+               rb_free_cpu_buffer(buffer->buffers[cpu]);
index 9abaa917e26b1a8432f9ddcf8ff2ac3a8bcab1d9..37a02cc2e2602987d6fac506f2d5d9ca779b78de 100644 (file)
@@ -39,3 +39,25 @@ iio-addac-stx104-fix-race-condition-for-stx104_write_raw.patch
 kheaders-use-array-declaration-instead-of-char.patch
 wifi-mt76-add-missing-locking-to-protect-against-concurrent-rx-status-calls.patch
 wifi-rtw89-correct-5-mhz-mask-setting.patch
+pwm-meson-fix-axg-ao-mux-parents.patch
+pwm-meson-fix-g12a-ao-clk81-name.patch
+soundwire-qcom-correct-setting-ignore-bit-on-v1.5.1.patch
+pinctrl-qcom-lpass-lpi-set-output-value-before-enabling-output.patch
+ring-buffer-ensure-proper-resetting-of-atomic-variables-in-ring_buffer_reset_online_cpus.patch
+ring-buffer-sync-irq-works-before-buffer-destruction.patch
+crypto-api-demote-bug_on-in-crypto_unregister_alg-to-a-warn_on.patch
+crypto-safexcel-cleanup-ring-irq-workqueues-on-load-failure.patch
+crypto-arm64-aes-neonbs-fix-crash-with-cfi-enabled.patch
+crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch
+crypto-ccp-don-t-initialize-ccp-for-psp-0x1649.patch
+rcu-avoid-stack-overflow-due-to-__rcu_irq_enter_check_tick-being-kprobe-ed.patch
+reiserfs-add-security-prefix-to-xattr-name-in-reiserfs_security_write.patch
+cpufreq-qcom-cpufreq-hw-fix-double-io-unmap-and-resource-release-on-exit.patch
+kvm-x86-pmu-disallow-legacy-lbrs-if-architectural-lbrs-are-available.patch
+kvm-nvmx-emulate-nops-in-l2-and-pause-if-it-s-not-intercepted.patch
+kvm-arm64-avoid-vcpu-mutex-v.-kvm-lock-inversion-in-cpu_on.patch
+kvm-arm64-avoid-lock-inversion-when-setting-the-vm-register-width.patch
+kvm-arm64-use-config_lock-to-protect-data-ordered-against-kvm_run.patch
+kvm-arm64-use-config_lock-to-protect-vgic-state.patch
+kvm-arm64-vgic-don-t-acquire-its_lock-before-config_lock.patch
+relayfs-fix-out-of-bounds-access-in-relay_file_read.patch
diff --git a/queue-6.3/soundwire-qcom-correct-setting-ignore-bit-on-v1.5.1.patch b/queue-6.3/soundwire-qcom-correct-setting-ignore-bit-on-v1.5.1.patch
new file mode 100644 (file)
index 0000000..3bc170f
--- /dev/null
@@ -0,0 +1,35 @@
+From bd934f77eeac377e81ddac8673803e7334b82d3d Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Date: Wed, 22 Feb 2023 15:03:43 +0100
+Subject: soundwire: qcom: correct setting ignore bit on v1.5.1
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+commit bd934f77eeac377e81ddac8673803e7334b82d3d upstream.
+
+According to the comment and to downstream sources, the
+SWRM_CONTINUE_EXEC_ON_CMD_IGNORE in SWRM_CMD_FIFO_CFG_ADDR register
+should be set for v1.5.1 and newer, so fix the >= operator.
+
+Fixes: 542d3491cdd7 ("soundwire: qcom: set continue execution flag for ignored commands")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230222140343.188691-1-krzysztof.kozlowski@linaro.org
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/soundwire/qcom.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/soundwire/qcom.c
++++ b/drivers/soundwire/qcom.c
+@@ -704,7 +704,7 @@ static int qcom_swrm_init(struct qcom_sw
+       }
+       /* Configure number of retries of a read/write cmd */
+-      if (ctrl->version > 0x01050001) {
++      if (ctrl->version >= 0x01050001) {
+               /* Only for versions >= 1.5.1 */
+               ctrl->reg_write(ctrl, SWRM_CMD_FIFO_CFG_ADDR,
+                               SWRM_RD_WR_CMD_RETRIES |