From 317a08e694e8ae2e3182b80c26b4b8e89f4ef3c1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 6 May 2023 11:34:08 +0900 Subject: [PATCH] 6.2-stable patches 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 --- ...o-unmap-and-resource-release-on-exit.patch | 101 +++ ...n-crypto_unregister_alg-to-a-warn_on.patch | 45 ++ ...es-neonbs-fix-crash-with-cfi-enabled.patch | 65 ++ ...-don-t-initialize-ccp-for-psp-0x1649.patch | 37 + ...-ring-irq-workqueues-on-load-failure.patch | 154 ++++ ...gr-fix-rng-performance-in-fuzz-tests.patch | 712 ++++++++++++++++++ ...n-when-setting-the-vm-register-width.patch | 118 +++ ...utex-v.-kvm-lock-inversion-in-cpu_on.patch | 268 +++++++ ...protect-data-ordered-against-kvm_run.patch | 162 ++++ ...se-config_lock-to-protect-vgic-state.patch | 531 +++++++++++++ ...-acquire-its_lock-before-config_lock.patch | 78 ++ ...l2-and-pause-if-it-s-not-intercepted.patch | 68 ++ ...-if-architectural-lbrs-are-available.patch | 44 ++ ...-output-value-before-enabling-output.patch | 54 ++ .../pwm-meson-fix-axg-ao-mux-parents.patch | 36 + .../pwm-meson-fix-g12a-ao-clk81-name.patch | 42 ++ ...irq_enter_check_tick-being-kprobe-ed.patch | 130 ++++ ...attr-name-in-reiserfs_security_write.patch | 54 ++ ...-of-bounds-access-in-relay_file_read.patch | 77 ++ ...les-in-ring_buffer_reset_online_cpus.patch | 81 ++ ...-irq-works-before-buffer-destruction.patch | 94 +++ queue-6.2/series | 22 + ...correct-setting-ignore-bit-on-v1.5.1.patch | 35 + 23 files changed, 3008 insertions(+) create mode 100644 queue-6.2/cpufreq-qcom-cpufreq-hw-fix-double-io-unmap-and-resource-release-on-exit.patch create mode 100644 queue-6.2/crypto-api-demote-bug_on-in-crypto_unregister_alg-to-a-warn_on.patch create mode 100644 queue-6.2/crypto-arm64-aes-neonbs-fix-crash-with-cfi-enabled.patch create mode 100644 queue-6.2/crypto-ccp-don-t-initialize-ccp-for-psp-0x1649.patch create mode 100644 queue-6.2/crypto-safexcel-cleanup-ring-irq-workqueues-on-load-failure.patch create mode 100644 queue-6.2/crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch create mode 100644 queue-6.2/kvm-arm64-avoid-lock-inversion-when-setting-the-vm-register-width.patch create mode 100644 queue-6.2/kvm-arm64-avoid-vcpu-mutex-v.-kvm-lock-inversion-in-cpu_on.patch create mode 100644 queue-6.2/kvm-arm64-use-config_lock-to-protect-data-ordered-against-kvm_run.patch create mode 100644 queue-6.2/kvm-arm64-use-config_lock-to-protect-vgic-state.patch create mode 100644 queue-6.2/kvm-arm64-vgic-don-t-acquire-its_lock-before-config_lock.patch create mode 100644 queue-6.2/kvm-nvmx-emulate-nops-in-l2-and-pause-if-it-s-not-intercepted.patch create mode 100644 queue-6.2/kvm-x86-pmu-disallow-legacy-lbrs-if-architectural-lbrs-are-available.patch create mode 100644 queue-6.2/pinctrl-qcom-lpass-lpi-set-output-value-before-enabling-output.patch create mode 100644 queue-6.2/pwm-meson-fix-axg-ao-mux-parents.patch create mode 100644 queue-6.2/pwm-meson-fix-g12a-ao-clk81-name.patch create mode 100644 queue-6.2/rcu-avoid-stack-overflow-due-to-__rcu_irq_enter_check_tick-being-kprobe-ed.patch create mode 100644 queue-6.2/reiserfs-add-security-prefix-to-xattr-name-in-reiserfs_security_write.patch create mode 100644 queue-6.2/relayfs-fix-out-of-bounds-access-in-relay_file_read.patch create mode 100644 queue-6.2/ring-buffer-ensure-proper-resetting-of-atomic-variables-in-ring_buffer_reset_online_cpus.patch create mode 100644 queue-6.2/ring-buffer-sync-irq-works-before-buffer-destruction.patch create mode 100644 queue-6.2/soundwire-qcom-correct-setting-ignore-bit-on-v1.5.1.patch diff --git a/queue-6.2/cpufreq-qcom-cpufreq-hw-fix-double-io-unmap-and-resource-release-on-exit.patch b/queue-6.2/cpufreq-qcom-cpufreq-hw-fix-double-io-unmap-and-resource-release-on-exit.patch new file mode 100644 index 00000000000..f1e4b287357 --- /dev/null +++ b/queue-6.2/cpufreq-qcom-cpufreq-hw-fix-double-io-unmap-and-resource-release-on-exit.patch @@ -0,0 +1,101 @@ +From ba5e770c9698782bc203bbf5cf3b36a77720bdbe Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +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 + +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: +Cc: Manivannan Sadhasivam +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Manivannan Sadhasivam +Reviewed-by: Bjorn Andersson +Signed-off-by: Viresh Kumar +Signed-off-by: Greg Kroah-Hartman +--- + 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.2/crypto-api-demote-bug_on-in-crypto_unregister_alg-to-a-warn_on.patch b/queue-6.2/crypto-api-demote-bug_on-in-crypto_unregister_alg-to-a-warn_on.patch new file mode 100644 index 00000000000..79c83b22936 --- /dev/null +++ b/queue-6.2/crypto-api-demote-bug_on-in-crypto_unregister_alg-to-a-warn_on.patch @@ -0,0 +1,45 @@ +From a543ada7db729514ddd3ba4efa45f4c7b802ad85 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= +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 + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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.2/crypto-arm64-aes-neonbs-fix-crash-with-cfi-enabled.patch b/queue-6.2/crypto-arm64-aes-neonbs-fix-crash-with-cfi-enabled.patch new file mode 100644 index 00000000000..f8e3fa92df8 --- /dev/null +++ b/queue-6.2/crypto-arm64-aes-neonbs-fix-crash-with-cfi-enabled.patch @@ -0,0 +1,65 @@ +From 47446d7cd42358ca7d7a544f2f7823db03f616ff Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Sun, 26 Feb 2023 22:32:23 -0800 +Subject: crypto: arm64/aes-neonbs - fix crash with CFI enabled + +From: Eric Biggers + +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 +Reviewed-by: Ard Biesheuvel +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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 ++#include + #include + + .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.2/crypto-ccp-don-t-initialize-ccp-for-psp-0x1649.patch b/queue-6.2/crypto-ccp-don-t-initialize-ccp-for-psp-0x1649.patch new file mode 100644 index 00000000000..9e6093d7e75 --- /dev/null +++ b/queue-6.2/crypto-ccp-don-t-initialize-ccp-for-psp-0x1649.patch @@ -0,0 +1,37 @@ +From c79a3169b9f3633c215b55857eba5921e5b49217 Mon Sep 17 00:00:00 2001 +From: Mario Limonciello +Date: Mon, 3 Apr 2023 12:38:01 -0500 +Subject: crypto: ccp - Don't initialize CCP for PSP 0x1649 + +From: Mario Limonciello + +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 +Acked-by: Tom Lendacky +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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.2/crypto-safexcel-cleanup-ring-irq-workqueues-on-load-failure.patch b/queue-6.2/crypto-safexcel-cleanup-ring-irq-workqueues-on-load-failure.patch new file mode 100644 index 00000000000..1d457b1eb44 --- /dev/null +++ b/queue-6.2/crypto-safexcel-cleanup-ring-irq-workqueues-on-load-failure.patch @@ -0,0 +1,154 @@ +From ca25c00ccbc5f942c63897ed23584cfc66e8ec81 Mon Sep 17 00:00:00 2001 +From: Jonathan McDowell +Date: Tue, 28 Feb 2023 18:28:58 +0000 +Subject: crypto: safexcel - Cleanup ring IRQ workqueues on load failure + +From: Jonathan McDowell + +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 +Cc: stable@vger.kernel.org +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -1639,19 +1639,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; +@@ -1665,7 +1669,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; +@@ -1677,8 +1682,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; +@@ -1695,16 +1702,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.2/crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch b/queue-6.2/crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch new file mode 100644 index 00000000000..f5926b3f5eb --- /dev/null +++ b/queue-6.2/crypto-testmgr-fix-rng-performance-in-fuzz-tests.patch @@ -0,0 +1,712 @@ +From f900fde28883602b6c5e1027a6c912b673382aaf Mon Sep 17 00:00:00 2001 +From: Eric Biggers +Date: Mon, 27 Feb 2023 10:29:47 -0800 +Subject: crypto: testmgr - fix RNG performance in fuzz tests + +From: Eric Biggers + +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 +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman +--- + crypto/testmgr.c | 266 ++++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 169 insertions(+), 97 deletions(-) + +--- a/crypto/testmgr.c ++++ b/crypto/testmgr.c +@@ -852,12 +852,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: +@@ -870,43 +908,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; +@@ -915,11 +954,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; +@@ -927,28 +966,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) + { +@@ -959,24 +998,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; +@@ -988,7 +1029,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) { +@@ -1023,7 +1064,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; +@@ -1035,7 +1077,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; +@@ -1050,12 +1092,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"); +@@ -1070,36 +1112,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); + } + +@@ -1612,11 +1655,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); +@@ -1634,15 +1680,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. +@@ -1652,9 +1699,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); +@@ -1688,6 +1735,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; +@@ -1701,6 +1749,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) +@@ -1769,10 +1819,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); +@@ -2174,11 +2225,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); +@@ -2194,6 +2248,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; +@@ -2212,24 +2267,26 @@ struct aead_extra_tests_ctx { + * here means the full ciphertext including the authentication tag. The + * authentication tag (and hence also the ciphertext) is assumed to be nonempty. + */ +-static void mutate_aead_message(struct aead_testvec *vec, bool aad_iv, ++static void mutate_aead_message(struct rnd_state *rng, ++ struct aead_testvec *vec, bool aad_iv, + unsigned int ivsize) + { + const unsigned int aad_tail_size = aad_iv ? ivsize : 0; + const unsigned int authsize = vec->clen - vec->plen; + +- if (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); + } + } + +@@ -2240,7 +2297,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) +@@ -2249,17 +2307,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; +@@ -2271,7 +2330,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); +@@ -2291,7 +2350,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) +@@ -2305,7 +2364,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, +@@ -2321,18 +2381,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)) +@@ -2341,11 +2401,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; + +@@ -2356,7 +2416,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); +@@ -2368,7 +2428,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, +@@ -2399,7 +2459,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, +@@ -2489,12 +2550,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, +@@ -2533,6 +2595,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; +@@ -2922,11 +2985,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); +@@ -2944,7 +3010,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) +@@ -2958,17 +3025,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) +@@ -3010,6 +3077,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; +@@ -3027,6 +3095,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) +@@ -3111,9 +3181,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.2/kvm-arm64-avoid-lock-inversion-when-setting-the-vm-register-width.patch b/queue-6.2/kvm-arm64-avoid-lock-inversion-when-setting-the-vm-register-width.patch new file mode 100644 index 00000000000..a25c3c834f9 --- /dev/null +++ b/queue-6.2/kvm-arm64-avoid-lock-inversion-when-setting-the-vm-register-width.patch @@ -0,0 +1,118 @@ +From c43120afb5c66a3465c7468f5cf9806a26484cde Mon Sep 17 00:00:00 2001 +From: Oliver Upton +Date: Mon, 27 Mar 2023 16:47:45 +0000 +Subject: KVM: arm64: Avoid lock inversion when setting the VM register width + +From: Oliver Upton + +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 +Link: https://lore.kernel.org/kvmarm/f6452cdd-65ff-34b8-bab0-5c06416da5f6@arm.com/ +Tested-by: Jeremy Linton +Signed-off-by: Oliver Upton +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230327164747.2466958-3-oliver.upton@linux.dev +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -191,6 +191,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 +@@ -138,6 +138,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; +@@ -338,6 +348,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 +@@ -200,7 +200,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)) { + /* +@@ -253,9 +253,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.2/kvm-arm64-avoid-vcpu-mutex-v.-kvm-lock-inversion-in-cpu_on.patch b/queue-6.2/kvm-arm64-avoid-vcpu-mutex-v.-kvm-lock-inversion-in-cpu_on.patch new file mode 100644 index 00000000000..89a62c54b53 --- /dev/null +++ b/queue-6.2/kvm-arm64-avoid-vcpu-mutex-v.-kvm-lock-inversion-in-cpu_on.patch @@ -0,0 +1,268 @@ +From 0acc7239c20a8401b8968c2adace8f7c9b0295ae Mon Sep 17 00:00:00 2001 +From: Oliver Upton +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 + +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 +Signed-off-by: Oliver Upton +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230327164747.2466958-2-oliver.upton@linux.dev +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -482,6 +482,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 +@@ -336,6 +336,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); +@@ -453,34 +455,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; + } +@@ -490,12 +499,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); +@@ -504,6 +515,8 @@ int kvm_arch_vcpu_ioctl_set_mpstate(stru + ret = -EINVAL; + } + ++ spin_unlock(&vcpu->arch.mp_state_lock); ++ + return ret; + } + +@@ -1223,7 +1236,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 +@@ -255,15 +255,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.2/kvm-arm64-use-config_lock-to-protect-data-ordered-against-kvm_run.patch b/queue-6.2/kvm-arm64-use-config_lock-to-protect-data-ordered-against-kvm_run.patch new file mode 100644 index 00000000000..9a764d25383 --- /dev/null +++ b/queue-6.2/kvm-arm64-use-config_lock-to-protect-data-ordered-against-kvm_run.patch @@ -0,0 +1,162 @@ +From 4bba7f7def6f278266dadf845da472cfbfed784e Mon Sep 17 00:00:00 2001 +From: Oliver Upton +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 + +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 +Signed-off-by: Oliver Upton +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230327164747.2466958-4-oliver.upton@linux.dev +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -634,9 +634,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 +@@ -951,7 +951,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.2/kvm-arm64-use-config_lock-to-protect-vgic-state.patch b/queue-6.2/kvm-arm64-use-config_lock-to-protect-vgic-state.patch new file mode 100644 index 00000000000..424724e6ceb --- /dev/null +++ b/queue-6.2/kvm-arm64-use-config_lock-to-protect-vgic-state.patch @@ -0,0 +1,531 @@ +From f00327731131d1b5aa6a1aa9f50bcf8d620ace4c Mon Sep 17 00:00:00 2001 +From: Oliver Upton +Date: Mon, 27 Mar 2023 16:47:47 +0000 +Subject: KVM: arm64: Use config_lock to protect vgic state + +From: Oliver Upton + +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 +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230327164747.2466958-5-oliver.upton@linux.dev +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -527,13 +527,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; + } +@@ -622,13 +622,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, +@@ -659,13 +659,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.2/kvm-arm64-vgic-don-t-acquire-its_lock-before-config_lock.patch b/queue-6.2/kvm-arm64-vgic-don-t-acquire-its_lock-before-config_lock.patch new file mode 100644 index 00000000000..da3a162a7bf --- /dev/null +++ b/queue-6.2/kvm-arm64-vgic-don-t-acquire-its_lock-before-config_lock.patch @@ -0,0 +1,78 @@ +From 49e5d16b6fc003407a33a9961b4bcbb970bd1c76 Mon Sep 17 00:00:00 2001 +From: Oliver Upton +Date: Wed, 12 Apr 2023 06:27:33 +0000 +Subject: KVM: arm64: vgic: Don't acquire its_lock before config_lock + +From: Oliver Upton + +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 +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20230412062733.988229-1-oliver.upton@linux.dev +Signed-off-by: Greg Kroah-Hartman +--- + 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.2/kvm-nvmx-emulate-nops-in-l2-and-pause-if-it-s-not-intercepted.patch b/queue-6.2/kvm-nvmx-emulate-nops-in-l2-and-pause-if-it-s-not-intercepted.patch new file mode 100644 index 00000000000..d6627e6116d --- /dev/null +++ b/queue-6.2/kvm-nvmx-emulate-nops-in-l2-and-pause-if-it-s-not-intercepted.patch @@ -0,0 +1,68 @@ +From 4984563823f0034d3533854c1b50e729f5191089 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +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 + +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 +Cc: stable@vger.kernel.org +Reviewed-by: Paolo Bonzini +Link: https://lore.kernel.org/r/20230405002359.418138-1-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -7893,6 +7893,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.2/kvm-x86-pmu-disallow-legacy-lbrs-if-architectural-lbrs-are-available.patch b/queue-6.2/kvm-x86-pmu-disallow-legacy-lbrs-if-architectural-lbrs-are-available.patch new file mode 100644 index 00000000000..7b7e99b30c3 --- /dev/null +++ b/queue-6.2/kvm-x86-pmu-disallow-legacy-lbrs-if-architectural-lbrs-are-available.patch @@ -0,0 +1,44 @@ +From 098f4c061ea10b777033b71c10bd9fd706820ee9 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Sat, 28 Jan 2023 00:14:27 +0000 +Subject: KVM: x86/pmu: Disallow legacy LBRs if architectural LBRs are available + +From: Sean Christopherson + +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 +Cc: Like Xu +Reported-by: Paolo Bonzini +Fixes: be635e34c284 ("KVM: vmx/pmu: Expose LBR_FMT in the MSR_IA32_PERF_CAPABILITIES") +Tested-by: Like Xu +Link: https://lore.kernel.org/r/20230128001427.2548858-1-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -7749,9 +7749,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.2/pinctrl-qcom-lpass-lpi-set-output-value-before-enabling-output.patch b/queue-6.2/pinctrl-qcom-lpass-lpi-set-output-value-before-enabling-output.patch new file mode 100644 index 00000000000..1257bb170a5 --- /dev/null +++ b/queue-6.2/pinctrl-qcom-lpass-lpi-set-output-value-before-enabling-output.patch @@ -0,0 +1,54 @@ +From 163bfb0cb1f6fbf961cf912cbde57399ea1ae0e8 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Thu, 9 Mar 2023 16:49:46 +0100 +Subject: pinctrl: qcom: lpass-lpi: set output value before enabling output + +From: Krzysztof Kozlowski + +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: +Fixes: 6e261d1090d6 ("pinctrl: qcom: Add sm8250 lpass lpi pinctrl driver") +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20230309154949.658380-1-krzysztof.kozlowski@linaro.org +Signed-off-by: Linus Walleij +Signed-off-by: Greg Kroah-Hartman +--- + 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.2/pwm-meson-fix-axg-ao-mux-parents.patch b/queue-6.2/pwm-meson-fix-axg-ao-mux-parents.patch new file mode 100644 index 00000000000..74839bffb37 --- /dev/null +++ b/queue-6.2/pwm-meson-fix-axg-ao-mux-parents.patch @@ -0,0 +1,36 @@ +From eb411c0cf59ae6344b34bc6f0d298a22b300627e Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Sun, 9 Apr 2023 17:15:52 +0200 +Subject: pwm: meson: Fix axg ao mux parents + +From: Heiner Kallweit + +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 +Reviewed-by: Martin Blumenstingl +Signed-off-by: Thierry Reding +Signed-off-by: Greg Kroah-Hartman +--- + 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.2/pwm-meson-fix-g12a-ao-clk81-name.patch b/queue-6.2/pwm-meson-fix-g12a-ao-clk81-name.patch new file mode 100644 index 00000000000..e8a2b609f0b --- /dev/null +++ b/queue-6.2/pwm-meson-fix-g12a-ao-clk81-name.patch @@ -0,0 +1,42 @@ +From 9e4fa80ab7ef9eb4f7b1ea9fc31e0eb040e85e25 Mon Sep 17 00:00:00 2001 +From: Heiner Kallweit +Date: Tue, 11 Apr 2023 07:34:11 +0200 +Subject: pwm: meson: Fix g12a ao clk81 name + +From: Heiner Kallweit + +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 +Reviewed-by: Martin Blumenstingl +Signed-off-by: Thierry Reding +Signed-off-by: Greg Kroah-Hartman +--- + 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.2/rcu-avoid-stack-overflow-due-to-__rcu_irq_enter_check_tick-being-kprobe-ed.patch b/queue-6.2/rcu-avoid-stack-overflow-due-to-__rcu_irq_enter_check_tick-being-kprobe-ed.patch new file mode 100644 index 00000000000..9d383354de7 --- /dev/null +++ b/queue-6.2/rcu-avoid-stack-overflow-due-to-__rcu_irq_enter_check_tick-being-kprobe-ed.patch @@ -0,0 +1,130 @@ +From 7a29fb4a4771124bc61de397dbfc1554dbbcc19c Mon Sep 17 00:00:00 2001 +From: Zheng Yejian +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 + +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) +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 +Cc: stable@vger.kernel.org +Signed-off-by: Paul E. McKenney +Signed-off-by: Joel Fernandes (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/rcu/tree.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -659,6 +659,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.2/reiserfs-add-security-prefix-to-xattr-name-in-reiserfs_security_write.patch b/queue-6.2/reiserfs-add-security-prefix-to-xattr-name-in-reiserfs_security_write.patch new file mode 100644 index 00000000000..c3377df3ad4 --- /dev/null +++ b/queue-6.2/reiserfs-add-security-prefix-to-xattr-name-in-reiserfs_security_write.patch @@ -0,0 +1,54 @@ +From d82dcd9e21b77d338dc4875f3d4111f0db314a7c Mon Sep 17 00:00:00 2001 +From: Roberto Sassu +Date: Fri, 31 Mar 2023 14:32:18 +0200 +Subject: reiserfs: Add security prefix to xattr name in reiserfs_security_write() + +From: Roberto Sassu + +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.'. 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 +Signed-off-by: Paul Moore +Signed-off-by: Greg Kroah-Hartman +--- + 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.2/relayfs-fix-out-of-bounds-access-in-relay_file_read.patch b/queue-6.2/relayfs-fix-out-of-bounds-access-in-relay_file_read.patch new file mode 100644 index 00000000000..3a7dfac6b9f --- /dev/null +++ b/queue-6.2/relayfs-fix-out-of-bounds-access-in-relay_file_read.patch @@ -0,0 +1,77 @@ +From 43ec16f1450f4936025a9bdf1a273affdb9732c1 Mon Sep 17 00:00:00 2001 +From: Zhang Zhengming +Date: Wed, 19 Apr 2023 12:02:03 +0800 +Subject: relayfs: fix out-of-bounds access in relay_file_read + +From: Zhang Zhengming + +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 +Reviewed-by: Zhao Lei +Reviewed-by: Zhou Kete +Reviewed-by: Pengcheng Yang +Cc: Jens Axboe +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + 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.2/ring-buffer-ensure-proper-resetting-of-atomic-variables-in-ring_buffer_reset_online_cpus.patch b/queue-6.2/ring-buffer-ensure-proper-resetting-of-atomic-variables-in-ring_buffer_reset_online_cpus.patch new file mode 100644 index 00000000000..95d427c1ccc --- /dev/null +++ b/queue-6.2/ring-buffer-ensure-proper-resetting-of-atomic-variables-in-ring_buffer_reset_online_cpus.patch @@ -0,0 +1,81 @@ +From 7c339fb4d8577792378136c15fde773cfb863cb8 Mon Sep 17 00:00:00 2001 +From: Tze-nan Wu +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 + +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: +Cc: npiggin@gmail.com +Fixes: b23d7a5f4a07 ("ring-buffer: speed up buffer resets by avoiding synchronize_rcu for each CPU") +Reviewed-by: Cheng-Jui Wang +Signed-off-by: Tze-nan Wu +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -5349,6 +5349,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 +@@ -5365,20 +5368,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.2/ring-buffer-sync-irq-works-before-buffer-destruction.patch b/queue-6.2/ring-buffer-sync-irq-works-before-buffer-destruction.patch new file mode 100644 index 00000000000..398ac3d6abb --- /dev/null +++ b/queue-6.2/ring-buffer-sync-irq-works-before-buffer-destruction.patch @@ -0,0 +1,94 @@ +From 675751bb20634f981498c7d66161584080cc061e Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 27 Apr 2023 17:59:20 +0200 +Subject: ring-buffer: Sync IRQ works before buffer destruction + +From: Johannes Berg + +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 +Fixes: 15693458c4bc ("tracing/ring-buffer: Move poll wake ups into ring buffer code") +Signed-off-by: Johannes Berg +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/ring_buffer.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -1778,6 +1778,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) { +@@ -1884,6 +1886,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]); + diff --git a/queue-6.2/series b/queue-6.2/series index aeeb94b7b47..4a31a51acf4 100644 --- a/queue-6.2/series +++ b/queue-6.2/series @@ -60,3 +60,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.2/soundwire-qcom-correct-setting-ignore-bit-on-v1.5.1.patch b/queue-6.2/soundwire-qcom-correct-setting-ignore-bit-on-v1.5.1.patch new file mode 100644 index 00000000000..3bc170fe1ab --- /dev/null +++ b/queue-6.2/soundwire-qcom-correct-setting-ignore-bit-on-v1.5.1.patch @@ -0,0 +1,35 @@ +From bd934f77eeac377e81ddac8673803e7334b82d3d Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Wed, 22 Feb 2023 15:03:43 +0100 +Subject: soundwire: qcom: correct setting ignore bit on v1.5.1 + +From: Krzysztof Kozlowski + +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: +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20230222140343.188691-1-krzysztof.kozlowski@linaro.org +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman +--- + 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 | -- 2.47.3