From: Greg Kroah-Hartman Date: Tue, 17 Jun 2025 14:32:16 +0000 (+0200) Subject: 6.15-stable patches X-Git-Tag: v6.6.94~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ebc6cce0383ec45afb4f68322ea8f267294d4145;p=thirdparty%2Fkernel%2Fstable-queue.git 6.15-stable patches added patches: 9p-add-a-migrate_folio-method.patch don-t-propagate-mounts-into-detached-trees.patch mm-filemap-gate-dropbehind-invalidate-on-folio-dirty-writeback.patch mm-filemap-use-filemap_end_dropbehind-for-read-invalidation.patch nvmem-zynqmp_nvmem-unbreak-driver-after-cleanup.patch ring-buffer-do-not-trigger-warn_on-due-to-a-commit_overrun.patch ring-buffer-fix-buffer-locking-in-ring_buffer_subbuf_order_set.patch ring-buffer-move-cpus_read_lock-outside-of-buffer-mutex.patch tty-serial-8250_omap-fix-tx-with-dma-for-am33xx.patch usb-cdnsp-fix-issue-with-detecting-command-completion-event.patch usb-cdnsp-fix-issue-with-detecting-usb-3.2-speed.patch usb-flush-altsetting-0-endpoints-before-reinitializating-them-after-reset.patch usb-misc-onboard_usb_dev-fix-usb5744-initialization-sequence.patch usb-typec-tcpm-move-tcpm_queue_vdm_unlocked-to-asynchronous-work.patch usb-typec-tcpm-tcpci_maxim-fix-bounds-check-in-process_rx.patch usb-usbtmc-fix-read_stb-function-and-get_stb-ioctl.patch vmci-fix-race-between-vmci_host_setup_notify-and-vmci_ctx_unset_notify.patch x86-fred-signal-prevent-immediate-repeat-of-single-step-trap-on-return-from-sigtrap-handler.patch x86-hyperv-fix-apic-id-and-vp-index-confusion-in-hv_snp_boot_ap.patch x86-iopl-cure-tif_io_bitmap-inconsistencies.patch xen-arm-call-uaccess_ttbr0_enable-for-dm_op-hypercall.patch xfs-don-t-assume-perags-are-initialised-when-trimming-ags.patch --- diff --git a/queue-6.15/9p-add-a-migrate_folio-method.patch b/queue-6.15/9p-add-a-migrate_folio-method.patch new file mode 100644 index 0000000000..965371bf90 --- /dev/null +++ b/queue-6.15/9p-add-a-migrate_folio-method.patch @@ -0,0 +1,37 @@ +From 03ddd7725ed1b39cf9251e1a420559f25dac49b3 Mon Sep 17 00:00:00 2001 +From: "Matthew Wilcox (Oracle)" +Date: Wed, 2 Apr 2025 15:59:55 +0100 +Subject: 9p: Add a migrate_folio method + +From: Matthew Wilcox (Oracle) + +commit 03ddd7725ed1b39cf9251e1a420559f25dac49b3 upstream. + +The migration code used to be able to migrate dirty 9p folios by writing +them back using writepage. When the writepage method was removed, +we neglected to add a migrate_folio method, which means that dirty 9p +folios have been unmovable ever since. This reduced our success at +defragmenting memory on machines which use 9p heavily. + +Fixes: 80105ed2fd27 (9p: Use netfslib read/write_iter) +Cc: stable@vger.kernel.org +Cc: David Howells +Cc: v9fs@lists.linux.dev +Signed-off-by: "Matthew Wilcox (Oracle)" +Link: https://lore.kernel.org/r/20250402150005.2309458-2-willy@infradead.org +Acked-by: Dominique Martinet +Reviewed-by: David Howells +Signed-off-by: Christian Brauner +Signed-off-by: Greg Kroah-Hartman +--- + fs/9p/vfs_addr.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/9p/vfs_addr.c ++++ b/fs/9p/vfs_addr.c +@@ -165,4 +165,5 @@ const struct address_space_operations v9 + .invalidate_folio = netfs_invalidate_folio, + .direct_IO = noop_direct_IO, + .writepages = netfs_writepages, ++ .migrate_folio = filemap_migrate_folio, + }; diff --git a/queue-6.15/don-t-propagate-mounts-into-detached-trees.patch b/queue-6.15/don-t-propagate-mounts-into-detached-trees.patch new file mode 100644 index 0000000000..104ef30a76 --- /dev/null +++ b/queue-6.15/don-t-propagate-mounts-into-detached-trees.patch @@ -0,0 +1,109 @@ +From 3b5260d12b1fe76b566fe182de8abc586b827ed0 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 23 May 2025 19:20:36 -0400 +Subject: Don't propagate mounts into detached trees + +From: Al Viro + +commit 3b5260d12b1fe76b566fe182de8abc586b827ed0 upstream. + +All versions up to 6.14 did not propagate mount events into detached +tree. Shortly after 6.14 a merge of vfs-6.15-rc1.mount.namespace +(130e696aa68b) has changed that. + +Unfortunately, that has caused userland regressions (reported in +https://lore.kernel.org/all/CAOYeF9WQhFDe+BGW=Dp5fK8oRy5AgZ6zokVyTj1Wp4EUiYgt4w@mail.gmail.com/) + +Straight revert wouldn't be an option - in particular, the variant in 6.14 +had a bug that got fixed in d1ddc6f1d9f0 ("fix IS_MNT_PROPAGATING uses") +and we don't want to bring the bug back. + +This is a modification of manual revert posted by Christian, with changes +needed to avoid reintroducing the breakage in scenario described in +d1ddc6f1d9f0. + +Cc: stable@vger.kernel.org +Reported-by: Allison Karlitskaya +Tested-by: Allison Karlitskaya +Acked-by: Christian Brauner +Co-developed-by: Christian Brauner +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman +--- + fs/mount.h | 5 ----- + fs/namespace.c | 15 ++------------- + fs/pnode.c | 4 ++-- + 3 files changed, 4 insertions(+), 20 deletions(-) + +--- a/fs/mount.h ++++ b/fs/mount.h +@@ -7,10 +7,6 @@ + + extern struct list_head notify_list; + +-typedef __u32 __bitwise mntns_flags_t; +- +-#define MNTNS_PROPAGATING ((__force mntns_flags_t)(1 << 0)) +- + struct mnt_namespace { + struct ns_common ns; + struct mount * root; +@@ -37,7 +33,6 @@ struct mnt_namespace { + struct rb_node mnt_ns_tree_node; /* node in the mnt_ns_tree */ + struct list_head mnt_ns_list; /* entry in the sequential list of mounts namespace */ + refcount_t passive; /* number references not pinning @mounts */ +- mntns_flags_t mntns_flags; + } __randomize_layout; + + struct mnt_pcp { +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -3673,7 +3673,7 @@ static int do_move_mount(struct path *ol + if (!(attached ? check_mnt(old) : is_anon_ns(ns))) + goto out; + +- if (is_anon_ns(ns)) { ++ if (is_anon_ns(ns) && ns == p->mnt_ns) { + /* + * Ending up with two files referring to the root of the + * same anonymous mount namespace would cause an error +@@ -3681,16 +3681,7 @@ static int do_move_mount(struct path *ol + * twice into the mount tree which would be rejected + * later. But be explicit about it right here. + */ +- if ((is_anon_ns(p->mnt_ns) && ns == p->mnt_ns)) +- goto out; +- +- /* +- * If this is an anonymous mount tree ensure that mount +- * propagation can detect mounts that were just +- * propagated to the target mount tree so we don't +- * propagate onto them. +- */ +- ns->mntns_flags |= MNTNS_PROPAGATING; ++ goto out; + } else if (is_anon_ns(p->mnt_ns)) { + /* + * Don't allow moving an attached mount tree to an +@@ -3747,8 +3738,6 @@ static int do_move_mount(struct path *ol + if (attached) + put_mountpoint(old_mp); + out: +- if (is_anon_ns(ns)) +- ns->mntns_flags &= ~MNTNS_PROPAGATING; + unlock_mount(mp); + if (!err) { + if (attached) { +--- a/fs/pnode.c ++++ b/fs/pnode.c +@@ -231,8 +231,8 @@ static int propagate_one(struct mount *m + /* skip if mountpoint isn't visible in m */ + if (!is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) + return 0; +- /* skip if m is in the anon_ns we are emptying */ +- if (m->mnt_ns->mntns_flags & MNTNS_PROPAGATING) ++ /* skip if m is in the anon_ns */ ++ if (is_anon_ns(m->mnt_ns)) + return 0; + + if (peers(m, last_dest)) { diff --git a/queue-6.15/mm-filemap-gate-dropbehind-invalidate-on-folio-dirty-writeback.patch b/queue-6.15/mm-filemap-gate-dropbehind-invalidate-on-folio-dirty-writeback.patch new file mode 100644 index 0000000000..18a4b8314b --- /dev/null +++ b/queue-6.15/mm-filemap-gate-dropbehind-invalidate-on-folio-dirty-writeback.patch @@ -0,0 +1,56 @@ +From 095f627add86a6ddda2c2cfd563b0ee05d0172b2 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Tue, 27 May 2025 07:28:52 -0600 +Subject: mm/filemap: gate dropbehind invalidate on folio !dirty && !writeback + +From: Jens Axboe + +commit 095f627add86a6ddda2c2cfd563b0ee05d0172b2 upstream. + +It's possible for the folio to either get marked for writeback or +redirtied. Add a helper, filemap_end_dropbehind(), which guards the +folio_unmap_invalidate() call behind check for the folio being both +non-dirty and not under writeback AFTER the folio lock has been +acquired. Use this helper folio_end_dropbehind_write(). + +Cc: stable@vger.kernel.org +Reported-by: Al Viro +Fixes: fb7d3bc41493 ("mm/filemap: drop streaming/uncached pages when writeback completes") +Link: https://lore.kernel.org/linux-fsdevel/20250525083209.GS2023217@ZenIV/ +Signed-off-by: Jens Axboe +Link: https://lore.kernel.org/20250527133255.452431-2-axboe@kernel.dk +Signed-off-by: Christian Brauner +Signed-off-by: Greg Kroah-Hartman +--- + mm/filemap.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -1589,6 +1589,16 @@ int folio_wait_private_2_killable(struct + } + EXPORT_SYMBOL(folio_wait_private_2_killable); + ++static void filemap_end_dropbehind(struct folio *folio) ++{ ++ struct address_space *mapping = folio->mapping; ++ ++ VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio); ++ ++ if (mapping && !folio_test_writeback(folio) && !folio_test_dirty(folio)) ++ folio_unmap_invalidate(mapping, folio, 0); ++} ++ + /* + * If folio was marked as dropbehind, then pages should be dropped when writeback + * completes. Do that now. If we fail, it's likely because of a big folio - +@@ -1604,8 +1614,7 @@ static void folio_end_dropbehind_write(s + * invalidation in that case. + */ + if (in_task() && folio_trylock(folio)) { +- if (folio->mapping) +- folio_unmap_invalidate(folio->mapping, folio, 0); ++ filemap_end_dropbehind(folio); + folio_unlock(folio); + } + } diff --git a/queue-6.15/mm-filemap-use-filemap_end_dropbehind-for-read-invalidation.patch b/queue-6.15/mm-filemap-use-filemap_end_dropbehind-for-read-invalidation.patch new file mode 100644 index 0000000000..4e0ea6a24d --- /dev/null +++ b/queue-6.15/mm-filemap-use-filemap_end_dropbehind-for-read-invalidation.patch @@ -0,0 +1,56 @@ +From 25b065a744ff0c1099bb357be1c40030b5a14c07 Mon Sep 17 00:00:00 2001 +From: Jens Axboe +Date: Tue, 27 May 2025 07:28:53 -0600 +Subject: mm/filemap: use filemap_end_dropbehind() for read invalidation + +From: Jens Axboe + +commit 25b065a744ff0c1099bb357be1c40030b5a14c07 upstream. + +Use the filemap_end_dropbehind() helper rather than calling +folio_unmap_invalidate() directly, as we need to check if the folio has +been redirtied or marked for writeback once the folio lock has been +re-acquired. + +Cc: stable@vger.kernel.org +Reported-by: Trond Myklebust +Fixes: 8026e49bff9b ("mm/filemap: add read support for RWF_DONTCACHE") +Link: https://lore.kernel.org/linux-fsdevel/ba8a9805331ce258a622feaca266b163db681a10.camel@hammerspace.com/ +Signed-off-by: Jens Axboe +Link: https://lore.kernel.org/20250527133255.452431-3-axboe@kernel.dk +Signed-off-by: Christian Brauner +Signed-off-by: Greg Kroah-Hartman +--- + mm/filemap.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2644,8 +2644,7 @@ static inline bool pos_same_folio(loff_t + return (pos1 >> shift == pos2 >> shift); + } + +-static void filemap_end_dropbehind_read(struct address_space *mapping, +- struct folio *folio) ++static void filemap_end_dropbehind_read(struct folio *folio) + { + if (!folio_test_dropbehind(folio)) + return; +@@ -2653,7 +2652,7 @@ static void filemap_end_dropbehind_read( + return; + if (folio_trylock(folio)) { + if (folio_test_clear_dropbehind(folio)) +- folio_unmap_invalidate(mapping, folio, 0); ++ filemap_end_dropbehind(folio); + folio_unlock(folio); + } + } +@@ -2774,7 +2773,7 @@ put_folios: + for (i = 0; i < folio_batch_count(&fbatch); i++) { + struct folio *folio = fbatch.folios[i]; + +- filemap_end_dropbehind_read(mapping, folio); ++ filemap_end_dropbehind_read(folio); + folio_put(folio); + } + folio_batch_init(&fbatch); diff --git a/queue-6.15/nvmem-zynqmp_nvmem-unbreak-driver-after-cleanup.patch b/queue-6.15/nvmem-zynqmp_nvmem-unbreak-driver-after-cleanup.patch new file mode 100644 index 0000000000..e3801ba224 --- /dev/null +++ b/queue-6.15/nvmem-zynqmp_nvmem-unbreak-driver-after-cleanup.patch @@ -0,0 +1,37 @@ +From fe8abdd175d7b547ae1a612757e7902bcd62e9cf Mon Sep 17 00:00:00 2001 +From: Peter Korsgaard +Date: Fri, 9 May 2025 13:24:07 +0100 +Subject: nvmem: zynqmp_nvmem: unbreak driver after cleanup + +From: Peter Korsgaard + +commit fe8abdd175d7b547ae1a612757e7902bcd62e9cf upstream. + +Commit 29be47fcd6a0 ("nvmem: zynqmp_nvmem: zynqmp_nvmem_probe cleanup") +changed the driver to expect the device pointer to be passed as the +"context", but in nvmem the context parameter comes from nvmem_config.priv +which is never set - Leading to null pointer exceptions when the device is +accessed. + +Fixes: 29be47fcd6a0 ("nvmem: zynqmp_nvmem: zynqmp_nvmem_probe cleanup") +Cc: stable +Signed-off-by: Peter Korsgaard +Reviewed-by: Michal Simek +Tested-by: Michal Simek +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20250509122407.11763-3-srini@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvmem/zynqmp_nvmem.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/nvmem/zynqmp_nvmem.c ++++ b/drivers/nvmem/zynqmp_nvmem.c +@@ -213,6 +213,7 @@ static int zynqmp_nvmem_probe(struct pla + econfig.word_size = 1; + econfig.size = ZYNQMP_NVMEM_SIZE; + econfig.dev = dev; ++ econfig.priv = dev; + econfig.add_legacy_fixed_of_cells = true; + econfig.reg_read = zynqmp_nvmem_read; + econfig.reg_write = zynqmp_nvmem_write; diff --git a/queue-6.15/ring-buffer-do-not-trigger-warn_on-due-to-a-commit_overrun.patch b/queue-6.15/ring-buffer-do-not-trigger-warn_on-due-to-a-commit_overrun.patch new file mode 100644 index 0000000000..810dbd2328 --- /dev/null +++ b/queue-6.15/ring-buffer-do-not-trigger-warn_on-due-to-a-commit_overrun.patch @@ -0,0 +1,145 @@ +From 4fc78a7c9ca994e1da5d3940704d4e8f0ea8c5e4 Mon Sep 17 00:00:00 2001 +From: Steven Rostedt +Date: Wed, 28 May 2025 12:15:55 -0400 +Subject: ring-buffer: Do not trigger WARN_ON() due to a commit_overrun + +From: Steven Rostedt + +commit 4fc78a7c9ca994e1da5d3940704d4e8f0ea8c5e4 upstream. + +When reading a memory mapped buffer the reader page is just swapped out +with the last page written in the write buffer. If the reader page is the +same as the commit buffer (the buffer that is currently being written to) +it was assumed that it should never have missed events. If it does, it +triggers a WARN_ON_ONCE(). + +But there just happens to be one scenario where this can legitimately +happen. That is on a commit_overrun. A commit overrun is when an interrupt +preempts an event being written to the buffer and then the interrupt adds +so many new events that it fills and wraps the buffer back to the commit. +Any new events would then be dropped and be reported as "missed_events". + +In this case, the next page to read is the commit buffer and after the +swap of the reader page, the reader page will be the commit buffer, but +this time there will be missed events and this triggers the following +warning: + + ------------[ cut here ]------------ + WARNING: CPU: 2 PID: 1127 at kernel/trace/ring_buffer.c:7357 ring_buffer_map_get_reader+0x49a/0x780 + Modules linked in: kvm_intel kvm irqbypass + CPU: 2 UID: 0 PID: 1127 Comm: trace-cmd Not tainted 6.15.0-rc7-test-00004-g478bc2824b45-dirty #564 PREEMPT + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 + RIP: 0010:ring_buffer_map_get_reader+0x49a/0x780 + Code: 00 00 00 48 89 fe 48 c1 ee 03 80 3c 2e 00 0f 85 ec 01 00 00 4d 3b a6 a8 00 00 00 0f 85 8a fd ff ff 48 85 c0 0f 84 55 fe ff ff <0f> 0b e9 4e fe ff ff be 08 00 00 00 4c 89 54 24 58 48 89 54 24 50 + RSP: 0018:ffff888121787dc0 EFLAGS: 00010002 + RAX: 00000000000006a2 RBX: ffff888100062800 RCX: ffffffff8190cb49 + RDX: ffff888126934c00 RSI: 1ffff11020200a15 RDI: ffff8881010050a8 + RBP: dffffc0000000000 R08: 0000000000000000 R09: ffffed1024d26982 + R10: ffff888126934c17 R11: ffff8881010050a8 R12: ffff888126934c00 + R13: ffff8881010050b8 R14: ffff888101005000 R15: ffff888126930008 + FS: 00007f95c8cd7540(0000) GS:ffff8882b576e000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f95c8de4dc0 CR3: 0000000128452002 CR4: 0000000000172ef0 + Call Trace: + + ? __pfx_ring_buffer_map_get_reader+0x10/0x10 + tracing_buffers_ioctl+0x283/0x370 + __x64_sys_ioctl+0x134/0x190 + do_syscall_64+0x79/0x1c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + RIP: 0033:0x7f95c8de48db + Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00 + RSP: 002b:00007ffe037ba110 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 + RAX: ffffffffffffffda RBX: 00007ffe037bb2b0 RCX: 00007f95c8de48db + RDX: 0000000000000000 RSI: 0000000000005220 RDI: 0000000000000006 + RBP: 00007ffe037ba180 R08: 0000000000000000 R09: 0000000000000000 + R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 + R13: 00007ffe037bb6f8 R14: 00007f95c9065000 R15: 00005575c7492c90 + + irq event stamp: 5080 + hardirqs last enabled at (5079): [] _raw_spin_unlock_irqrestore+0x50/0x70 + hardirqs last disabled at (5080): [] _raw_spin_lock_irqsave+0x63/0x70 + softirqs last enabled at (4182): [] handle_softirqs+0x552/0x710 + softirqs last disabled at (4159): [] __irq_exit_rcu+0x107/0x210 + ---[ end trace 0000000000000000 ]--- + +The above was triggered by running on a kernel with both lockdep and KASAN +as well as kmemleak enabled and executing the following command: + + # perf record -o perf-test.dat -a -- trace-cmd record --nosplice -e all -p function hackbench 50 + +With perf interjecting a lot of interrupts and trace-cmd enabling all +events as well as function tracing, with lockdep, KASAN and kmemleak +enabled, it could cause an interrupt preempting an event being written to +add enough events to wrap the buffer. trace-cmd was modified to have +--nosplice use mmap instead of reading the buffer. + +The way to differentiate this case from the normal case of there only +being one page written to where the swap of the reader page received that +one page (which is the commit page), check if the tail page is on the +reader page. The difference between the commit page and the tail page is +that the tail page is where new writes go to, and the commit page holds +the first write that hasn't been committed yet. In the case of an +interrupt preempting the write of an event and filling the buffer, it +would move the tail page but not the commit page. + +Have the warning only trigger if the tail page is also on the reader page, +and also print out the number of events dropped by a commit overrun as +that can not yet be safely added to the page so that the reader can see +there were events dropped. + +Cc: stable@vger.kernel.org +Cc: Mathieu Desnoyers +Cc: Vincent Donnefort +Link: https://lore.kernel.org/20250528121555.2066527e@gandalf.local.home +Fixes: fe832be05a8ee ("ring-buffer: Have mmapped ring buffer keep track of missed events") +Reviewed-by: Masami Hiramatsu (Google) +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/ring_buffer.c | 26 ++++++++++++++++++-------- + 1 file changed, 18 insertions(+), 8 deletions(-) + +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -7284,8 +7284,8 @@ consume: + /* Check if any events were dropped */ + missed_events = cpu_buffer->lost_events; + +- if (cpu_buffer->reader_page != cpu_buffer->commit_page) { +- if (missed_events) { ++ if (missed_events) { ++ if (cpu_buffer->reader_page != cpu_buffer->commit_page) { + struct buffer_data_page *bpage = reader->page; + unsigned int commit; + /* +@@ -7306,13 +7306,23 @@ consume: + local_add(RB_MISSED_STORED, &bpage->commit); + } + local_add(RB_MISSED_EVENTS, &bpage->commit); ++ } else if (!WARN_ONCE(cpu_buffer->reader_page == cpu_buffer->tail_page, ++ "Reader on commit with %ld missed events", ++ missed_events)) { ++ /* ++ * There shouldn't be any missed events if the tail_page ++ * is on the reader page. But if the tail page is not on the ++ * reader page and the commit_page is, that would mean that ++ * there's a commit_overrun (an interrupt preempted an ++ * addition of an event and then filled the buffer ++ * with new events). In this case it's not an ++ * error, but it should still be reported. ++ * ++ * TODO: Add missed events to the page for user space to know. ++ */ ++ pr_info("Ring buffer [%d] commit overrun lost %ld events at timestamp:%lld\n", ++ cpu, missed_events, cpu_buffer->reader_page->page->time_stamp); + } +- } else { +- /* +- * There really shouldn't be any missed events if the commit +- * is on the reader page. +- */ +- WARN_ON_ONCE(missed_events); + } + + cpu_buffer->lost_events = 0; diff --git a/queue-6.15/ring-buffer-fix-buffer-locking-in-ring_buffer_subbuf_order_set.patch b/queue-6.15/ring-buffer-fix-buffer-locking-in-ring_buffer_subbuf_order_set.patch new file mode 100644 index 0000000000..483668f0dd --- /dev/null +++ b/queue-6.15/ring-buffer-fix-buffer-locking-in-ring_buffer_subbuf_order_set.patch @@ -0,0 +1,55 @@ +From 40ee2afafc1d9fe3aa44a6fbe440d78a5c96a72e Mon Sep 17 00:00:00 2001 +From: Dmitry Antipov +Date: Fri, 6 Jun 2025 14:22:42 +0300 +Subject: ring-buffer: Fix buffer locking in ring_buffer_subbuf_order_set() + +From: Dmitry Antipov + +commit 40ee2afafc1d9fe3aa44a6fbe440d78a5c96a72e upstream. + +Enlarge the critical section in ring_buffer_subbuf_order_set() to +ensure that error handling takes place with per-buffer mutex held, +thus preventing list corruption and other concurrency-related issues. + +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Cc: Mathieu Desnoyers +Cc: Tzvetomir Stoyanov +Link: https://lore.kernel.org/20250606112242.1510605-1-dmantipov@yandex.ru +Reported-by: syzbot+05d673e83ec640f0ced9@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=05d673e83ec640f0ced9 +Fixes: f9b94daa542a8 ("ring-buffer: Set new size of the ring buffer sub page") +Signed-off-by: Dmitry Antipov +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/ring_buffer.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -6764,7 +6764,7 @@ int ring_buffer_subbuf_order_set(struct + old_size = buffer->subbuf_size; + + /* prevent another thread from changing buffer sizes */ +- mutex_lock(&buffer->mutex); ++ guard(mutex)(&buffer->mutex); + atomic_inc(&buffer->record_disabled); + + /* Make sure all commits have finished */ +@@ -6869,7 +6869,6 @@ int ring_buffer_subbuf_order_set(struct + } + + atomic_dec(&buffer->record_disabled); +- mutex_unlock(&buffer->mutex); + + return 0; + +@@ -6878,7 +6877,6 @@ error: + buffer->subbuf_size = old_size; + + atomic_dec(&buffer->record_disabled); +- mutex_unlock(&buffer->mutex); + + for_each_buffer_cpu(buffer, cpu) { + cpu_buffer = buffer->buffers[cpu]; diff --git a/queue-6.15/ring-buffer-move-cpus_read_lock-outside-of-buffer-mutex.patch b/queue-6.15/ring-buffer-move-cpus_read_lock-outside-of-buffer-mutex.patch new file mode 100644 index 0000000000..8a64d05a78 --- /dev/null +++ b/queue-6.15/ring-buffer-move-cpus_read_lock-outside-of-buffer-mutex.patch @@ -0,0 +1,240 @@ +From c98cc9797b7009308fff73d41bc1d08642dab77a Mon Sep 17 00:00:00 2001 +From: Steven Rostedt +Date: Tue, 27 May 2025 10:58:20 -0400 +Subject: ring-buffer: Move cpus_read_lock() outside of buffer->mutex + +From: Steven Rostedt + +commit c98cc9797b7009308fff73d41bc1d08642dab77a upstream. + +Running a modified trace-cmd record --nosplice where it does a mmap of the +ring buffer when '--nosplice' is set, caused the following lockdep splat: + + ====================================================== + WARNING: possible circular locking dependency detected + 6.15.0-rc7-test-00002-gfb7d03d8a82f #551 Not tainted + ------------------------------------------------------ + trace-cmd/1113 is trying to acquire lock: + ffff888100062888 (&buffer->mutex){+.+.}-{4:4}, at: ring_buffer_map+0x11c/0xe70 + + but task is already holding lock: + ffff888100a5f9f8 (&cpu_buffer->mapping_lock){+.+.}-{4:4}, at: ring_buffer_map+0xcf/0xe70 + + which lock already depends on the new lock. + + the existing dependency chain (in reverse order) is: + + -> #5 (&cpu_buffer->mapping_lock){+.+.}-{4:4}: + __mutex_lock+0x192/0x18c0 + ring_buffer_map+0xcf/0xe70 + tracing_buffers_mmap+0x1c4/0x3b0 + __mmap_region+0xd8d/0x1f70 + do_mmap+0x9d7/0x1010 + vm_mmap_pgoff+0x20b/0x390 + ksys_mmap_pgoff+0x2e9/0x440 + do_syscall_64+0x79/0x1c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + -> #4 (&mm->mmap_lock){++++}-{4:4}: + __might_fault+0xa5/0x110 + _copy_to_user+0x22/0x80 + _perf_ioctl+0x61b/0x1b70 + perf_ioctl+0x62/0x90 + __x64_sys_ioctl+0x134/0x190 + do_syscall_64+0x79/0x1c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + -> #3 (&cpuctx_mutex){+.+.}-{4:4}: + __mutex_lock+0x192/0x18c0 + perf_event_init_cpu+0x325/0x7c0 + perf_event_init+0x52a/0x5b0 + start_kernel+0x263/0x3e0 + x86_64_start_reservations+0x24/0x30 + x86_64_start_kernel+0x95/0xa0 + common_startup_64+0x13e/0x141 + + -> #2 (pmus_lock){+.+.}-{4:4}: + __mutex_lock+0x192/0x18c0 + perf_event_init_cpu+0xb7/0x7c0 + cpuhp_invoke_callback+0x2c0/0x1030 + __cpuhp_invoke_callback_range+0xbf/0x1f0 + _cpu_up+0x2e7/0x690 + cpu_up+0x117/0x170 + cpuhp_bringup_mask+0xd5/0x120 + bringup_nonboot_cpus+0x13d/0x170 + smp_init+0x2b/0xf0 + kernel_init_freeable+0x441/0x6d0 + kernel_init+0x1e/0x160 + ret_from_fork+0x34/0x70 + ret_from_fork_asm+0x1a/0x30 + + -> #1 (cpu_hotplug_lock){++++}-{0:0}: + cpus_read_lock+0x2a/0xd0 + ring_buffer_resize+0x610/0x14e0 + __tracing_resize_ring_buffer.part.0+0x42/0x120 + tracing_set_tracer+0x7bd/0xa80 + tracing_set_trace_write+0x132/0x1e0 + vfs_write+0x21c/0xe80 + ksys_write+0xf9/0x1c0 + do_syscall_64+0x79/0x1c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + -> #0 (&buffer->mutex){+.+.}-{4:4}: + __lock_acquire+0x1405/0x2210 + lock_acquire+0x174/0x310 + __mutex_lock+0x192/0x18c0 + ring_buffer_map+0x11c/0xe70 + tracing_buffers_mmap+0x1c4/0x3b0 + __mmap_region+0xd8d/0x1f70 + do_mmap+0x9d7/0x1010 + vm_mmap_pgoff+0x20b/0x390 + ksys_mmap_pgoff+0x2e9/0x440 + do_syscall_64+0x79/0x1c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + + other info that might help us debug this: + + Chain exists of: + &buffer->mutex --> &mm->mmap_lock --> &cpu_buffer->mapping_lock + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock(&cpu_buffer->mapping_lock); + lock(&mm->mmap_lock); + lock(&cpu_buffer->mapping_lock); + lock(&buffer->mutex); + + *** DEADLOCK *** + + 2 locks held by trace-cmd/1113: + #0: ffff888106b847e0 (&mm->mmap_lock){++++}-{4:4}, at: vm_mmap_pgoff+0x192/0x390 + #1: ffff888100a5f9f8 (&cpu_buffer->mapping_lock){+.+.}-{4:4}, at: ring_buffer_map+0xcf/0xe70 + + stack backtrace: + CPU: 5 UID: 0 PID: 1113 Comm: trace-cmd Not tainted 6.15.0-rc7-test-00002-gfb7d03d8a82f #551 PREEMPT + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 + Call Trace: + + dump_stack_lvl+0x6e/0xa0 + print_circular_bug.cold+0x178/0x1be + check_noncircular+0x146/0x160 + __lock_acquire+0x1405/0x2210 + lock_acquire+0x174/0x310 + ? ring_buffer_map+0x11c/0xe70 + ? ring_buffer_map+0x11c/0xe70 + ? __mutex_lock+0x169/0x18c0 + __mutex_lock+0x192/0x18c0 + ? ring_buffer_map+0x11c/0xe70 + ? ring_buffer_map+0x11c/0xe70 + ? function_trace_call+0x296/0x370 + ? __pfx___mutex_lock+0x10/0x10 + ? __pfx_function_trace_call+0x10/0x10 + ? __pfx___mutex_lock+0x10/0x10 + ? _raw_spin_unlock+0x2d/0x50 + ? ring_buffer_map+0x11c/0xe70 + ? ring_buffer_map+0x11c/0xe70 + ? __mutex_lock+0x5/0x18c0 + ring_buffer_map+0x11c/0xe70 + ? do_raw_spin_lock+0x12d/0x270 + ? find_held_lock+0x2b/0x80 + ? _raw_spin_unlock+0x2d/0x50 + ? rcu_is_watching+0x15/0xb0 + ? _raw_spin_unlock+0x2d/0x50 + ? trace_preempt_on+0xd0/0x110 + tracing_buffers_mmap+0x1c4/0x3b0 + __mmap_region+0xd8d/0x1f70 + ? ring_buffer_lock_reserve+0x99/0xff0 + ? __pfx___mmap_region+0x10/0x10 + ? ring_buffer_lock_reserve+0x99/0xff0 + ? __pfx_ring_buffer_lock_reserve+0x10/0x10 + ? __pfx_ring_buffer_lock_reserve+0x10/0x10 + ? bpf_lsm_mmap_addr+0x4/0x10 + ? security_mmap_addr+0x46/0xd0 + ? lock_is_held_type+0xd9/0x130 + do_mmap+0x9d7/0x1010 + ? 0xffffffffc0370095 + ? __pfx_do_mmap+0x10/0x10 + vm_mmap_pgoff+0x20b/0x390 + ? __pfx_vm_mmap_pgoff+0x10/0x10 + ? 0xffffffffc0370095 + ksys_mmap_pgoff+0x2e9/0x440 + do_syscall_64+0x79/0x1c0 + entry_SYSCALL_64_after_hwframe+0x76/0x7e + RIP: 0033:0x7fb0963a7de2 + Code: 00 00 00 0f 1f 44 00 00 41 f7 c1 ff 0f 00 00 75 27 55 89 cd 53 48 89 fb 48 85 ff 74 3b 41 89 ea 48 89 df b8 09 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 76 5b 5d c3 0f 1f 00 48 8b 05 e1 9f 0d 00 64 + RSP: 002b:00007ffdcc8fb878 EFLAGS: 00000246 ORIG_RAX: 0000000000000009 + RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fb0963a7de2 + RDX: 0000000000000001 RSI: 0000000000001000 RDI: 0000000000000000 + RBP: 0000000000000001 R08: 0000000000000006 R09: 0000000000000000 + R10: 0000000000000001 R11: 0000000000000246 R12: 0000000000000000 + R13: 00007ffdcc8fbe68 R14: 00007fb096628000 R15: 00005633e01a5c90 + + +The issue is that cpus_read_lock() is taken within buffer->mutex. The +memory mapped pages are taken with the mmap_lock held. The buffer->mutex +is taken within the cpu_buffer->mapping_lock. There's quite a chain with +all these locks, where the deadlock can be fixed by moving the +cpus_read_lock() outside the taking of the buffer->mutex. + +Cc: stable@vger.kernel.org +Cc: Masami Hiramatsu +Cc: Mathieu Desnoyers +Cc: Vincent Donnefort +Link: https://lore.kernel.org/20250527105820.0f45d045@gandalf.local.home +Fixes: 117c39200d9d7 ("ring-buffer: Introducing ring-buffer mapping functions") +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Greg Kroah-Hartman +--- + kernel/trace/ring_buffer.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -2849,6 +2849,12 @@ int ring_buffer_resize(struct trace_buff + if (nr_pages < 2) + nr_pages = 2; + ++ /* ++ * Keep CPUs from coming online while resizing to synchronize ++ * with new per CPU buffers being created. ++ */ ++ guard(cpus_read_lock)(); ++ + /* prevent another thread from changing buffer sizes */ + mutex_lock(&buffer->mutex); + atomic_inc(&buffer->resizing); +@@ -2893,7 +2899,6 @@ int ring_buffer_resize(struct trace_buff + cond_resched(); + } + +- cpus_read_lock(); + /* + * Fire off all the required work handlers + * We can't schedule on offline CPUs, but it's not necessary +@@ -2933,7 +2938,6 @@ int ring_buffer_resize(struct trace_buff + cpu_buffer->nr_pages_to_update = 0; + } + +- cpus_read_unlock(); + } else { + cpu_buffer = buffer->buffers[cpu_id]; + +@@ -2961,8 +2965,6 @@ int ring_buffer_resize(struct trace_buff + goto out_err; + } + +- cpus_read_lock(); +- + /* Can't run something on an offline CPU. */ + if (!cpu_online(cpu_id)) + rb_update_pages(cpu_buffer); +@@ -2981,7 +2983,6 @@ int ring_buffer_resize(struct trace_buff + } + + cpu_buffer->nr_pages_to_update = 0; +- cpus_read_unlock(); + } + + out: diff --git a/queue-6.15/series b/queue-6.15/series index 744c1a90ff..6fd98482ba 100644 --- a/queue-6.15/series +++ b/queue-6.15/series @@ -749,3 +749,25 @@ alsa-usb-audio-add-implicit-feedback-quirk-for-rode-ai-1.patch hid-usbhid-eliminate-recurrent-out-of-bounds-bug-in-usbhid_parse.patch powerpc-kernel-fix-ppc_save_regs-inclusion-in-build.patch posix-cpu-timers-fix-race-between-handle_posix_cpu_timers-and-posix_cpu_timer_del.patch +nvmem-zynqmp_nvmem-unbreak-driver-after-cleanup.patch +usb-usbtmc-fix-read_stb-function-and-get_stb-ioctl.patch +vmci-fix-race-between-vmci_host_setup_notify-and-vmci_ctx_unset_notify.patch +tty-serial-8250_omap-fix-tx-with-dma-for-am33xx.patch +usb-misc-onboard_usb_dev-fix-usb5744-initialization-sequence.patch +usb-cdnsp-fix-issue-with-detecting-command-completion-event.patch +usb-cdnsp-fix-issue-with-detecting-usb-3.2-speed.patch +usb-flush-altsetting-0-endpoints-before-reinitializating-them-after-reset.patch +usb-typec-tcpm-tcpci_maxim-fix-bounds-check-in-process_rx.patch +usb-typec-tcpm-move-tcpm_queue_vdm_unlocked-to-asynchronous-work.patch +9p-add-a-migrate_folio-method.patch +don-t-propagate-mounts-into-detached-trees.patch +mm-filemap-gate-dropbehind-invalidate-on-folio-dirty-writeback.patch +mm-filemap-use-filemap_end_dropbehind-for-read-invalidation.patch +ring-buffer-do-not-trigger-warn_on-due-to-a-commit_overrun.patch +ring-buffer-fix-buffer-locking-in-ring_buffer_subbuf_order_set.patch +ring-buffer-move-cpus_read_lock-outside-of-buffer-mutex.patch +xfs-don-t-assume-perags-are-initialised-when-trimming-ags.patch +xen-arm-call-uaccess_ttbr0_enable-for-dm_op-hypercall.patch +x86-iopl-cure-tif_io_bitmap-inconsistencies.patch +x86-hyperv-fix-apic-id-and-vp-index-confusion-in-hv_snp_boot_ap.patch +x86-fred-signal-prevent-immediate-repeat-of-single-step-trap-on-return-from-sigtrap-handler.patch diff --git a/queue-6.15/tty-serial-8250_omap-fix-tx-with-dma-for-am33xx.patch b/queue-6.15/tty-serial-8250_omap-fix-tx-with-dma-for-am33xx.patch new file mode 100644 index 0000000000..59f38bf278 --- /dev/null +++ b/queue-6.15/tty-serial-8250_omap-fix-tx-with-dma-for-am33xx.patch @@ -0,0 +1,100 @@ +From b495021a973e2468497689bd3e29b736747b896f Mon Sep 17 00:00:00 2001 +From: "Jiri Slaby (SUSE)" +Date: Thu, 22 May 2025 07:38:35 +0200 +Subject: tty: serial: 8250_omap: fix TX with DMA for am33xx + +From: Jiri Slaby (SUSE) + +commit b495021a973e2468497689bd3e29b736747b896f upstream. + +Commit 1788cf6a91d9 ("tty: serial: switch from circ_buf to kfifo") +introduced an error in the TX DMA handling for 8250_omap. + +When the OMAP_DMA_TX_KICK flag is set, the "skip_byte" is pulled from +the kfifo and emitted directly in order to start the DMA. While the +kfifo is updated, dma->tx_size is not decreased. This leads to +uart_xmit_advance() called in omap_8250_dma_tx_complete() advancing the +kfifo by one too much. + +In practice, transmitting N bytes has been seen to result in the last +N-1 bytes being sent repeatedly. + +This change fixes the problem by moving all of the dma setup after the +OMAP_DMA_TX_KICK handling and using kfifo_len() instead of the DMA size +for the 4-byte cutoff check. This slightly changes the behaviour at +buffer wraparound, but it still transmits the correct bytes somehow. + +Now, the "skip_byte" would no longer be accounted to the stats. As +previously, dma->tx_size included also this skip byte, up->icount.tx was +updated by aforementioned uart_xmit_advance() in +omap_8250_dma_tx_complete(). Fix this by using the uart_fifo_out() +helper instead of bare kfifo_get(). + +Based on patch by Mans Rullgard + +Signed-off-by: "Jiri Slaby (SUSE)" +Fixes: 1788cf6a91d9 ("tty: serial: switch from circ_buf to kfifo") +Link: https://lore.kernel.org/all/20250506150748.3162-1-mans@mansr.com/ +Reported-by: Mans Rullgard +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20250522053835.3495975-1-jirislaby@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/8250/8250_omap.c | 25 ++++++++++--------------- + 1 file changed, 10 insertions(+), 15 deletions(-) + +--- a/drivers/tty/serial/8250/8250_omap.c ++++ b/drivers/tty/serial/8250/8250_omap.c +@@ -1173,16 +1173,6 @@ static int omap_8250_tx_dma(struct uart_ + return 0; + } + +- sg_init_table(&sg, 1); +- ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1, +- UART_XMIT_SIZE, dma->tx_addr); +- if (ret != 1) { +- serial8250_clear_THRI(p); +- return 0; +- } +- +- dma->tx_size = sg_dma_len(&sg); +- + if (priv->habit & OMAP_DMA_TX_KICK) { + unsigned char c; + u8 tx_lvl; +@@ -1207,18 +1197,22 @@ static int omap_8250_tx_dma(struct uart_ + ret = -EBUSY; + goto err; + } +- if (dma->tx_size < 4) { ++ if (kfifo_len(&tport->xmit_fifo) < 4) { + ret = -EINVAL; + goto err; + } +- if (!kfifo_get(&tport->xmit_fifo, &c)) { ++ if (!uart_fifo_out(&p->port, &c, 1)) { + ret = -EINVAL; + goto err; + } + skip_byte = c; +- /* now we need to recompute due to kfifo_get */ +- kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1, +- UART_XMIT_SIZE, dma->tx_addr); ++ } ++ ++ sg_init_table(&sg, 1); ++ ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1, UART_XMIT_SIZE, dma->tx_addr); ++ if (ret != 1) { ++ ret = -EINVAL; ++ goto err; + } + + desc = dmaengine_prep_slave_sg(dma->txchan, &sg, 1, DMA_MEM_TO_DEV, +@@ -1228,6 +1222,7 @@ static int omap_8250_tx_dma(struct uart_ + goto err; + } + ++ dma->tx_size = sg_dma_len(&sg); + dma->tx_running = 1; + + desc->callback = omap_8250_dma_tx_complete; diff --git a/queue-6.15/usb-cdnsp-fix-issue-with-detecting-command-completion-event.patch b/queue-6.15/usb-cdnsp-fix-issue-with-detecting-command-completion-event.patch new file mode 100644 index 0000000000..fb290d3b6b --- /dev/null +++ b/queue-6.15/usb-cdnsp-fix-issue-with-detecting-command-completion-event.patch @@ -0,0 +1,75 @@ +From f4ecdc352646f7d23f348e5c544dbe3212c94fc8 Mon Sep 17 00:00:00 2001 +From: Pawel Laszczak +Date: Tue, 13 May 2025 05:30:09 +0000 +Subject: usb: cdnsp: Fix issue with detecting command completion event + +From: Pawel Laszczak + +commit f4ecdc352646f7d23f348e5c544dbe3212c94fc8 upstream. + +In some cases, there is a small-time gap in which CMD_RING_BUSY can be +cleared by controller but adding command completion event to event ring +will be delayed. As the result driver will return error code. + +This behavior has been detected on usbtest driver (test 9) with +configuration including ep1in/ep1out bulk and ep2in/ep2out isoc +endpoint. + +Probably this gap occurred because controller was busy with adding some +other events to event ring. + +The CMD_RING_BUSY is cleared to '0' when the Command Descriptor has been +executed and not when command completion event has been added to event +ring. + +To fix this issue for this test the small delay is sufficient less than +10us) but to make sure the problem doesn't happen again in the future +the patch introduces 10 retries to check with delay about 20us before +returning error code. + +Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver") +Cc: stable +Signed-off-by: Pawel Laszczak +Acked-by: Peter Chen +Link: https://lore.kernel.org/r/PH7PR07MB9538AA45362ACCF1B94EE9B7DD96A@PH7PR07MB9538.namprd07.prod.outlook.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/cdns3/cdnsp-gadget.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +--- a/drivers/usb/cdns3/cdnsp-gadget.c ++++ b/drivers/usb/cdns3/cdnsp-gadget.c +@@ -547,6 +547,7 @@ int cdnsp_wait_for_cmd_compl(struct cdns + dma_addr_t cmd_deq_dma; + union cdnsp_trb *event; + u32 cycle_state; ++ u32 retry = 10; + int ret, val; + u64 cmd_dma; + u32 flags; +@@ -578,8 +579,23 @@ int cdnsp_wait_for_cmd_compl(struct cdns + flags = le32_to_cpu(event->event_cmd.flags); + + /* Check the owner of the TRB. */ +- if ((flags & TRB_CYCLE) != cycle_state) ++ if ((flags & TRB_CYCLE) != cycle_state) { ++ /* ++ * Give some extra time to get chance controller ++ * to finish command before returning error code. ++ * Checking CMD_RING_BUSY is not sufficient because ++ * this bit is cleared to '0' when the Command ++ * Descriptor has been executed by controller ++ * and not when command completion event has ++ * be added to event ring. ++ */ ++ if (retry--) { ++ udelay(20); ++ continue; ++ } ++ + return -EINVAL; ++ } + + cmd_dma = le64_to_cpu(event->event_cmd.cmd_trb); + diff --git a/queue-6.15/usb-cdnsp-fix-issue-with-detecting-usb-3.2-speed.patch b/queue-6.15/usb-cdnsp-fix-issue-with-detecting-usb-3.2-speed.patch new file mode 100644 index 0000000000..db0a9b4a3a --- /dev/null +++ b/queue-6.15/usb-cdnsp-fix-issue-with-detecting-usb-3.2-speed.patch @@ -0,0 +1,53 @@ +From 2852788cfbe9ca1ab68509d65804413871f741f9 Mon Sep 17 00:00:00 2001 +From: Pawel Laszczak +Date: Tue, 13 May 2025 06:54:03 +0000 +Subject: usb: cdnsp: Fix issue with detecting USB 3.2 speed + +From: Pawel Laszczak + +commit 2852788cfbe9ca1ab68509d65804413871f741f9 upstream. + +Patch adds support for detecting SuperSpeedPlus Gen1 x2 and +SuperSpeedPlus Gen2 x2 speed. + +Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver") +Cc: stable +Signed-off-by: Pawel Laszczak +Acked-by: Peter Chen +Link: https://lore.kernel.org/r/PH7PR07MB95387AD98EDCA695FECE52BADD96A@PH7PR07MB9538.namprd07.prod.outlook.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/cdns3/cdnsp-gadget.c | 3 ++- + drivers/usb/cdns3/cdnsp-gadget.h | 4 ++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/usb/cdns3/cdnsp-gadget.c ++++ b/drivers/usb/cdns3/cdnsp-gadget.c +@@ -29,7 +29,8 @@ + unsigned int cdnsp_port_speed(unsigned int port_status) + { + /*Detect gadget speed based on PORTSC register*/ +- if (DEV_SUPERSPEEDPLUS(port_status)) ++ if (DEV_SUPERSPEEDPLUS(port_status) || ++ DEV_SSP_GEN1x2(port_status) || DEV_SSP_GEN2x2(port_status)) + return USB_SPEED_SUPER_PLUS; + else if (DEV_SUPERSPEED(port_status)) + return USB_SPEED_SUPER; +--- a/drivers/usb/cdns3/cdnsp-gadget.h ++++ b/drivers/usb/cdns3/cdnsp-gadget.h +@@ -285,11 +285,15 @@ struct cdnsp_port_regs { + #define XDEV_HS (0x3 << 10) + #define XDEV_SS (0x4 << 10) + #define XDEV_SSP (0x5 << 10) ++#define XDEV_SSP1x2 (0x6 << 10) ++#define XDEV_SSP2x2 (0x7 << 10) + #define DEV_UNDEFSPEED(p) (((p) & DEV_SPEED_MASK) == (0x0 << 10)) + #define DEV_FULLSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_FS) + #define DEV_HIGHSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_HS) + #define DEV_SUPERSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_SS) + #define DEV_SUPERSPEEDPLUS(p) (((p) & DEV_SPEED_MASK) == XDEV_SSP) ++#define DEV_SSP_GEN1x2(p) (((p) & DEV_SPEED_MASK) == XDEV_SSP1x2) ++#define DEV_SSP_GEN2x2(p) (((p) & DEV_SPEED_MASK) == XDEV_SSP2x2) + #define DEV_SUPERSPEED_ANY(p) (((p) & DEV_SPEED_MASK) >= XDEV_SS) + #define DEV_PORT_SPEED(p) (((p) >> 10) & 0x0f) + /* Port Link State Write Strobe - set this when changing link state */ diff --git a/queue-6.15/usb-flush-altsetting-0-endpoints-before-reinitializating-them-after-reset.patch b/queue-6.15/usb-flush-altsetting-0-endpoints-before-reinitializating-them-after-reset.patch new file mode 100644 index 0000000000..7fffe04cdd --- /dev/null +++ b/queue-6.15/usb-flush-altsetting-0-endpoints-before-reinitializating-them-after-reset.patch @@ -0,0 +1,75 @@ +From 89bb3dc13ac29a563f4e4c555e422882f64742bd Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Wed, 14 May 2025 16:25:20 +0300 +Subject: usb: Flush altsetting 0 endpoints before reinitializating them after reset. + +From: Mathias Nyman + +commit 89bb3dc13ac29a563f4e4c555e422882f64742bd upstream. + +usb core avoids sending a Set-Interface altsetting 0 request after device +reset, and instead relies on calling usb_disable_interface() and +usb_enable_interface() to flush and reset host-side of those endpoints. + +xHCI hosts allocate and set up endpoint ring buffers and host_ep->hcpriv +during usb_hcd_alloc_bandwidth() callback, which in this case is called +before flushing the endpoint in usb_disable_interface(). + +Call usb_disable_interface() before usb_hcd_alloc_bandwidth() to ensure +URBs are flushed before new ring buffers for the endpoints are allocated. + +Otherwise host driver will attempt to find and remove old stale URBs +from a freshly allocated new ringbuffer. + +Cc: stable +Fixes: 4fe0387afa89 ("USB: don't send Set-Interface after reset") +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20250514132520.225345-1-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/hub.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -6133,6 +6133,7 @@ static int usb_reset_and_verify_device(s + struct usb_hub *parent_hub; + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + struct usb_device_descriptor descriptor; ++ struct usb_interface *intf; + struct usb_host_bos *bos; + int i, j, ret = 0; + int port1 = udev->portnum; +@@ -6190,6 +6191,18 @@ static int usb_reset_and_verify_device(s + if (!udev->actconfig) + goto done; + ++ /* ++ * Some devices can't handle setting default altsetting 0 with a ++ * Set-Interface request. Disable host-side endpoints of those ++ * interfaces here. Enable and reset them back after host has set ++ * its internal endpoint structures during usb_hcd_alloc_bandwith() ++ */ ++ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { ++ intf = udev->actconfig->interface[i]; ++ if (intf->cur_altsetting->desc.bAlternateSetting == 0) ++ usb_disable_interface(udev, intf, true); ++ } ++ + mutex_lock(hcd->bandwidth_mutex); + ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL); + if (ret < 0) { +@@ -6221,12 +6234,11 @@ static int usb_reset_and_verify_device(s + */ + for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { + struct usb_host_config *config = udev->actconfig; +- struct usb_interface *intf = config->interface[i]; + struct usb_interface_descriptor *desc; + ++ intf = config->interface[i]; + desc = &intf->cur_altsetting->desc; + if (desc->bAlternateSetting == 0) { +- usb_disable_interface(udev, intf, true); + usb_enable_interface(udev, intf, true); + ret = 0; + } else { diff --git a/queue-6.15/usb-misc-onboard_usb_dev-fix-usb5744-initialization-sequence.patch b/queue-6.15/usb-misc-onboard_usb_dev-fix-usb5744-initialization-sequence.patch new file mode 100644 index 0000000000..666ea36987 --- /dev/null +++ b/queue-6.15/usb-misc-onboard_usb_dev-fix-usb5744-initialization-sequence.patch @@ -0,0 +1,161 @@ +From 1143d41922c0f87504f095417ba1870167970143 Mon Sep 17 00:00:00 2001 +From: Jonathan Stroud +Date: Fri, 16 May 2025 18:02:40 +0530 +Subject: usb: misc: onboard_usb_dev: Fix usb5744 initialization sequence + +From: Jonathan Stroud + +commit 1143d41922c0f87504f095417ba1870167970143 upstream. + +Introduce i2c APIs to read/write for proper configuration register +programming. It ensures that read-modify-write sequence is performed +and reserved bit in Runtime Flags 2 register are not touched. + +Also legacy smbus block write inserted an extra count value into the +i2c data stream which breaks the register write on the usb5744. + +Switching to new read/write i2c APIs fixes both issues. + +Fixes: 6782311d04df ("usb: misc: onboard_usb_dev: add Microchip usb5744 SMBus programming support") +Cc: stable +Signed-off-by: Jonathan Stroud +Co-developed-by: Radhey Shyam Pandey +Signed-off-by: Radhey Shyam Pandey +Link: https://lore.kernel.org/r/1747398760-284021-1-git-send-email-radhey.shyam.pandey@amd.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/onboard_usb_dev.c | 100 ++++++++++++++++++++++++++++++++----- + 1 file changed, 87 insertions(+), 13 deletions(-) + +--- a/drivers/usb/misc/onboard_usb_dev.c ++++ b/drivers/usb/misc/onboard_usb_dev.c +@@ -36,9 +36,10 @@ + #define USB5744_CMD_CREG_ACCESS 0x99 + #define USB5744_CMD_CREG_ACCESS_LSB 0x37 + #define USB5744_CREG_MEM_ADDR 0x00 ++#define USB5744_CREG_MEM_RD_ADDR 0x04 + #define USB5744_CREG_WRITE 0x00 +-#define USB5744_CREG_RUNTIMEFLAGS2 0x41 +-#define USB5744_CREG_RUNTIMEFLAGS2_LSB 0x1D ++#define USB5744_CREG_READ 0x01 ++#define USB5744_CREG_RUNTIMEFLAGS2 0x411D + #define USB5744_CREG_BYPASS_UDC_SUSPEND BIT(3) + + static void onboard_dev_attach_usb_driver(struct work_struct *work); +@@ -309,11 +310,88 @@ static void onboard_dev_attach_usb_drive + pr_err("Failed to attach USB driver: %pe\n", ERR_PTR(err)); + } + ++static int onboard_dev_5744_i2c_read_byte(struct i2c_client *client, u16 addr, u8 *data) ++{ ++ struct i2c_msg msg[2]; ++ u8 rd_buf[3]; ++ int ret; ++ ++ u8 wr_buf[7] = {0, USB5744_CREG_MEM_ADDR, 4, ++ USB5744_CREG_READ, 1, ++ addr >> 8 & 0xff, ++ addr & 0xff}; ++ msg[0].addr = client->addr; ++ msg[0].flags = 0; ++ msg[0].len = sizeof(wr_buf); ++ msg[0].buf = wr_buf; ++ ++ ret = i2c_transfer(client->adapter, msg, 1); ++ if (ret < 0) ++ return ret; ++ ++ wr_buf[0] = USB5744_CMD_CREG_ACCESS; ++ wr_buf[1] = USB5744_CMD_CREG_ACCESS_LSB; ++ wr_buf[2] = 0; ++ msg[0].len = 3; ++ ++ ret = i2c_transfer(client->adapter, msg, 1); ++ if (ret < 0) ++ return ret; ++ ++ wr_buf[0] = 0; ++ wr_buf[1] = USB5744_CREG_MEM_RD_ADDR; ++ msg[0].len = 2; ++ ++ msg[1].addr = client->addr; ++ msg[1].flags = I2C_M_RD; ++ msg[1].len = 2; ++ msg[1].buf = rd_buf; ++ ++ ret = i2c_transfer(client->adapter, msg, 2); ++ if (ret < 0) ++ return ret; ++ *data = rd_buf[1]; ++ ++ return 0; ++} ++ ++static int onboard_dev_5744_i2c_write_byte(struct i2c_client *client, u16 addr, u8 data) ++{ ++ struct i2c_msg msg[2]; ++ int ret; ++ ++ u8 wr_buf[8] = {0, USB5744_CREG_MEM_ADDR, 5, ++ USB5744_CREG_WRITE, 1, ++ addr >> 8 & 0xff, ++ addr & 0xff, ++ data}; ++ msg[0].addr = client->addr; ++ msg[0].flags = 0; ++ msg[0].len = sizeof(wr_buf); ++ msg[0].buf = wr_buf; ++ ++ ret = i2c_transfer(client->adapter, msg, 1); ++ if (ret < 0) ++ return ret; ++ ++ msg[0].len = 3; ++ wr_buf[0] = USB5744_CMD_CREG_ACCESS; ++ wr_buf[1] = USB5744_CMD_CREG_ACCESS_LSB; ++ wr_buf[2] = 0; ++ ++ ret = i2c_transfer(client->adapter, msg, 1); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + static int onboard_dev_5744_i2c_init(struct i2c_client *client) + { + #if IS_ENABLED(CONFIG_USB_ONBOARD_DEV_USB5744) + struct device *dev = &client->dev; + int ret; ++ u8 reg; + + /* + * Set BYPASS_UDC_SUSPEND bit to ensure MCU is always enabled +@@ -321,20 +399,16 @@ static int onboard_dev_5744_i2c_init(str + * The command writes 5 bytes to memory and single data byte in + * configuration register. + */ +- char wr_buf[7] = {USB5744_CREG_MEM_ADDR, 5, +- USB5744_CREG_WRITE, 1, +- USB5744_CREG_RUNTIMEFLAGS2, +- USB5744_CREG_RUNTIMEFLAGS2_LSB, +- USB5744_CREG_BYPASS_UDC_SUSPEND}; +- +- ret = i2c_smbus_write_block_data(client, 0, sizeof(wr_buf), wr_buf); ++ ret = onboard_dev_5744_i2c_read_byte(client, ++ USB5744_CREG_RUNTIMEFLAGS2, ®); + if (ret) +- return dev_err_probe(dev, ret, "BYPASS_UDC_SUSPEND bit configuration failed\n"); ++ return dev_err_probe(dev, ret, "CREG_RUNTIMEFLAGS2 read failed\n"); + +- ret = i2c_smbus_write_word_data(client, USB5744_CMD_CREG_ACCESS, +- USB5744_CMD_CREG_ACCESS_LSB); ++ reg |= USB5744_CREG_BYPASS_UDC_SUSPEND; ++ ret = onboard_dev_5744_i2c_write_byte(client, ++ USB5744_CREG_RUNTIMEFLAGS2, reg); + if (ret) +- return dev_err_probe(dev, ret, "Configuration Register Access Command failed\n"); ++ return dev_err_probe(dev, ret, "BYPASS_UDC_SUSPEND bit configuration failed\n"); + + /* Send SMBus command to boot hub. */ + ret = i2c_smbus_write_word_data(client, USB5744_CMD_ATTACH, diff --git a/queue-6.15/usb-typec-tcpm-move-tcpm_queue_vdm_unlocked-to-asynchronous-work.patch b/queue-6.15/usb-typec-tcpm-move-tcpm_queue_vdm_unlocked-to-asynchronous-work.patch new file mode 100644 index 0000000000..dafb625f62 --- /dev/null +++ b/queue-6.15/usb-typec-tcpm-move-tcpm_queue_vdm_unlocked-to-asynchronous-work.patch @@ -0,0 +1,233 @@ +From 324d45e53f1a36c88bc649dc39e0c8300a41be0a Mon Sep 17 00:00:00 2001 +From: RD Babiera +Date: Tue, 6 May 2025 23:28:53 +0000 +Subject: usb: typec: tcpm: move tcpm_queue_vdm_unlocked to asynchronous work + +From: RD Babiera + +commit 324d45e53f1a36c88bc649dc39e0c8300a41be0a upstream. + +A state check was previously added to tcpm_queue_vdm_unlocked to +prevent a deadlock where the DisplayPort Alt Mode driver would be +executing work and attempting to grab the tcpm_lock while the TCPM +was holding the lock and attempting to unregister the altmode, blocking +on the altmode driver's cancel_work_sync call. + +Because the state check isn't protected, there is a small window +where the Alt Mode driver could determine that the TCPM is +in a ready state and attempt to grab the lock while the +TCPM grabs the lock and changes the TCPM state to one that +causes the deadlock. The callstack is provided below: + +[110121.667392][ C7] Call trace: +[110121.667396][ C7] __switch_to+0x174/0x338 +[110121.667406][ C7] __schedule+0x608/0x9f0 +[110121.667414][ C7] schedule+0x7c/0xe8 +[110121.667423][ C7] kernfs_drain+0xb0/0x114 +[110121.667431][ C7] __kernfs_remove+0x16c/0x20c +[110121.667436][ C7] kernfs_remove_by_name_ns+0x74/0xe8 +[110121.667442][ C7] sysfs_remove_group+0x84/0xe8 +[110121.667450][ C7] sysfs_remove_groups+0x34/0x58 +[110121.667458][ C7] device_remove_groups+0x10/0x20 +[110121.667464][ C7] device_release_driver_internal+0x164/0x2e4 +[110121.667475][ C7] device_release_driver+0x18/0x28 +[110121.667484][ C7] bus_remove_device+0xec/0x118 +[110121.667491][ C7] device_del+0x1e8/0x4ac +[110121.667498][ C7] device_unregister+0x18/0x38 +[110121.667504][ C7] typec_unregister_altmode+0x30/0x44 +[110121.667515][ C7] tcpm_reset_port+0xac/0x370 +[110121.667523][ C7] tcpm_snk_detach+0x84/0xb8 +[110121.667529][ C7] run_state_machine+0x4c0/0x1b68 +[110121.667536][ C7] tcpm_state_machine_work+0x94/0xe4 +[110121.667544][ C7] kthread_worker_fn+0x10c/0x244 +[110121.667552][ C7] kthread+0x104/0x1d4 +[110121.667557][ C7] ret_from_fork+0x10/0x20 + +[110121.667689][ C7] Workqueue: events dp_altmode_work +[110121.667697][ C7] Call trace: +[110121.667701][ C7] __switch_to+0x174/0x338 +[110121.667710][ C7] __schedule+0x608/0x9f0 +[110121.667717][ C7] schedule+0x7c/0xe8 +[110121.667725][ C7] schedule_preempt_disabled+0x24/0x40 +[110121.667733][ C7] __mutex_lock+0x408/0xdac +[110121.667741][ C7] __mutex_lock_slowpath+0x14/0x24 +[110121.667748][ C7] mutex_lock+0x40/0xec +[110121.667757][ C7] tcpm_altmode_enter+0x78/0xb4 +[110121.667764][ C7] typec_altmode_enter+0xdc/0x10c +[110121.667769][ C7] dp_altmode_work+0x68/0x164 +[110121.667775][ C7] process_one_work+0x1e4/0x43c +[110121.667783][ C7] worker_thread+0x25c/0x430 +[110121.667789][ C7] kthread+0x104/0x1d4 +[110121.667794][ C7] ret_from_fork+0x10/0x20 + +Change tcpm_queue_vdm_unlocked to queue for tcpm_queue_vdm_work, +which can perform the state check while holding the TCPM lock +while the Alt Mode lock is no longer held. This requires a new +struct to hold the vdm data, altmode_vdm_event. + +Fixes: cdc9946ea637 ("usb: typec: tcpm: enforce ready state when queueing alt mode vdm") +Cc: stable +Signed-off-by: RD Babiera +Reviewed-by: Heikki Krogerus +Reviewed-by: Badhri Jagan Sridharan +Link: https://lore.kernel.org/r/20250506232853.1968304-2-rdbabiera@google.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/tcpm/tcpm.c | 91 ++++++++++++++++++++++++++++++++---------- + 1 file changed, 71 insertions(+), 20 deletions(-) + +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -596,6 +596,15 @@ struct pd_rx_event { + enum tcpm_transmit_type rx_sop_type; + }; + ++struct altmode_vdm_event { ++ struct kthread_work work; ++ struct tcpm_port *port; ++ u32 header; ++ u32 *data; ++ int cnt; ++ enum tcpm_transmit_type tx_sop_type; ++}; ++ + static const char * const pd_rev[] = { + [PD_REV10] = "rev1", + [PD_REV20] = "rev2", +@@ -1608,18 +1617,68 @@ static void tcpm_queue_vdm(struct tcpm_p + mod_vdm_delayed_work(port, 0); + } + +-static void tcpm_queue_vdm_unlocked(struct tcpm_port *port, const u32 header, +- const u32 *data, int cnt, enum tcpm_transmit_type tx_sop_type) ++static void tcpm_queue_vdm_work(struct kthread_work *work) + { +- if (port->state != SRC_READY && port->state != SNK_READY && +- port->state != SRC_VDM_IDENTITY_REQUEST) +- return; ++ struct altmode_vdm_event *event = container_of(work, ++ struct altmode_vdm_event, ++ work); ++ struct tcpm_port *port = event->port; + + mutex_lock(&port->lock); +- tcpm_queue_vdm(port, header, data, cnt, tx_sop_type); ++ if (port->state != SRC_READY && port->state != SNK_READY && ++ port->state != SRC_VDM_IDENTITY_REQUEST) { ++ tcpm_log_force(port, "dropping altmode_vdm_event"); ++ goto port_unlock; ++ } ++ ++ tcpm_queue_vdm(port, event->header, event->data, event->cnt, event->tx_sop_type); ++ ++port_unlock: ++ kfree(event->data); ++ kfree(event); + mutex_unlock(&port->lock); + } + ++static int tcpm_queue_vdm_unlocked(struct tcpm_port *port, const u32 header, ++ const u32 *data, int cnt, enum tcpm_transmit_type tx_sop_type) ++{ ++ struct altmode_vdm_event *event; ++ u32 *data_cpy; ++ int ret = -ENOMEM; ++ ++ event = kzalloc(sizeof(*event), GFP_KERNEL); ++ if (!event) ++ goto err_event; ++ ++ data_cpy = kcalloc(cnt, sizeof(u32), GFP_KERNEL); ++ if (!data_cpy) ++ goto err_data; ++ ++ kthread_init_work(&event->work, tcpm_queue_vdm_work); ++ event->port = port; ++ event->header = header; ++ memcpy(data_cpy, data, sizeof(u32) * cnt); ++ event->data = data_cpy; ++ event->cnt = cnt; ++ event->tx_sop_type = tx_sop_type; ++ ++ ret = kthread_queue_work(port->wq, &event->work); ++ if (!ret) { ++ ret = -EBUSY; ++ goto err_queue; ++ } ++ ++ return 0; ++ ++err_queue: ++ kfree(data_cpy); ++err_data: ++ kfree(event); ++err_event: ++ tcpm_log_force(port, "failed to queue altmode vdm, err:%d", ret); ++ return ret; ++} ++ + static void svdm_consume_identity(struct tcpm_port *port, const u32 *p, int cnt) + { + u32 vdo = p[VDO_INDEX_IDH]; +@@ -2830,8 +2889,7 @@ static int tcpm_altmode_enter(struct typ + header = VDO(altmode->svid, vdo ? 2 : 1, svdm_version, CMD_ENTER_MODE); + header |= VDO_OPOS(altmode->mode); + +- tcpm_queue_vdm_unlocked(port, header, vdo, vdo ? 1 : 0, TCPC_TX_SOP); +- return 0; ++ return tcpm_queue_vdm_unlocked(port, header, vdo, vdo ? 1 : 0, TCPC_TX_SOP); + } + + static int tcpm_altmode_exit(struct typec_altmode *altmode) +@@ -2847,8 +2905,7 @@ static int tcpm_altmode_exit(struct type + header = VDO(altmode->svid, 1, svdm_version, CMD_EXIT_MODE); + header |= VDO_OPOS(altmode->mode); + +- tcpm_queue_vdm_unlocked(port, header, NULL, 0, TCPC_TX_SOP); +- return 0; ++ return tcpm_queue_vdm_unlocked(port, header, NULL, 0, TCPC_TX_SOP); + } + + static int tcpm_altmode_vdm(struct typec_altmode *altmode, +@@ -2856,9 +2913,7 @@ static int tcpm_altmode_vdm(struct typec + { + struct tcpm_port *port = typec_altmode_get_drvdata(altmode); + +- tcpm_queue_vdm_unlocked(port, header, data, count - 1, TCPC_TX_SOP); +- +- return 0; ++ return tcpm_queue_vdm_unlocked(port, header, data, count - 1, TCPC_TX_SOP); + } + + static const struct typec_altmode_ops tcpm_altmode_ops = { +@@ -2882,8 +2937,7 @@ static int tcpm_cable_altmode_enter(stru + header = VDO(altmode->svid, vdo ? 2 : 1, svdm_version, CMD_ENTER_MODE); + header |= VDO_OPOS(altmode->mode); + +- tcpm_queue_vdm_unlocked(port, header, vdo, vdo ? 1 : 0, TCPC_TX_SOP_PRIME); +- return 0; ++ return tcpm_queue_vdm_unlocked(port, header, vdo, vdo ? 1 : 0, TCPC_TX_SOP_PRIME); + } + + static int tcpm_cable_altmode_exit(struct typec_altmode *altmode, enum typec_plug_index sop) +@@ -2899,8 +2953,7 @@ static int tcpm_cable_altmode_exit(struc + header = VDO(altmode->svid, 1, svdm_version, CMD_EXIT_MODE); + header |= VDO_OPOS(altmode->mode); + +- tcpm_queue_vdm_unlocked(port, header, NULL, 0, TCPC_TX_SOP_PRIME); +- return 0; ++ return tcpm_queue_vdm_unlocked(port, header, NULL, 0, TCPC_TX_SOP_PRIME); + } + + static int tcpm_cable_altmode_vdm(struct typec_altmode *altmode, enum typec_plug_index sop, +@@ -2908,9 +2961,7 @@ static int tcpm_cable_altmode_vdm(struct + { + struct tcpm_port *port = typec_altmode_get_drvdata(altmode); + +- tcpm_queue_vdm_unlocked(port, header, data, count - 1, TCPC_TX_SOP_PRIME); +- +- return 0; ++ return tcpm_queue_vdm_unlocked(port, header, data, count - 1, TCPC_TX_SOP_PRIME); + } + + static const struct typec_cable_ops tcpm_cable_ops = { diff --git a/queue-6.15/usb-typec-tcpm-tcpci_maxim-fix-bounds-check-in-process_rx.patch b/queue-6.15/usb-typec-tcpm-tcpci_maxim-fix-bounds-check-in-process_rx.patch new file mode 100644 index 0000000000..eca84dd590 --- /dev/null +++ b/queue-6.15/usb-typec-tcpm-tcpci_maxim-fix-bounds-check-in-process_rx.patch @@ -0,0 +1,44 @@ +From 0736299d090f5c6a1032678705c4bc0a9511a3db Mon Sep 17 00:00:00 2001 +From: Amit Sunil Dhamne +Date: Fri, 2 May 2025 16:57:03 -0700 +Subject: usb: typec: tcpm/tcpci_maxim: Fix bounds check in process_rx() + +From: Amit Sunil Dhamne + +commit 0736299d090f5c6a1032678705c4bc0a9511a3db upstream. + +Register read of TCPC_RX_BYTE_CNT returns the total size consisting of: + + PD message (pending read) size + 1 Byte for Frame Type (SOP*) + +This is validated against the max PD message (`struct pd_message`) size +without accounting for the extra byte for the frame type. Note that the +struct pd_message does not contain a field for the frame_type. This +results in false negatives when the "PD message (pending read)" is equal +to the max PD message size. + +Fixes: 6f413b559f86 ("usb: typec: tcpci_maxim: Chip level TCPC driver") +Signed-off-by: Amit Sunil Dhamne +Signed-off-by: Badhri Jagan Sridharan +Reviewed-by: Kyle Tso +Cc: stable +Link: https://lore.kernel.org/stable/20250502-b4-new-fix-pd-rx-count-v1-1-e5711ed09b3d%40google.com +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20250502-b4-new-fix-pd-rx-count-v1-1-e5711ed09b3d@google.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/tcpm/tcpci_maxim_core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c ++++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c +@@ -166,7 +166,8 @@ static void process_rx(struct max_tcpci_ + return; + } + +- if (count > sizeof(struct pd_message) || count + 1 > TCPC_RECEIVE_BUFFER_LEN) { ++ if (count > sizeof(struct pd_message) + 1 || ++ count + 1 > TCPC_RECEIVE_BUFFER_LEN) { + dev_err(chip->dev, "Invalid TCPC_RX_BYTE_CNT %d\n", count); + return; + } diff --git a/queue-6.15/usb-usbtmc-fix-read_stb-function-and-get_stb-ioctl.patch b/queue-6.15/usb-usbtmc-fix-read_stb-function-and-get_stb-ioctl.patch new file mode 100644 index 0000000000..582d68fa73 --- /dev/null +++ b/queue-6.15/usb-usbtmc-fix-read_stb-function-and-get_stb-ioctl.patch @@ -0,0 +1,69 @@ +From acb3dac2805d3342ded7dbbd164add32bbfdf21c Mon Sep 17 00:00:00 2001 +From: Dave Penkler +Date: Wed, 21 May 2025 14:16:55 +0200 +Subject: usb: usbtmc: Fix read_stb function and get_stb ioctl + +From: Dave Penkler + +commit acb3dac2805d3342ded7dbbd164add32bbfdf21c upstream. + +The usbtmc488_ioctl_read_stb function relied on a positive return from +usbtmc_get_stb to reset the srq condition in the driver. The +USBTMC_IOCTL_GET_STB case tested for a positive return to return the stb +to the user. + +Commit: ("usb: usbtmc: Fix erroneous get_stb ioctl +error returns") changed the return value of usbtmc_get_stb to 0 on +success instead of returning the value of usb_control_msg which is +positive in the normal case. This change caused the function +usbtmc488_ioctl_read_stb and the USBTMC_IOCTL_GET_STB ioctl to no +longer function correctly. + +Change the test in usbtmc488_ioctl_read_stb to test for failure +first and return the failure code immediately. +Change the test for the USBTMC_IOCTL_GET_STB ioctl to test for 0 +instead of a positive value. + +Fixes: cac01bd178d6 ("usb: usbtmc: Fix erroneous get_stb ioctl error returns") +Cc: stable@vger.kernel.org +Signed-off-by: Dave Penkler +Link: https://lore.kernel.org/r/20250521121656.18174-3-dpenkler@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/class/usbtmc.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +--- a/drivers/usb/class/usbtmc.c ++++ b/drivers/usb/class/usbtmc.c +@@ -565,14 +565,15 @@ static int usbtmc488_ioctl_read_stb(stru + + rv = usbtmc_get_stb(file_data, &stb); + +- if (rv > 0) { +- srq_asserted = atomic_xchg(&file_data->srq_asserted, +- srq_asserted); +- if (srq_asserted) +- stb |= 0x40; /* Set RQS bit */ ++ if (rv < 0) ++ return rv; ++ ++ srq_asserted = atomic_xchg(&file_data->srq_asserted, srq_asserted); ++ if (srq_asserted) ++ stb |= 0x40; /* Set RQS bit */ ++ ++ rv = put_user(stb, (__u8 __user *)arg); + +- rv = put_user(stb, (__u8 __user *)arg); +- } + return rv; + + } +@@ -2201,7 +2202,7 @@ static long usbtmc_ioctl(struct file *fi + + case USBTMC_IOCTL_GET_STB: + retval = usbtmc_get_stb(file_data, &tmp_byte); +- if (retval > 0) ++ if (!retval) + retval = put_user(tmp_byte, (__u8 __user *)arg); + break; + diff --git a/queue-6.15/vmci-fix-race-between-vmci_host_setup_notify-and-vmci_ctx_unset_notify.patch b/queue-6.15/vmci-fix-race-between-vmci_host_setup_notify-and-vmci_ctx_unset_notify.patch new file mode 100644 index 0000000000..e7261b700a --- /dev/null +++ b/queue-6.15/vmci-fix-race-between-vmci_host_setup_notify-and-vmci_ctx_unset_notify.patch @@ -0,0 +1,95 @@ +From 1bd6406fb5f36c2bb1e96e27d4c3e9f4d09edde4 Mon Sep 17 00:00:00 2001 +From: Wupeng Ma +Date: Sat, 10 May 2025 11:30:40 +0800 +Subject: VMCI: fix race between vmci_host_setup_notify and vmci_ctx_unset_notify + +From: Wupeng Ma + +commit 1bd6406fb5f36c2bb1e96e27d4c3e9f4d09edde4 upstream. + +During our test, it is found that a warning can be trigger in try_grab_folio +as follow: + + ------------[ cut here ]------------ + WARNING: CPU: 0 PID: 1678 at mm/gup.c:147 try_grab_folio+0x106/0x130 + Modules linked in: + CPU: 0 UID: 0 PID: 1678 Comm: syz.3.31 Not tainted 6.15.0-rc5 #163 PREEMPT(undef) + RIP: 0010:try_grab_folio+0x106/0x130 + Call Trace: + + follow_huge_pmd+0x240/0x8e0 + follow_pmd_mask.constprop.0.isra.0+0x40b/0x5c0 + follow_pud_mask.constprop.0.isra.0+0x14a/0x170 + follow_page_mask+0x1c2/0x1f0 + __get_user_pages+0x176/0x950 + __gup_longterm_locked+0x15b/0x1060 + ? gup_fast+0x120/0x1f0 + gup_fast_fallback+0x17e/0x230 + get_user_pages_fast+0x5f/0x80 + vmci_host_unlocked_ioctl+0x21c/0xf80 + RIP: 0033:0x54d2cd + ---[ end trace 0000000000000000 ]--- + +Digging into the source, context->notify_page may init by get_user_pages_fast +and can be seen in vmci_ctx_unset_notify which will try to put_page. However +get_user_pages_fast is not finished here and lead to following +try_grab_folio warning. The race condition is shown as follow: + +cpu0 cpu1 +vmci_host_do_set_notify +vmci_host_setup_notify +get_user_pages_fast(uva, 1, FOLL_WRITE, &context->notify_page); +lockless_pages_from_mm +gup_pgd_range +gup_huge_pmd // update &context->notify_page + vmci_host_do_set_notify + vmci_ctx_unset_notify + notify_page = context->notify_page; + if (notify_page) + put_page(notify_page); // page is freed +__gup_longterm_locked +__get_user_pages +follow_trans_huge_pmd +try_grab_folio // warn here + +To slove this, use local variable page to make notify_page can be seen +after finish get_user_pages_fast. + +Fixes: a1d88436d53a ("VMCI: Fix two UVA mapping bugs") +Cc: stable +Closes: https://lore.kernel.org/all/e91da589-ad57-3969-d979-879bbd10dddd@huawei.com/ +Signed-off-by: Wupeng Ma +Link: https://lore.kernel.org/r/20250510033040.901582-1-mawupeng1@huawei.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/misc/vmw_vmci/vmci_host.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/drivers/misc/vmw_vmci/vmci_host.c ++++ b/drivers/misc/vmw_vmci/vmci_host.c +@@ -227,6 +227,7 @@ static int drv_cp_harray_to_user(void __ + static int vmci_host_setup_notify(struct vmci_ctx *context, + unsigned long uva) + { ++ struct page *page; + int retval; + + if (context->notify_page) { +@@ -243,13 +244,11 @@ static int vmci_host_setup_notify(struct + /* + * Lock physical page backing a given user VA. + */ +- retval = get_user_pages_fast(uva, 1, FOLL_WRITE, &context->notify_page); +- if (retval != 1) { +- context->notify_page = NULL; ++ retval = get_user_pages_fast(uva, 1, FOLL_WRITE, &page); ++ if (retval != 1) + return VMCI_ERROR_GENERIC; +- } +- if (context->notify_page == NULL) +- return VMCI_ERROR_UNAVAILABLE; ++ ++ context->notify_page = page; + + /* + * Map the locked page and set up notify pointer. diff --git a/queue-6.15/x86-fred-signal-prevent-immediate-repeat-of-single-step-trap-on-return-from-sigtrap-handler.patch b/queue-6.15/x86-fred-signal-prevent-immediate-repeat-of-single-step-trap-on-return-from-sigtrap-handler.patch new file mode 100644 index 0000000000..a2109d8e95 --- /dev/null +++ b/queue-6.15/x86-fred-signal-prevent-immediate-repeat-of-single-step-trap-on-return-from-sigtrap-handler.patch @@ -0,0 +1,124 @@ +From e34dbbc85d64af59176fe59fad7b4122f4330fe2 Mon Sep 17 00:00:00 2001 +From: "Xin Li (Intel)" +Date: Mon, 9 Jun 2025 01:40:53 -0700 +Subject: x86/fred/signal: Prevent immediate repeat of single step trap on return from SIGTRAP handler + +From: Xin Li (Intel) + +commit e34dbbc85d64af59176fe59fad7b4122f4330fe2 upstream. + +Clear the software event flag in the augmented SS to prevent immediate +repeat of single step trap on return from SIGTRAP handler if the trap +flag (TF) is set without an external debugger attached. + +Following is a typical single-stepping flow for a user process: + +1) The user process is prepared for single-stepping by setting + RFLAGS.TF = 1. +2) When any instruction in user space completes, a #DB is triggered. +3) The kernel handles the #DB and returns to user space, invoking the + SIGTRAP handler with RFLAGS.TF = 0. +4) After the SIGTRAP handler finishes, the user process performs a + sigreturn syscall, restoring the original state, including + RFLAGS.TF = 1. +5) Goto step 2. + +According to the FRED specification: + +A) Bit 17 in the augmented SS is designated as the software event + flag, which is set to 1 for FRED event delivery of SYSCALL, + SYSENTER, or INT n. +B) If bit 17 of the augmented SS is 1 and ERETU would result in + RFLAGS.TF = 1, a single-step trap will be pending upon completion + of ERETU. + +In step 4) above, the software event flag is set upon the sigreturn +syscall, and its corresponding ERETU would restore RFLAGS.TF = 1. +This combination causes a pending single-step trap upon completion of +ERETU. Therefore, another #DB is triggered before any user space +instruction is executed, which leads to an infinite loop in which the +SIGTRAP handler keeps being invoked on the same user space IP. + +Fixes: 14619d912b65 ("x86/fred: FRED entry/exit and dispatch code") +Suggested-by: H. Peter Anvin (Intel) +Signed-off-by: Xin Li (Intel) +Signed-off-by: Dave Hansen +Tested-by: Sohil Mehta +Cc:stable@vger.kernel.org +Link: https://lore.kernel.org/all/20250609084054.2083189-2-xin%40zytor.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/sighandling.h | 22 ++++++++++++++++++++++ + arch/x86/kernel/signal_32.c | 4 ++++ + arch/x86/kernel/signal_64.c | 4 ++++ + 3 files changed, 30 insertions(+) + +--- a/arch/x86/include/asm/sighandling.h ++++ b/arch/x86/include/asm/sighandling.h +@@ -24,4 +24,26 @@ int ia32_setup_rt_frame(struct ksignal * + int x64_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs); + int x32_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs); + ++/* ++ * To prevent immediate repeat of single step trap on return from SIGTRAP ++ * handler if the trap flag (TF) is set without an external debugger attached, ++ * clear the software event flag in the augmented SS, ensuring no single-step ++ * trap is pending upon ERETU completion. ++ * ++ * Note, this function should be called in sigreturn() before the original ++ * state is restored to make sure the TF is read from the entry frame. ++ */ ++static __always_inline void prevent_single_step_upon_eretu(struct pt_regs *regs) ++{ ++ /* ++ * If the trap flag (TF) is set, i.e., the sigreturn() SYSCALL instruction ++ * is being single-stepped, do not clear the software event flag in the ++ * augmented SS, thus a debugger won't skip over the following instruction. ++ */ ++#ifdef CONFIG_X86_FRED ++ if (!(regs->flags & X86_EFLAGS_TF)) ++ regs->fred_ss.swevent = 0; ++#endif ++} ++ + #endif /* _ASM_X86_SIGHANDLING_H */ +--- a/arch/x86/kernel/signal_32.c ++++ b/arch/x86/kernel/signal_32.c +@@ -152,6 +152,8 @@ SYSCALL32_DEFINE0(sigreturn) + struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8); + sigset_t set; + ++ prevent_single_step_upon_eretu(regs); ++ + if (!access_ok(frame, sizeof(*frame))) + goto badframe; + if (__get_user(set.sig[0], &frame->sc.oldmask) +@@ -175,6 +177,8 @@ SYSCALL32_DEFINE0(rt_sigreturn) + struct rt_sigframe_ia32 __user *frame; + sigset_t set; + ++ prevent_single_step_upon_eretu(regs); ++ + frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4); + + if (!access_ok(frame, sizeof(*frame))) +--- a/arch/x86/kernel/signal_64.c ++++ b/arch/x86/kernel/signal_64.c +@@ -250,6 +250,8 @@ SYSCALL_DEFINE0(rt_sigreturn) + sigset_t set; + unsigned long uc_flags; + ++ prevent_single_step_upon_eretu(regs); ++ + frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); + if (!access_ok(frame, sizeof(*frame))) + goto badframe; +@@ -366,6 +368,8 @@ COMPAT_SYSCALL_DEFINE0(x32_rt_sigreturn) + sigset_t set; + unsigned long uc_flags; + ++ prevent_single_step_upon_eretu(regs); ++ + frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8); + + if (!access_ok(frame, sizeof(*frame))) diff --git a/queue-6.15/x86-hyperv-fix-apic-id-and-vp-index-confusion-in-hv_snp_boot_ap.patch b/queue-6.15/x86-hyperv-fix-apic-id-and-vp-index-confusion-in-hv_snp_boot_ap.patch new file mode 100644 index 0000000000..151748f9d0 --- /dev/null +++ b/queue-6.15/x86-hyperv-fix-apic-id-and-vp-index-confusion-in-hv_snp_boot_ap.patch @@ -0,0 +1,244 @@ +From 86c48271e0d60c82665e9fd61277002391efcef7 Mon Sep 17 00:00:00 2001 +From: Roman Kisel +Date: Wed, 7 May 2025 11:22:25 -0700 +Subject: x86/hyperv: Fix APIC ID and VP index confusion in hv_snp_boot_ap() + +From: Roman Kisel + +commit 86c48271e0d60c82665e9fd61277002391efcef7 upstream. + +To start an application processor in SNP-isolated guest, a hypercall +is used that takes a virtual processor index. The hv_snp_boot_ap() +function uses that START_VP hypercall but passes as VP index to it +what it receives as a wakeup_secondary_cpu_64 callback: the APIC ID. + +As those two aren't generally interchangeable, that may lead to hung +APs if the VP index and the APIC ID don't match up. + +Update the parameter names to avoid confusion as to what the parameter +is. Use the APIC ID to the VP index conversion to provide the correct +input to the hypercall. + +Cc: stable@vger.kernel.org +Fixes: 44676bb9d566 ("x86/hyperv: Add smp support for SEV-SNP guest") +Signed-off-by: Roman Kisel +Reviewed-by: Michael Kelley +Link: https://lore.kernel.org/r/20250507182227.7421-2-romank@linux.microsoft.com +Signed-off-by: Wei Liu +Message-ID: <20250507182227.7421-2-romank@linux.microsoft.com> +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/hyperv/hv_init.c | 33 ++++++++++++++++++++++++++++++ + arch/x86/hyperv/hv_vtl.c | 44 +++++----------------------------------- + arch/x86/hyperv/ivm.c | 22 ++++++++++++++++++-- + arch/x86/include/asm/mshyperv.h | 6 +++-- + include/hyperv/hvgdk_mini.h | 2 - + 5 files changed, 64 insertions(+), 43 deletions(-) + +--- a/arch/x86/hyperv/hv_init.c ++++ b/arch/x86/hyperv/hv_init.c +@@ -706,3 +706,36 @@ bool hv_is_hyperv_initialized(void) + return hypercall_msr.enable; + } + EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized); ++ ++int hv_apicid_to_vp_index(u32 apic_id) ++{ ++ u64 control; ++ u64 status; ++ unsigned long irq_flags; ++ struct hv_get_vp_from_apic_id_in *input; ++ u32 *output, ret; ++ ++ local_irq_save(irq_flags); ++ ++ input = *this_cpu_ptr(hyperv_pcpu_input_arg); ++ memset(input, 0, sizeof(*input)); ++ input->partition_id = HV_PARTITION_ID_SELF; ++ input->apic_ids[0] = apic_id; ++ ++ output = *this_cpu_ptr(hyperv_pcpu_output_arg); ++ ++ control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_INDEX_FROM_APIC_ID; ++ status = hv_do_hypercall(control, input, output); ++ ret = output[0]; ++ ++ local_irq_restore(irq_flags); ++ ++ if (!hv_result_success(status)) { ++ pr_err("failed to get vp index from apic id %d, status %#llx\n", ++ apic_id, status); ++ return -EINVAL; ++ } ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(hv_apicid_to_vp_index); +--- a/arch/x86/hyperv/hv_vtl.c ++++ b/arch/x86/hyperv/hv_vtl.c +@@ -206,41 +206,9 @@ free_lock: + return ret; + } + +-static int hv_vtl_apicid_to_vp_id(u32 apic_id) +-{ +- u64 control; +- u64 status; +- unsigned long irq_flags; +- struct hv_get_vp_from_apic_id_in *input; +- u32 *output, ret; +- +- local_irq_save(irq_flags); +- +- input = *this_cpu_ptr(hyperv_pcpu_input_arg); +- memset(input, 0, sizeof(*input)); +- input->partition_id = HV_PARTITION_ID_SELF; +- input->apic_ids[0] = apic_id; +- +- output = *this_cpu_ptr(hyperv_pcpu_output_arg); +- +- control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_ID_FROM_APIC_ID; +- status = hv_do_hypercall(control, input, output); +- ret = output[0]; +- +- local_irq_restore(irq_flags); +- +- if (!hv_result_success(status)) { +- pr_err("failed to get vp id from apic id %d, status %#llx\n", +- apic_id, status); +- return -EINVAL; +- } +- +- return ret; +-} +- + static int hv_vtl_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip) + { +- int vp_id, cpu; ++ int vp_index, cpu; + + /* Find the logical CPU for the APIC ID */ + for_each_present_cpu(cpu) { +@@ -251,18 +219,18 @@ static int hv_vtl_wakeup_secondary_cpu(u + return -EINVAL; + + pr_debug("Bringing up CPU with APIC ID %d in VTL2...\n", apicid); +- vp_id = hv_vtl_apicid_to_vp_id(apicid); ++ vp_index = hv_apicid_to_vp_index(apicid); + +- if (vp_id < 0) { ++ if (vp_index < 0) { + pr_err("Couldn't find CPU with APIC ID %d\n", apicid); + return -EINVAL; + } +- if (vp_id > ms_hyperv.max_vp_index) { +- pr_err("Invalid CPU id %d for APIC ID %d\n", vp_id, apicid); ++ if (vp_index > ms_hyperv.max_vp_index) { ++ pr_err("Invalid CPU id %d for APIC ID %d\n", vp_index, apicid); + return -EINVAL; + } + +- return hv_vtl_bringup_vcpu(vp_id, cpu, start_eip); ++ return hv_vtl_bringup_vcpu(vp_index, cpu, start_eip); + } + + int __init hv_vtl_early_init(void) +--- a/arch/x86/hyperv/ivm.c ++++ b/arch/x86/hyperv/ivm.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -288,7 +289,7 @@ static void snp_cleanup_vmsa(struct sev_ + free_page((unsigned long)vmsa); + } + +-int hv_snp_boot_ap(u32 cpu, unsigned long start_ip) ++int hv_snp_boot_ap(u32 apic_id, unsigned long start_ip) + { + struct sev_es_save_area *vmsa = (struct sev_es_save_area *) + __get_free_page(GFP_KERNEL | __GFP_ZERO); +@@ -297,10 +298,27 @@ int hv_snp_boot_ap(u32 cpu, unsigned lon + u64 ret, retry = 5; + struct hv_enable_vp_vtl *start_vp_input; + unsigned long flags; ++ int cpu, vp_index; + + if (!vmsa) + return -ENOMEM; + ++ /* Find the Hyper-V VP index which might be not the same as APIC ID */ ++ vp_index = hv_apicid_to_vp_index(apic_id); ++ if (vp_index < 0 || vp_index > ms_hyperv.max_vp_index) ++ return -EINVAL; ++ ++ /* ++ * Find the Linux CPU number for addressing the per-CPU data, and it ++ * might not be the same as APIC ID. ++ */ ++ for_each_present_cpu(cpu) { ++ if (arch_match_cpu_phys_id(cpu, apic_id)) ++ break; ++ } ++ if (cpu >= nr_cpu_ids) ++ return -EINVAL; ++ + native_store_gdt(&gdtr); + + vmsa->gdtr.base = gdtr.address; +@@ -348,7 +366,7 @@ int hv_snp_boot_ap(u32 cpu, unsigned lon + start_vp_input = (struct hv_enable_vp_vtl *)ap_start_input_arg; + memset(start_vp_input, 0, sizeof(*start_vp_input)); + start_vp_input->partition_id = -1; +- start_vp_input->vp_index = cpu; ++ start_vp_input->vp_index = vp_index; + start_vp_input->target_vtl.target_vtl = ms_hyperv.vtl; + *(u64 *)&start_vp_input->vp_context = __pa(vmsa) | 1; + +--- a/arch/x86/include/asm/mshyperv.h ++++ b/arch/x86/include/asm/mshyperv.h +@@ -268,11 +268,11 @@ int hv_unmap_ioapic_interrupt(int ioapic + #ifdef CONFIG_AMD_MEM_ENCRYPT + bool hv_ghcb_negotiate_protocol(void); + void __noreturn hv_ghcb_terminate(unsigned int set, unsigned int reason); +-int hv_snp_boot_ap(u32 cpu, unsigned long start_ip); ++int hv_snp_boot_ap(u32 apic_id, unsigned long start_ip); + #else + static inline bool hv_ghcb_negotiate_protocol(void) { return false; } + static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {} +-static inline int hv_snp_boot_ap(u32 cpu, unsigned long start_ip) { return 0; } ++static inline int hv_snp_boot_ap(u32 apic_id, unsigned long start_ip) { return 0; } + #endif + + #if defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST) +@@ -306,6 +306,7 @@ static __always_inline u64 hv_raw_get_ms + { + return __rdmsr(reg); + } ++int hv_apicid_to_vp_index(u32 apic_id); + + #else /* CONFIG_HYPERV */ + static inline void hyperv_init(void) {} +@@ -327,6 +328,7 @@ static inline void hv_set_msr(unsigned i + static inline u64 hv_get_msr(unsigned int reg) { return 0; } + static inline void hv_set_non_nested_msr(unsigned int reg, u64 value) { } + static inline u64 hv_get_non_nested_msr(unsigned int reg) { return 0; } ++static inline int hv_apicid_to_vp_index(u32 apic_id) { return -EINVAL; } + #endif /* CONFIG_HYPERV */ + + +--- a/include/hyperv/hvgdk_mini.h ++++ b/include/hyperv/hvgdk_mini.h +@@ -475,7 +475,7 @@ union hv_vp_assist_msr_contents { /* HV + #define HVCALL_CREATE_PORT 0x0095 + #define HVCALL_CONNECT_PORT 0x0096 + #define HVCALL_START_VP 0x0099 +-#define HVCALL_GET_VP_ID_FROM_APIC_ID 0x009a ++#define HVCALL_GET_VP_INDEX_FROM_APIC_ID 0x009a + #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_SPACE 0x00af + #define HVCALL_FLUSH_GUEST_PHYSICAL_ADDRESS_LIST 0x00b0 + #define HVCALL_SIGNAL_EVENT_DIRECT 0x00c0 diff --git a/queue-6.15/x86-iopl-cure-tif_io_bitmap-inconsistencies.patch b/queue-6.15/x86-iopl-cure-tif_io_bitmap-inconsistencies.patch new file mode 100644 index 0000000000..a16d4f7696 --- /dev/null +++ b/queue-6.15/x86-iopl-cure-tif_io_bitmap-inconsistencies.patch @@ -0,0 +1,118 @@ +From 8b68e978718f14fdcb080c2a7791c52a0d09bc6d Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Wed, 26 Feb 2025 16:01:57 +0100 +Subject: x86/iopl: Cure TIF_IO_BITMAP inconsistencies + +From: Thomas Gleixner + +commit 8b68e978718f14fdcb080c2a7791c52a0d09bc6d upstream. + +io_bitmap_exit() is invoked from exit_thread() when a task exists or +when a fork fails. In the latter case the exit_thread() cleans up +resources which were allocated during fork(). + +io_bitmap_exit() invokes task_update_io_bitmap(), which in turn ends up +in tss_update_io_bitmap(). tss_update_io_bitmap() operates on the +current task. If current has TIF_IO_BITMAP set, but no bitmap installed, +tss_update_io_bitmap() crashes with a NULL pointer dereference. + +There are two issues, which lead to that problem: + + 1) io_bitmap_exit() should not invoke task_update_io_bitmap() when + the task, which is cleaned up, is not the current task. That's a + clear indicator for a cleanup after a failed fork(). + + 2) A task should not have TIF_IO_BITMAP set and neither a bitmap + installed nor IOPL emulation level 3 activated. + + This happens when a kernel thread is created in the context of + a user space thread, which has TIF_IO_BITMAP set as the thread + flags are copied and the IO bitmap pointer is cleared. + + Other than in the failed fork() case this has no impact because + kernel threads including IO workers never return to user space and + therefore never invoke tss_update_io_bitmap(). + +Cure this by adding the missing cleanups and checks: + + 1) Prevent io_bitmap_exit() to invoke task_update_io_bitmap() if + the to be cleaned up task is not the current task. + + 2) Clear TIF_IO_BITMAP in copy_thread() unconditionally. For user + space forks it is set later, when the IO bitmap is inherited in + io_bitmap_share(). + +For paranoia sake, add a warning into tss_update_io_bitmap() to catch +the case, when that code is invoked with inconsistent state. + +Fixes: ea5f1cd7ab49 ("x86/ioperm: Remove bitmap if all permissions dropped") +Reported-by: syzbot+e2b1803445d236442e54@syzkaller.appspotmail.com +Signed-off-by: Thomas Gleixner +Signed-off-by: Borislav Petkov (AMD) +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/87wmdceom2.ffs@tglx +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/ioport.c | 13 +++++++++---- + arch/x86/kernel/process.c | 6 ++++++ + 2 files changed, 15 insertions(+), 4 deletions(-) + +--- a/arch/x86/kernel/ioport.c ++++ b/arch/x86/kernel/ioport.c +@@ -33,8 +33,9 @@ void io_bitmap_share(struct task_struct + set_tsk_thread_flag(tsk, TIF_IO_BITMAP); + } + +-static void task_update_io_bitmap(struct task_struct *tsk) ++static void task_update_io_bitmap(void) + { ++ struct task_struct *tsk = current; + struct thread_struct *t = &tsk->thread; + + if (t->iopl_emul == 3 || t->io_bitmap) { +@@ -54,7 +55,12 @@ void io_bitmap_exit(struct task_struct * + struct io_bitmap *iobm = tsk->thread.io_bitmap; + + tsk->thread.io_bitmap = NULL; +- task_update_io_bitmap(tsk); ++ /* ++ * Don't touch the TSS when invoked on a failed fork(). TSS ++ * reflects the state of @current and not the state of @tsk. ++ */ ++ if (tsk == current) ++ task_update_io_bitmap(); + if (iobm && refcount_dec_and_test(&iobm->refcnt)) + kfree(iobm); + } +@@ -192,8 +198,7 @@ SYSCALL_DEFINE1(iopl, unsigned int, leve + } + + t->iopl_emul = level; +- task_update_io_bitmap(current); +- ++ task_update_io_bitmap(); + return 0; + } + +--- a/arch/x86/kernel/process.c ++++ b/arch/x86/kernel/process.c +@@ -181,6 +181,7 @@ int copy_thread(struct task_struct *p, c + frame->ret_addr = (unsigned long) ret_from_fork_asm; + p->thread.sp = (unsigned long) fork_frame; + p->thread.io_bitmap = NULL; ++ clear_tsk_thread_flag(p, TIF_IO_BITMAP); + p->thread.iopl_warn = 0; + memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); + +@@ -469,6 +470,11 @@ void native_tss_update_io_bitmap(void) + } else { + struct io_bitmap *iobm = t->io_bitmap; + ++ if (WARN_ON_ONCE(!iobm)) { ++ clear_thread_flag(TIF_IO_BITMAP); ++ native_tss_invalidate_io_bitmap(); ++ } ++ + /* + * Only copy bitmap data when the sequence number differs. The + * update time is accounted to the incoming task. diff --git a/queue-6.15/xen-arm-call-uaccess_ttbr0_enable-for-dm_op-hypercall.patch b/queue-6.15/xen-arm-call-uaccess_ttbr0_enable-for-dm_op-hypercall.patch new file mode 100644 index 0000000000..34e74ecf37 --- /dev/null +++ b/queue-6.15/xen-arm-call-uaccess_ttbr0_enable-for-dm_op-hypercall.patch @@ -0,0 +1,63 @@ +From 7f9bbc1140ff8796230bc2634055763e271fd692 Mon Sep 17 00:00:00 2001 +From: Stefano Stabellini +Date: Mon, 12 May 2025 14:54:52 -0700 +Subject: xen/arm: call uaccess_ttbr0_enable for dm_op hypercall + +From: Stefano Stabellini + +commit 7f9bbc1140ff8796230bc2634055763e271fd692 upstream. + +dm_op hypercalls might come from userspace and pass memory addresses as +parameters. The memory addresses typically correspond to buffers +allocated in userspace to hold extra hypercall parameters. + +On ARM, when CONFIG_ARM64_SW_TTBR0_PAN is enabled, they might not be +accessible by Xen, as a result ioreq hypercalls might fail. See the +existing comment in arch/arm64/xen/hypercall.S regarding privcmd_call +for reference. + +For privcmd_call, Linux calls uaccess_ttbr0_enable before issuing the +hypercall thanks to commit 9cf09d68b89a. We need to do the same for +dm_op. This resolves the problem. + +Cc: stable@kernel.org +Fixes: 9cf09d68b89a ("arm64: xen: Enable user access before a privcmd hvc call") +Signed-off-by: Stefano Stabellini +Reviewed-by: Juergen Gross +Message-ID: +Signed-off-by: Juergen Gross +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/xen/hypercall.S | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +--- a/arch/arm64/xen/hypercall.S ++++ b/arch/arm64/xen/hypercall.S +@@ -83,7 +83,26 @@ HYPERCALL3(vcpu_op); + HYPERCALL1(platform_op_raw); + HYPERCALL2(multicall); + HYPERCALL2(vm_assist); +-HYPERCALL3(dm_op); ++ ++SYM_FUNC_START(HYPERVISOR_dm_op) ++ mov x16, #__HYPERVISOR_dm_op; \ ++ /* ++ * dm_op hypercalls are issued by the userspace. The kernel needs to ++ * enable access to TTBR0_EL1 as the hypervisor would issue stage 1 ++ * translations to user memory via AT instructions. Since AT ++ * instructions are not affected by the PAN bit (ARMv8.1), we only ++ * need the explicit uaccess_enable/disable if the TTBR0 PAN emulation ++ * is enabled (it implies that hardware UAO and PAN disabled). ++ */ ++ uaccess_ttbr0_enable x6, x7, x8 ++ hvc XEN_IMM ++ ++ /* ++ * Disable userspace access from kernel once the hyp call completed. ++ */ ++ uaccess_ttbr0_disable x6, x7 ++ ret ++SYM_FUNC_END(HYPERVISOR_dm_op); + + SYM_FUNC_START(privcmd_call) + mov x16, x0 diff --git a/queue-6.15/xfs-don-t-assume-perags-are-initialised-when-trimming-ags.patch b/queue-6.15/xfs-don-t-assume-perags-are-initialised-when-trimming-ags.patch new file mode 100644 index 0000000000..6e7132a5cc --- /dev/null +++ b/queue-6.15/xfs-don-t-assume-perags-are-initialised-when-trimming-ags.patch @@ -0,0 +1,86 @@ +From 23be716b1c4f3f3a6c00ee38d51a57ef7db9ef7d Mon Sep 17 00:00:00 2001 +From: Dave Chinner +Date: Thu, 1 May 2025 09:27:24 +1000 +Subject: xfs: don't assume perags are initialised when trimming AGs + +From: Dave Chinner + +commit 23be716b1c4f3f3a6c00ee38d51a57ef7db9ef7d upstream. + +When running fstrim immediately after mounting a V4 filesystem, +the fstrim fails to trim all the free space in the filesystem. It +only trims the first extent in the by-size free space tree in each +AG and then returns. If a second fstrim is then run, it runs +correctly and the entire free space in the filesystem is iterated +and discarded correctly. + +The problem lies in the setup of the trim cursor - it assumes that +pag->pagf_longest is valid without either reading the AGF first or +checking if xfs_perag_initialised_agf(pag) is true or not. + +As a result, when a filesystem is mounted without reading the AGF +(e.g. a clean mount on a v4 filesystem) and the first operation is a +fstrim call, pag->pagf_longest is zero and so the free extent search +starts at the wrong end of the by-size btree and exits after +discarding the first record in the tree. + +Fix this by deferring the initialisation of tcur->count to after +we have locked the AGF and guaranteed that the perag is properly +initialised. We trigger this on tcur->count == 0 after locking the +AGF, as this will only occur on the first call to +xfs_trim_gather_extents() for each AG. If we need to iterate, +tcur->count will be set to the length of the record we need to +restart at, so we can use this to ensure we only sample a valid +pag->pagf_longest value for the iteration. + +Signed-off-by: Dave Chinner +Reviewed-by: Bill O'Donnell +Reviewed-by: Darrick J. Wong +Fixes: 89cfa899608f ("xfs: reduce AGF hold times during fstrim operations") +Cc: # v6.6 +Signed-off-by: Carlos Maiolino +Signed-off-by: Greg Kroah-Hartman +--- + fs/xfs/xfs_discard.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +--- a/fs/xfs/xfs_discard.c ++++ b/fs/xfs/xfs_discard.c +@@ -167,6 +167,14 @@ xfs_discard_extents( + return error; + } + ++/* ++ * Care must be taken setting up the trim cursor as the perags may not have been ++ * initialised when the cursor is initialised. e.g. a clean mount which hasn't ++ * read in AGFs and the first operation run on the mounted fs is a trim. This ++ * can result in perag fields that aren't initialised until ++ * xfs_trim_gather_extents() calls xfs_alloc_read_agf() to lock down the AG for ++ * the free space search. ++ */ + struct xfs_trim_cur { + xfs_agblock_t start; + xfs_extlen_t count; +@@ -204,6 +212,14 @@ xfs_trim_gather_extents( + if (error) + goto out_trans_cancel; + ++ /* ++ * First time through tcur->count will not have been initialised as ++ * pag->pagf_longest is not guaranteed to be valid before we read ++ * the AGF buffer above. ++ */ ++ if (!tcur->count) ++ tcur->count = pag->pagf_longest; ++ + if (tcur->by_bno) { + /* sub-AG discard request always starts at tcur->start */ + cur = xfs_bnobt_init_cursor(mp, tp, agbp, pag); +@@ -350,7 +366,6 @@ xfs_trim_perag_extents( + { + struct xfs_trim_cur tcur = { + .start = start, +- .count = pag->pagf_longest, + .end = end, + .minlen = minlen, + };