]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees
authorSasha Levin <sashal@kernel.org>
Tue, 28 Jul 2026 16:09:36 +0000 (12:09 -0400)
committerSasha Levin <sashal@kernel.org>
Tue, 28 Jul 2026 16:09:36 +0000 (12:09 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
29 files changed:
queue-5.10/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch [new file with mode: 0644]
queue-5.15/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch [new file with mode: 0644]
queue-6.1/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch [new file with mode: 0644]
queue-6.1/bpf-prefer-dirty-packs-for-ebpf-allocations.patch [new file with mode: 0644]
queue-6.1/bpf-prefer-packs-that-won-t-trigger-an-ibpb-flush-on.patch [new file with mode: 0644]
queue-6.1/bpf-restrict-jit-predictor-flush-to-cbpf.patch [new file with mode: 0644]
queue-6.1/bpf-skip-redundant-ibpb-in-pack-allocator.patch [new file with mode: 0644]
queue-6.1/bpf-support-for-hardening-against-jit-spraying.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch [new file with mode: 0644]
queue-6.1/x86-bugs-enable-ibpb-flush-on-bpf-jit-allocation.patch [new file with mode: 0644]
queue-6.12/risc-v-kvm-serialize-virtual-interrupt-pending-state.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch [new file with mode: 0644]
queue-6.18/selftests-bpf-adjust-verifier_map_ptr-for-the-map-s-.patch [new file with mode: 0644]
queue-6.18/selftests-bpf-keep-verifier_map_ptr-exercising-ops-p.patch [new file with mode: 0644]
queue-6.18/series
queue-6.18/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch [new file with mode: 0644]
queue-6.6/risc-v-kvm-serialize-virtual-interrupt-pending-state.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch [new file with mode: 0644]
queue-7.1/selftests-bpf-adjust-verifier_map_ptr-for-the-map-s-.patch [new file with mode: 0644]
queue-7.1/selftests-bpf-keep-verifier_map_ptr-exercising-ops-p.patch [new file with mode: 0644]
queue-7.1/series
queue-7.1/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch [new file with mode: 0644]

diff --git a/queue-5.10/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch b/queue-5.10/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
new file mode 100644 (file)
index 0000000..9b526c7
--- /dev/null
@@ -0,0 +1,73 @@
+From 29ae8286712519330c5689704acdd299b2ebaf62 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 17:54:34 +0800
+Subject: bpf: Fix ld_{abs,ind} failure path analysis in subprogs
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit ee861486e377edc55361c08dcbceab3f6b6577bd upstream.
+
+Usage of ld_{abs,ind} instructions got extended into subprogs some time
+ago via commit 09b28d76eac4 ("bpf: Add abnormal return checks."). These
+are only allowed in subprograms when the latter are BTF annotated and
+have scalar return types.
+
+The code generator in bpf_gen_ld_abs() has an abnormal exit path (r0=0 +
+exit) from legacy cBPF times. While the enforcement is on scalar return
+types, the verifier must also simulate the path of abnormal exit if the
+packet data load via ld_{abs,ind} failed.
+
+This is currently not the case. Fix it by having the verifier simulate
+both success and failure paths, and extend it in similar ways as we do
+for tail calls. The success path (r0=unknown, continue to next insn) is
+pushed onto stack for later validation and the r0=0 and return to the
+caller is done on the fall-through side.
+
+Fixes: 09b28d76eac4 ("bpf: Add abnormal return checks.")
+Reported-by: STAR Labs SG <info@starlabs.sg>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260408191242.526279-2-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[ Dropped visit_abnormal_return_insn changes: depends on 7.0 symbols from
+ e40f5a6bf88a ("bpf: correct stack liveness for tail calls");
+ Hunk1: adapted IS_ERR/PTR_ERR to !branch/-EFAULT to match push_stack()
+ NULL-on-failure convention;
+ Dropped mark_reg_scratched(), which only affects log verbosity, introduced
+ by 0f55f9ed21f9 ("bpf: Only print scratched registers and stack slots to
+ verifier logs.").]
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 19e1f7fff07a9c..058c05e7f144c7 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -8556,6 +8556,22 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
+       mark_reg_unknown(env, regs, BPF_REG_0);
+       /* ld_abs load up to 32-bit skb data. */
+       regs[BPF_REG_0].subreg_def = env->insn_idx + 1;
++      /*
++       * See bpf_gen_ld_abs() which emits a hidden BPF_EXIT with r0=0
++       * which must be explored by the verifier when in a subprog.
++       */
++      if (env->cur_state->curframe) {
++              struct bpf_verifier_state *branch;
++
++              branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
++              if (!branch)
++                      return -EFAULT;
++              mark_reg_known_zero(env, regs, BPF_REG_0);
++              err = prepare_func_exit(env, &env->insn_idx);
++              if (err)
++                      return err;
++              env->insn_idx--;
++      }
+       return 0;
+ }
+-- 
+2.53.0
+
index 10dd46bc181ae9418e67114553664f08283f5555..4304ed3faae72a30576aab13f7c59bb36fb6f747 100644 (file)
@@ -57,3 +57,5 @@ usb-serial-io_edgeport-cap-received-transmit-credits.patch
 usb-serial-option-add-tdtech-mt5710-cn.patch
 posix-cpu-timers-prevent-uaf-caused-by-non-leader-ex.patch
 crypto-rsa-pkcs1pad-don-t-warn-on-an-empty-digest.patch
+bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
+usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
diff --git a/queue-5.10/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch b/queue-5.10/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
new file mode 100644 (file)
index 0000000..edec8e0
--- /dev/null
@@ -0,0 +1,98 @@
+From 67de533bcda4a5bc79f7041ab651c6f09ec2fb32 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 09:50:00 +0800
+Subject: usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
+
+From: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+
+commit 1fc50f1ecde39feb4fccdaf4bc71aa6c0eb25c49 upstream.
+
+The VIA VL805/806 xHCI controller advertises AC64, but fails to handle
+DMA addresses at or above 0x1000000000. On systems with large amounts of
+RAM, this can cause USB device failures when the controller is given DMA
+addresses beyond its usable address width.
+
+Do not use XHCI_NO_64BIT_SUPPORT for this controller. That quirk clears
+the cached AC64 capability and limits DMA to 32 bits, causing unnecessary
+bouncing for addresses between 4GiB and 64GiB and hiding the controller's
+real AC64 capability from code that may need to distinguish register
+access width from usable DMA address width.
+
+Track the usable DMA address width separately from the AC64 capability.
+Initialize the generic xhci->dma_mask_bits field to 64 and let PCI quirks
+reduce it for controllers with narrower DMA support. Set VIA VL805/806 to
+36 bits so the DMA API only hands it addresses in the range it can handle
+while keeping HCCPARAMS1.AC64 visible.
+
+Cc: stable <stable@kernel.org>
+Signed-off-by: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+Link: https://patch.msgid.link/20260630-xhci-via-dma-fix-v3-1-690dcb8cf75a@ultrarisc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-pci.c |  1 +
+ drivers/usb/host/xhci.c     | 15 ++++++++++-----
+ drivers/usb/host/xhci.h     |  1 +
+ 3 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
+index 2be84d5e9261da..6e87f36afb49c4 100644
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -302,6 +302,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+               xhci->quirks |= XHCI_LPM_SUPPORT;
+               xhci->quirks |= XHCI_TRB_OVERFETCH;
+               xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
++              xhci->dma_mask_bits = 36;
+       }
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 03de77fbe3af34..2cc27dba08e2d6 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -5323,6 +5323,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->hci_version > 0x100)
+               xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
++      xhci->dma_mask_bits = 64;
+       xhci->quirks |= quirks;
+       get_quirks(dev, xhci);
+@@ -5358,12 +5359,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->quirks & XHCI_NO_64BIT_SUPPORT)
+               xhci->hcc_params &= ~BIT(0);
+-      /* Set dma_mask and coherent_dma_mask to 64-bits,
+-       * if xHC supports 64-bit addressing */
++      /*
++       * Set dma_mask and coherent_dma_mask to 64-bits if xHC supports
++       * 64-bit addressing, unless a controller-specific quirk callback
++       * limits the usable address width.
++       */
+       if (HCC_64BIT_ADDR(xhci->hcc_params) &&
+-                      !dma_set_mask(dev, DMA_BIT_MASK(64))) {
+-              xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+-              dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
++          !dma_set_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits))) {
++              xhci_dbg(xhci, "Enabling %u-bit DMA addresses.\n",
++                       xhci->dma_mask_bits);
++              dma_set_coherent_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits));
+       } else {
+               /*
+                * This is to avoid error in cases where a 32-bit USB
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 4d4ac8ec614b20..8d1c6c59e9e927 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1782,6 +1782,7 @@ struct xhci_hcd {
+       int             event_ring_max;
+       /* 4KB min, 128MB max */
+       int             page_size;
++      unsigned int    dma_mask_bits;
+       /* Valid values are 12 to 20, inclusive */
+       int             page_shift;
+       /* msi-x vectors */
+-- 
+2.53.0
+
diff --git a/queue-5.15/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch b/queue-5.15/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
new file mode 100644 (file)
index 0000000..7bd1202
--- /dev/null
@@ -0,0 +1,73 @@
+From d0768ec9dbcb21527597bb22c39f5ff142e1b0db Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 17:54:34 +0800
+Subject: bpf: Fix ld_{abs,ind} failure path analysis in subprogs
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit ee861486e377edc55361c08dcbceab3f6b6577bd upstream.
+
+Usage of ld_{abs,ind} instructions got extended into subprogs some time
+ago via commit 09b28d76eac4 ("bpf: Add abnormal return checks."). These
+are only allowed in subprograms when the latter are BTF annotated and
+have scalar return types.
+
+The code generator in bpf_gen_ld_abs() has an abnormal exit path (r0=0 +
+exit) from legacy cBPF times. While the enforcement is on scalar return
+types, the verifier must also simulate the path of abnormal exit if the
+packet data load via ld_{abs,ind} failed.
+
+This is currently not the case. Fix it by having the verifier simulate
+both success and failure paths, and extend it in similar ways as we do
+for tail calls. The success path (r0=unknown, continue to next insn) is
+pushed onto stack for later validation and the r0=0 and return to the
+caller is done on the fall-through side.
+
+Fixes: 09b28d76eac4 ("bpf: Add abnormal return checks.")
+Reported-by: STAR Labs SG <info@starlabs.sg>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260408191242.526279-2-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[ Dropped visit_abnormal_return_insn changes: depends on 7.0 symbols from
+ e40f5a6bf88a ("bpf: correct stack liveness for tail calls");
+ Hunk1: adapted IS_ERR/PTR_ERR to !branch/-EFAULT to match push_stack()
+ NULL-on-failure convention;
+ Dropped mark_reg_scratched(), which only affects log verbosity, introduced
+ by 0f55f9ed21f9 ("bpf: Only print scratched registers and stack slots to
+ verifier logs.").]
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index ec447854f53450..5e71d58e4a3006 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -9644,6 +9644,22 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
+       mark_reg_unknown(env, regs, BPF_REG_0);
+       /* ld_abs load up to 32-bit skb data. */
+       regs[BPF_REG_0].subreg_def = env->insn_idx + 1;
++      /*
++       * See bpf_gen_ld_abs() which emits a hidden BPF_EXIT with r0=0
++       * which must be explored by the verifier when in a subprog.
++       */
++      if (env->cur_state->curframe) {
++              struct bpf_verifier_state *branch;
++
++              branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
++              if (!branch)
++                      return -EFAULT;
++              mark_reg_known_zero(env, regs, BPF_REG_0);
++              err = prepare_func_exit(env, &env->insn_idx);
++              if (err)
++                      return err;
++              env->insn_idx--;
++      }
+       return 0;
+ }
+-- 
+2.53.0
+
index bbfea89b7238e680832292e5fe452b1814c320ee..9b8c9fc633fdc23cb44d325b4284401572bee0ab 100644 (file)
@@ -74,3 +74,5 @@ usb-serial-option-add-tdtech-mt5710-cn.patch
 posix-cpu-timers-prevent-uaf-caused-by-non-leader-ex.patch
 crypto-rsa-pkcs1pad-don-t-warn-on-an-empty-digest.patch
 revert-drm-amd-display-add-missing-kdoc-for-allm-par.patch
+bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
+usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
diff --git a/queue-5.15/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch b/queue-5.15/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
new file mode 100644 (file)
index 0000000..dea0dc3
--- /dev/null
@@ -0,0 +1,98 @@
+From b5ca4f4659b7447dcf31b14b78743f87b73a8392 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 10:25:14 +0800
+Subject: usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
+
+From: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+
+commit 1fc50f1ecde39feb4fccdaf4bc71aa6c0eb25c49 upstream.
+
+The VIA VL805/806 xHCI controller advertises AC64, but fails to handle
+DMA addresses at or above 0x1000000000. On systems with large amounts of
+RAM, this can cause USB device failures when the controller is given DMA
+addresses beyond its usable address width.
+
+Do not use XHCI_NO_64BIT_SUPPORT for this controller. That quirk clears
+the cached AC64 capability and limits DMA to 32 bits, causing unnecessary
+bouncing for addresses between 4GiB and 64GiB and hiding the controller's
+real AC64 capability from code that may need to distinguish register
+access width from usable DMA address width.
+
+Track the usable DMA address width separately from the AC64 capability.
+Initialize the generic xhci->dma_mask_bits field to 64 and let PCI quirks
+reduce it for controllers with narrower DMA support. Set VIA VL805/806 to
+36 bits so the DMA API only hands it addresses in the range it can handle
+while keeping HCCPARAMS1.AC64 visible.
+
+Cc: stable@kernel.org
+Signed-off-by: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+Link: https://patch.msgid.link/20260630-xhci-via-dma-fix-v3-1-690dcb8cf75a@ultrarisc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-pci.c |  1 +
+ drivers/usb/host/xhci.c     | 15 ++++++++++-----
+ drivers/usb/host/xhci.h     |  1 +
+ 3 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
+index 9c7491ac28f2f3..f8988f110dcff5 100644
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -338,6 +338,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+       if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == PCI_DEVICE_ID_VIA_VL805) {
+               xhci->quirks |= XHCI_LPM_SUPPORT;
+               xhci->quirks |= XHCI_TRB_OVERFETCH;
++              xhci->dma_mask_bits = 36;
+       }
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 0ac438392545dd..823fe397bfb105 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -5398,6 +5398,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->hci_version > 0x100)
+               xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
++      xhci->dma_mask_bits = 64;
+       /* xhci-plat or xhci-pci might have set max_interrupters already */
+       if ((!xhci->max_interrupters) ||
+           xhci->max_interrupters > HCS_MAX_INTRS(xhci->hcs_params1))
+@@ -5438,12 +5439,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->quirks & XHCI_NO_64BIT_SUPPORT)
+               xhci->hcc_params &= ~BIT(0);
+-      /* Set dma_mask and coherent_dma_mask to 64-bits,
+-       * if xHC supports 64-bit addressing */
++      /*
++       * Set dma_mask and coherent_dma_mask to 64-bits if xHC supports
++       * 64-bit addressing, unless a controller-specific quirk callback
++       * limits the usable address width.
++       */
+       if (HCC_64BIT_ADDR(xhci->hcc_params) &&
+-                      !dma_set_mask(dev, DMA_BIT_MASK(64))) {
+-              xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+-              dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
++          !dma_set_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits))) {
++              xhci_dbg(xhci, "Enabling %u-bit DMA addresses.\n",
++                       xhci->dma_mask_bits);
++              dma_set_coherent_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits));
+       } else {
+               /*
+                * This is to avoid error in cases where a 32-bit USB
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index ac33baa2b0f82d..96519c446778d1 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1544,6 +1544,7 @@ struct xhci_hcd {
+       int             event_ring_max;
+       /* 4KB min, 128MB max */
+       int             page_size;
++      unsigned int    dma_mask_bits;
+       /* Valid values are 12 to 20, inclusive */
+       int             page_shift;
+       /* msi-x vectors */
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch b/queue-6.1/bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
new file mode 100644 (file)
index 0000000..c2138e6
--- /dev/null
@@ -0,0 +1,71 @@
+From aa07a55e06f2ec3dfb56964de6666e3feb2290ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 17:49:37 +0800
+Subject: bpf: Fix ld_{abs,ind} failure path analysis in subprogs
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit ee861486e377edc55361c08dcbceab3f6b6577bd upstream.
+
+Usage of ld_{abs,ind} instructions got extended into subprogs some time
+ago via commit 09b28d76eac4 ("bpf: Add abnormal return checks."). These
+are only allowed in subprograms when the latter are BTF annotated and
+have scalar return types.
+
+The code generator in bpf_gen_ld_abs() has an abnormal exit path (r0=0 +
+exit) from legacy cBPF times. While the enforcement is on scalar return
+types, the verifier must also simulate the path of abnormal exit if the
+packet data load via ld_{abs,ind} failed.
+
+This is currently not the case. Fix it by having the verifier simulate
+both success and failure paths, and extend it in similar ways as we do
+for tail calls. The success path (r0=unknown, continue to next insn) is
+pushed onto stack for later validation and the r0=0 and return to the
+caller is done on the fall-through side.
+
+Fixes: 09b28d76eac4 ("bpf: Add abnormal return checks.")
+Reported-by: STAR Labs SG <info@starlabs.sg>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260408191242.526279-2-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[ Dropped visit_abnormal_return_insn changes: depends on 7.0 symbols from
+ e40f5a6bf88a ("bpf: correct stack liveness for tail calls");
+ Hunk1: adapted IS_ERR/PTR_ERR to !branch/-EFAULT to match push_stack()
+ NULL-on-failure convention. ]
+Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 4380082f321c7a..4ff1d5007a23e2 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -10751,6 +10751,23 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
+       mark_reg_unknown(env, regs, BPF_REG_0);
+       /* ld_abs load up to 32-bit skb data. */
+       regs[BPF_REG_0].subreg_def = env->insn_idx + 1;
++      /*
++       * See bpf_gen_ld_abs() which emits a hidden BPF_EXIT with r0=0
++       * which must be explored by the verifier when in a subprog.
++       */
++      if (env->cur_state->curframe) {
++              struct bpf_verifier_state *branch;
++
++              mark_reg_scratched(env, BPF_REG_0);
++              branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
++              if (!branch)
++                      return -EFAULT;
++              mark_reg_known_zero(env, regs, BPF_REG_0);
++              err = prepare_func_exit(env, &env->insn_idx);
++              if (err)
++                      return err;
++              env->insn_idx--;
++      }
+       return 0;
+ }
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-prefer-dirty-packs-for-ebpf-allocations.patch b/queue-6.1/bpf-prefer-dirty-packs-for-ebpf-allocations.patch
new file mode 100644 (file)
index 0000000..a459dcd
--- /dev/null
@@ -0,0 +1,49 @@
+From 4674e7a68b938484143f0e5167d48bb2866dddf3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 15:56:57 -0700
+Subject: bpf: Prefer dirty packs for eBPF allocations
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit b72e29e0f7ee329d89f86db8700c8ea99b4a370a upstream.
+
+The pack allocator only flushes predictors when reusing a dirty pack for
+cBPF, eBPF allocations never trigger a flush. Currently, eBPF picks the
+first free pack, which could be a clean pack. As an optimization, leaving
+a clean pack for cBPF can avoid flushes.
+
+Prefer dirty packs for eBPF and keep clean packs free for cBPF. This
+mirrors the existing cBPF preference for clean packs: each program kind
+prefers the pack that avoids an extra flush, and falls back to the other
+kind only when no preferred pack has room. eBPF reuse of a dirty pack is
+harmless since eBPF being privileged does not flush.
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/core.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index 926bf11aeaf21a..4ea21434bf78e6 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -946,10 +946,10 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool
+                       goto found_free_area;
+               /*
+                * cBPF reuse of a dirty pack triggers a flush, so prefer a
+-               * clean pack for cBPF. eBPF never flushes, so pick the first
+-               * free pack, dirty or clean.
++               * clean pack for cBPF. eBPF never flushes, so steer it to a
++               * dirty pack and keep clean packs free for cBPF.
+                */
+-              if (!was_classic || !pack->arch_flush_needed)
++              if (was_classic ^ pack->arch_flush_needed)
+                       goto found_free_area;
+               if (!fallback_pack) {
+                       fallback_pack = pack;
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-prefer-packs-that-won-t-trigger-an-ibpb-flush-on.patch b/queue-6.1/bpf-prefer-packs-that-won-t-trigger-an-ibpb-flush-on.patch
new file mode 100644 (file)
index 0000000..320aa07
--- /dev/null
@@ -0,0 +1,88 @@
+From b3af5f1c9afb58eeb3636a2aa0b39b79dffcbc93 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 15:56:42 -0700
+Subject: bpf: Prefer packs that won't trigger an IBPB flush on allocation
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit a9b1f19a6a673ba06820898d0f1ad02883ea1639 upstream.
+
+Currently BPF pack allocator picks the chunks from the first available
+pack. While this is okay, it naturally leads to more frequent flushes
+when there are multiple packs in the system that weren't used since the
+last flush.
+
+As an optimization prefer allocating the new programs from packs that
+are unused since last flush. When all packs are dirty, allocation forces
+a flush and marks all packs clean.
+
+Below are some future optimizations ideas:
+
+  1. Currently, the "dirty" tracking is only done at the pack-level.
+     Flush frequency can further be reduced with chunk-level tracking.
+     This requires a new bitmap per-pack to track the dirty state.
+  2. IBPB flush is done on all CPUs, even if only a single CPU ran the
+     BPF program. On a system with hundreds of CPUs this could be a
+     major bottleneck forcing hundreds of IPIs to deliver the flush.
+     The solution is to track the CPUs where a BPF program ran, and
+     issue IBPB only on those CPUs.
+  3. Avoid IBPB when flush is already done at other sources (e.g.
+     context switch).
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/core.c | 27 ++++++++++++++++++++++++---
+ 1 file changed, 24 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index 5a0f804ecdf404..926bf11aeaf21a 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -912,8 +912,8 @@ static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_ins
+ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool was_classic)
+ {
+       unsigned int nbits = BPF_PROG_SIZE_TO_NBITS(size);
+-      struct bpf_prog_pack *pack;
+-      unsigned long pos;
++      struct bpf_prog_pack *pack, *fallback_pack = NULL;
++      unsigned long pos, fallback_pos = 0;
+       void *ptr = NULL;
+       mutex_lock(&pack_mutex);
+@@ -939,8 +939,29 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool
+       list_for_each_entry(pack, &pack_list, list) {
+               pos = bitmap_find_next_zero_area(pack->bitmap, BPF_PROG_CHUNK_COUNT, 0,
+                                                nbits, 0);
+-              if (pos < BPF_PROG_CHUNK_COUNT)
++              if (pos >= BPF_PROG_CHUNK_COUNT)
++                      continue;
++              /* Flush not enabled, use any pack */
++              if (!static_branch_unlikely(&bpf_pred_flush_enabled))
+                       goto found_free_area;
++              /*
++               * cBPF reuse of a dirty pack triggers a flush, so prefer a
++               * clean pack for cBPF. eBPF never flushes, so pick the first
++               * free pack, dirty or clean.
++               */
++              if (!was_classic || !pack->arch_flush_needed)
++                      goto found_free_area;
++              if (!fallback_pack) {
++                      fallback_pack = pack;
++                      fallback_pos = pos;
++              }
++      }
++
++      /* No preferred pack found */
++      if (fallback_pack) {
++              pack = fallback_pack;
++              pos = fallback_pos;
++              goto found_free_area;
+       }
+       pack = alloc_new_pack(bpf_fill_ill_insns);
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-restrict-jit-predictor-flush-to-cbpf.patch b/queue-6.1/bpf-restrict-jit-predictor-flush-to-cbpf.patch
new file mode 100644 (file)
index 0000000..4737ff9
--- /dev/null
@@ -0,0 +1,137 @@
+From 513fdc68f0aa09190e09d7aa3505658f71f84441 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 15:56:11 -0700
+Subject: bpf: Restrict JIT predictor flush to cBPF
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit 0bb99f2cfaae6822d734d69722de30af823efdf3 upstream.
+
+Currently predictor flush on memory reuse is done for all BPF JIT
+allocations, but only cBPF programs can be loaded by an unprivileged user.
+eBPF is privileged by default, and flushing predictors for all CPUs on
+every eBPF reuse penalizes the common case for no security benefit.
+
+eBPF allocations can be frequent on busy systems, only flush predictors
+for cBPF programs. Trampoline and dispatcher allocations also skip the
+flush as they are eBPF-only.
+
+  [pawan: backport dropped "was_classic" hunk for arches that do not
+          support pack allocator]
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/net/bpf_jit_comp.c |  3 ++-
+ include/linux/filter.h      |  5 +++--
+ kernel/bpf/core.c           | 13 ++++++++-----
+ kernel/bpf/dispatcher.c     |  2 +-
+ 4 files changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
+index 095fec941bb739..30c6a021abcaf0 100644
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -2553,7 +2553,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
+                       /* allocate module memory for x86 insns and extable */
+                       header = bpf_jit_binary_pack_alloc(roundup(proglen, align) + extable_size,
+                                                          &image, align, &rw_header, &rw_image,
+-                                                         jit_fill_hole);
++                                                         jit_fill_hole,
++                                                         bpf_prog_was_classic(prog));
+                       if (!header) {
+                               prog = orig_prog;
+                               goto out_addrs;
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index fa7bb6f995989e..673aef4e1465af 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -1082,7 +1082,7 @@ void bpf_jit_free(struct bpf_prog *fp);
+ struct bpf_binary_header *
+ bpf_jit_binary_pack_hdr(const struct bpf_prog *fp);
+-void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns);
++void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool was_classic);
+ void bpf_prog_pack_free(struct bpf_binary_header *hdr);
+ static inline bool bpf_prog_kallsyms_verify_off(const struct bpf_prog *fp)
+@@ -1096,7 +1096,8 @@ bpf_jit_binary_pack_alloc(unsigned int proglen, u8 **ro_image,
+                         unsigned int alignment,
+                         struct bpf_binary_header **rw_hdr,
+                         u8 **rw_image,
+-                        bpf_jit_fill_hole_t bpf_fill_ill_insns);
++                        bpf_jit_fill_hole_t bpf_fill_ill_insns,
++                        bool was_classic);
+ int bpf_jit_binary_pack_finalize(struct bpf_prog *prog,
+                                struct bpf_binary_header *ro_header,
+                                struct bpf_binary_header *rw_header);
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index 4643554c6e3a9c..f78ee18bab3b55 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -906,7 +906,7 @@ static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_ins
+       return pack;
+ }
+-void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
++void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool was_classic)
+ {
+       unsigned int nbits = BPF_PROG_SIZE_TO_NBITS(size);
+       struct bpf_prog_pack *pack;
+@@ -921,7 +921,7 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
+                * safe because cBPF programs (the unprivileged attack surface)
+                * are bounded well below a pack size.
+                */
+-              if (static_branch_unlikely(&bpf_pred_flush_enabled))
++              if (was_classic && static_branch_unlikely(&bpf_pred_flush_enabled))
+                       pr_warn_once("BPF: Predictors not flushed for allocations greater than BPF_PROG_PACK_SIZE\n");
+               size = round_up(size, PAGE_SIZE);
+               ptr = module_alloc(size);
+@@ -947,7 +947,9 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
+       pos = 0;
+ found_free_area:
+-      static_call_cond(bpf_arch_pred_flush)();
++      /* Flush only for cBPF as it may contain a crafted gadget */
++      if (static_branch_unlikely(&bpf_pred_flush_enabled) && was_classic)
++              static_call_cond(bpf_arch_pred_flush)();
+       bitmap_set(pack->bitmap, pos, nbits);
+       ptr = (void *)(pack->ptr) + (pos << BPF_PROG_CHUNK_SHIFT);
+@@ -1107,7 +1109,8 @@ bpf_jit_binary_pack_alloc(unsigned int proglen, u8 **image_ptr,
+                         unsigned int alignment,
+                         struct bpf_binary_header **rw_header,
+                         u8 **rw_image,
+-                        bpf_jit_fill_hole_t bpf_fill_ill_insns)
++                        bpf_jit_fill_hole_t bpf_fill_ill_insns,
++                        bool was_classic)
+ {
+       struct bpf_binary_header *ro_header;
+       u32 size, hole, start;
+@@ -1120,7 +1123,7 @@ bpf_jit_binary_pack_alloc(unsigned int proglen, u8 **image_ptr,
+       if (bpf_jit_charge_modmem(size))
+               return NULL;
+-      ro_header = bpf_prog_pack_alloc(size, bpf_fill_ill_insns);
++      ro_header = bpf_prog_pack_alloc(size, bpf_fill_ill_insns, was_classic);
+       if (!ro_header) {
+               bpf_jit_uncharge_modmem(size);
+               return NULL;
+diff --git a/kernel/bpf/dispatcher.c b/kernel/bpf/dispatcher.c
+index fa3e9225aedc0a..b3f164e31c6bb4 100644
+--- a/kernel/bpf/dispatcher.c
++++ b/kernel/bpf/dispatcher.c
+@@ -145,7 +145,7 @@ void bpf_dispatcher_change_prog(struct bpf_dispatcher *d, struct bpf_prog *from,
+       mutex_lock(&d->mutex);
+       if (!d->image) {
+-              d->image = bpf_prog_pack_alloc(PAGE_SIZE, bpf_jit_fill_hole_with_zero);
++              d->image = bpf_prog_pack_alloc(PAGE_SIZE, bpf_jit_fill_hole_with_zero, false);
+               if (!d->image)
+                       goto out;
+               d->rw_image = bpf_jit_alloc_exec(PAGE_SIZE);
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-skip-redundant-ibpb-in-pack-allocator.patch b/queue-6.1/bpf-skip-redundant-ibpb-in-pack-allocator.patch
new file mode 100644 (file)
index 0000000..028e429
--- /dev/null
@@ -0,0 +1,81 @@
+From 776f5af2ca01e7e054c700e868be0424ae786ee1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 15:56:26 -0700
+Subject: bpf: Skip redundant IBPB in pack allocator
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit a23c1c5396a91680703360d1ee28a44657c503c4 upstream.
+
+bpf_prog_pack_alloc() issues IBPB on all CPUs on every cBPF allocation,
+even when reusing chunks from an existing pack where no new memory was
+touched since the last IBPB.
+
+Since IBPB on all CPUs is heavy, Dave Hansen suggested to track allocation
+since last IBPB, and only issue IBPB at reuse for the chunks that have not
+seen an IBPB since they were last freed.
+
+Track per-pack whether an IBPB is needed via arch_flush_needed. Set it when
+allocating a chunk, reset on IBPB flush. On reuse, conditionally issue the
+flush. Since IBPB invalidates all BTB entries, clear the flag on all packs
+after flushing.
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/core.c | 15 ++++++++++++++-
+ 1 file changed, 14 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index f78ee18bab3b55..5a0f804ecdf404 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -845,6 +845,7 @@ int bpf_jit_add_poke_descriptor(struct bpf_prog *prog,
+ struct bpf_prog_pack {
+       struct list_head list;
+       void *ptr;
++      bool arch_flush_needed;
+       unsigned long bitmap[];
+ };
+@@ -900,6 +901,8 @@ static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_ins
+       bitmap_zero(pack->bitmap, BPF_PROG_PACK_SIZE / BPF_PROG_CHUNK_SIZE);
+       list_add_tail(&pack->list, &pack_list);
++      if (static_branch_unlikely(&bpf_pred_flush_enabled))
++              pack->arch_flush_needed = true;
+       set_vm_flush_reset_perms(pack->ptr);
+       set_memory_ro((unsigned long)pack->ptr, BPF_PROG_PACK_SIZE / PAGE_SIZE);
+       set_memory_x((unsigned long)pack->ptr, BPF_PROG_PACK_SIZE / PAGE_SIZE);
+@@ -948,8 +951,15 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns, bool
+ found_free_area:
+       /* Flush only for cBPF as it may contain a crafted gadget */
+-      if (static_branch_unlikely(&bpf_pred_flush_enabled) && was_classic)
++      if (static_branch_unlikely(&bpf_pred_flush_enabled) &&
++          pack->arch_flush_needed &&
++          was_classic) {
++              struct bpf_prog_pack *p;
++
+               static_call_cond(bpf_arch_pred_flush)();
++              list_for_each_entry(p, &pack_list, list)
++                      p->arch_flush_needed = false;
++      }
+       bitmap_set(pack->bitmap, pos, nbits);
+       ptr = (void *)(pack->ptr) + (pos << BPF_PROG_CHUNK_SHIFT);
+@@ -987,6 +997,9 @@ void bpf_prog_pack_free(struct bpf_binary_header *hdr)
+                 "bpf_prog_pack bug: missing bpf_arch_text_invalidate?\n");
+       bitmap_clear(pack->bitmap, pos, nbits);
++
++      if (static_branch_unlikely(&bpf_pred_flush_enabled))
++              pack->arch_flush_needed = true;
+       if (bitmap_find_next_zero_area(pack->bitmap, BPF_PROG_CHUNK_COUNT, 0,
+                                      BPF_PROG_CHUNK_COUNT, 0) == 0) {
+               list_del(&pack->list);
+-- 
+2.53.0
+
diff --git a/queue-6.1/bpf-support-for-hardening-against-jit-spraying.patch b/queue-6.1/bpf-support-for-hardening-against-jit-spraying.patch
new file mode 100644 (file)
index 0000000..9199d10
--- /dev/null
@@ -0,0 +1,120 @@
+From 324250cda67e8434bd5aec8c9ad706e2a68605cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 15:55:40 -0700
+Subject: bpf: Support for hardening against JIT spraying
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit 96cce16e26dd02a8678f1e87f88a4b5cdb63b995 upstream.
+
+The BPF JIT allocator packs many small programs into larger executable
+allocations and reuses space within those allocations as programs are
+loaded and freed. When fresh code is written into space that a previous
+program occupied, an indirect jump into the new program can reuse a branch
+prediction left behind by the old one.
+
+Flush the indirect branch predictors before reusing JIT memory so that
+indirect jumps into a newly written program don't reuse predictions from an
+old program that occupied the same space.
+
+Introduce bpf_arch_pred_flush_enabled static key and bpf_arch_pred_flush
+static call for flushing the branch predictors on JIT memory reuse.
+Architectures that need a flush, can update it to a predictor flush
+function. By default, its a NOP and does not emit any CALL.
+
+Allocations larger than a pack are not covered by this flush. That is safe
+because cBPF programs (the unprivileged attack surface) are bounded well
+below a pack size. Issue a warning if this assumption is ever violated
+while the flush is active.
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/filter.h | 10 ++++++++++
+ kernel/bpf/core.c      | 19 +++++++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index 37260c48fad495..fa7bb6f995989e 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -21,6 +21,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/sockptr.h>
+ #include <crypto/sha1.h>
++#include <linux/static_call.h>
+ #include <linux/u64_stats_sync.h>
+ #include <net/sch_generic.h>
+@@ -1058,6 +1059,15 @@ extern long bpf_jit_limit_max;
+ typedef void (*bpf_jit_fill_hole_t)(void *area, unsigned int size);
++/*
++ * Flush the indirect branch predictors before reusing JIT memory, so that
++ * indirect jumps into a newly written program don't reuse predictions left
++ * behind by an old program that occupied the same space.
++ */
++void bpf_arch_pred_flush(void);
++DECLARE_STATIC_CALL(bpf_arch_pred_flush, bpf_arch_pred_flush);
++DECLARE_STATIC_KEY_FALSE(bpf_pred_flush_enabled);
++
+ void bpf_jit_fill_hole_with_zero(void *area, unsigned int size);
+ struct bpf_binary_header *
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index 77044d4a80cc16..4643554c6e3a9c 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -35,6 +35,7 @@
+ #include <linux/bpf_verifier.h>
+ #include <linux/nodemask.h>
+ #include <linux/nospec.h>
++#include <linux/static_call.h>
+ #include <asm/barrier.h>
+ #include <asm/unaligned.h>
+@@ -852,6 +853,15 @@ void bpf_jit_fill_hole_with_zero(void *area, unsigned int size)
+       memset(area, 0, size);
+ }
++DEFINE_STATIC_CALL_NULL(bpf_arch_pred_flush, bpf_arch_pred_flush);
++
++/*
++ * Enabled once bpf_arch_pred_flush points at a real flush routine. Lets the
++ * pack allocator test "is a predictor flush wired up at all" with a cheap
++ * static branch instead of repeatedly querying the static call target.
++ */
++DEFINE_STATIC_KEY_FALSE(bpf_pred_flush_enabled);
++
+ #define BPF_PROG_SIZE_TO_NBITS(size)  (round_up(size, BPF_PROG_CHUNK_SIZE) / BPF_PROG_CHUNK_SIZE)
+ static DEFINE_MUTEX(pack_mutex);
+@@ -905,6 +915,14 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
+       mutex_lock(&pack_mutex);
+       if (size > BPF_PROG_PACK_SIZE) {
++              /*
++               * Allocations larger than a pack get their own pages, and
++               * predictors are not flushed for such allocation. This is only
++               * safe because cBPF programs (the unprivileged attack surface)
++               * are bounded well below a pack size.
++               */
++              if (static_branch_unlikely(&bpf_pred_flush_enabled))
++                      pr_warn_once("BPF: Predictors not flushed for allocations greater than BPF_PROG_PACK_SIZE\n");
+               size = round_up(size, PAGE_SIZE);
+               ptr = module_alloc(size);
+               if (ptr) {
+@@ -929,6 +947,7 @@ void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns)
+       pos = 0;
+ found_free_area:
++      static_call_cond(bpf_arch_pred_flush)();
+       bitmap_set(pack->bitmap, pos, nbits);
+       ptr = (void *)(pack->ptr) + (pos << BPF_PROG_CHUNK_SHIFT);
+-- 
+2.53.0
+
index c486cc47b1a7c33b8ede12275238d7108b9e9c64..afd95acb760d7c986b864c7c9b4ded6a0dd99a3a 100644 (file)
@@ -89,3 +89,11 @@ usb-serial-option-add-tdtech-mt5710-cn.patch
 posix-cpu-timers-prevent-uaf-caused-by-non-leader-ex.patch
 crypto-rsa-pkcs1pad-don-t-warn-on-an-empty-digest.patch
 revert-drm-amd-display-add-missing-kdoc-for-allm-par.patch
+bpf-support-for-hardening-against-jit-spraying.patch
+x86-bugs-enable-ibpb-flush-on-bpf-jit-allocation.patch
+bpf-restrict-jit-predictor-flush-to-cbpf.patch
+bpf-skip-redundant-ibpb-in-pack-allocator.patch
+bpf-prefer-packs-that-won-t-trigger-an-ibpb-flush-on.patch
+bpf-prefer-dirty-packs-for-ebpf-allocations.patch
+bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch
+usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
diff --git a/queue-6.1/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch b/queue-6.1/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
new file mode 100644 (file)
index 0000000..82e8fd6
--- /dev/null
@@ -0,0 +1,98 @@
+From 7c6b5705648998527620b2584e33b95a44ed7dd5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 11:01:16 +0800
+Subject: usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
+
+From: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+
+commit 1fc50f1ecde39feb4fccdaf4bc71aa6c0eb25c49 upstream.
+
+The VIA VL805/806 xHCI controller advertises AC64, but fails to handle
+DMA addresses at or above 0x1000000000. On systems with large amounts of
+RAM, this can cause USB device failures when the controller is given DMA
+addresses beyond its usable address width.
+
+Do not use XHCI_NO_64BIT_SUPPORT for this controller. That quirk clears
+the cached AC64 capability and limits DMA to 32 bits, causing unnecessary
+bouncing for addresses between 4GiB and 64GiB and hiding the controller's
+real AC64 capability from code that may need to distinguish register
+access width from usable DMA address width.
+
+Track the usable DMA address width separately from the AC64 capability.
+Initialize the generic xhci->dma_mask_bits field to 64 and let PCI quirks
+reduce it for controllers with narrower DMA support. Set VIA VL805/806 to
+36 bits so the DMA API only hands it addresses in the range it can handle
+while keeping HCCPARAMS1.AC64 visible.
+
+Cc: stable@kernel.org
+Signed-off-by: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+Link: https://patch.msgid.link/20260630-xhci-via-dma-fix-v3-1-690dcb8cf75a@ultrarisc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-pci.c |  1 +
+ drivers/usb/host/xhci.c     | 15 ++++++++++-----
+ drivers/usb/host/xhci.h     |  1 +
+ 3 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
+index 7ad6d13d65ee94..8fffc84d014779 100644
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -337,6 +337,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+       if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == PCI_DEVICE_ID_VIA_VL805) {
+               xhci->quirks |= XHCI_LPM_SUPPORT;
+               xhci->quirks |= XHCI_TRB_OVERFETCH;
++              xhci->dma_mask_bits = 36;
+       }
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index e00baa3b7324cb..37fb2491d88f22 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -5394,6 +5394,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->hci_version > 0x100)
+               xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
++      xhci->dma_mask_bits = 64;
+       /* xhci-plat or xhci-pci might have set max_interrupters already */
+       if ((!xhci->max_interrupters) ||
+           xhci->max_interrupters > HCS_MAX_INTRS(xhci->hcs_params1))
+@@ -5434,12 +5435,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->quirks & XHCI_NO_64BIT_SUPPORT)
+               xhci->hcc_params &= ~BIT(0);
+-      /* Set dma_mask and coherent_dma_mask to 64-bits,
+-       * if xHC supports 64-bit addressing */
++      /*
++       * Set dma_mask and coherent_dma_mask to 64-bits if xHC supports
++       * 64-bit addressing, unless a controller-specific quirk callback
++       * limits the usable address width.
++       */
+       if (HCC_64BIT_ADDR(xhci->hcc_params) &&
+-                      !dma_set_mask(dev, DMA_BIT_MASK(64))) {
+-              xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+-              dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
++          !dma_set_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits))) {
++              xhci_dbg(xhci, "Enabling %u-bit DMA addresses.\n",
++                       xhci->dma_mask_bits);
++              dma_set_coherent_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits));
+       } else {
+               /*
+                * This is to avoid error in cases where a 32-bit USB
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index b43e88102200e5..b446fa9eb8370b 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1543,6 +1543,7 @@ struct xhci_hcd {
+       int             event_ring_max;
+       /* 4KB min, 128MB max */
+       int             page_size;
++      unsigned int    dma_mask_bits;
+       /* Valid values are 12 to 20, inclusive */
+       int             page_shift;
+       /* msi-x vectors */
+-- 
+2.53.0
+
diff --git a/queue-6.1/x86-bugs-enable-ibpb-flush-on-bpf-jit-allocation.patch b/queue-6.1/x86-bugs-enable-ibpb-flush-on-bpf-jit-allocation.patch
new file mode 100644 (file)
index 0000000..c82101a
--- /dev/null
@@ -0,0 +1,147 @@
+From 3c9eafeacf227f43739921c90ffec27fab8aa585 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 15:55:56 -0700
+Subject: x86/bugs: Enable IBPB flush on BPF JIT allocation
+
+From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+
+commit a3af84b0fa00ead01fcd0e28b5d773ff25990a0d upstream.
+
+Enable hardening against JIT spraying when Spectre-v2 mitigations are in
+use. Specifically, issue an IBPB flush on BPF JIT memory reuse. Skip
+enabling the IBPB flush if the BPF dispatcher is already using a retpoline
+sequence.
+
+This hardening applies only when BPF-JIT is in use. Guard the enabling
+under CONFIG_BPF_JIT so that bugs.c still builds with CONFIG_BPF_JIT=n.
+
+  [ pawan: Use entry_ibpb() instead of write_ibpb(). JIT hardening enable
+          moved to spectre_v2_select_mitigation() because there is no
+          spectre_v2_apply_mitigation()]
+
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/nospec-branch.h |  4 +++
+ arch/x86/kernel/cpu/bugs.c           | 50 +++++++++++++++++++++++++---
+ 2 files changed, 49 insertions(+), 5 deletions(-)
+
+diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
+index 818a5913f21950..40842aabd21783 100644
+--- a/arch/x86/include/asm/nospec-branch.h
++++ b/arch/x86/include/asm/nospec-branch.h
+@@ -280,6 +280,10 @@ extern void srso_alias_untrain_ret(void);
+ extern void entry_untrain_ret(void);
+ extern void entry_ibpb(void);
++#ifdef CONFIG_BPF_JIT
++extern void bpf_arch_ibpb(void);
++#endif
++
+ #ifdef CONFIG_X86_64
+ extern void clear_bhb_loop(void);
+ #endif
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index a0b362ac50a1b3..662d13612ef4b2 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -16,6 +16,7 @@
+ #include <linux/sched/smt.h>
+ #include <linux/pgtable.h>
+ #include <linux/bpf.h>
++#include <linux/filter.h>
+ #include <asm/spec-ctrl.h>
+ #include <asm/cmdline.h>
+@@ -1298,8 +1299,21 @@ static inline const char *spectre_v2_module_string(void)
+ {
+       return spectre_v2_bad_module ? " - vulnerable module loaded" : "";
+ }
++
++/*
++ * The "retpoline sequence" is the "call;mov;ret" sequence that
++ * replaces normal indirect branch instructions. Differentiate
++ * *the* retpoline sequence from the LFENCE-prefixed indirect
++ * branches that simply use the retpoline infrastructure.
++ */
++static inline bool retpoline_seq_enabled(void)
++{
++      return boot_cpu_has(X86_FEATURE_RETPOLINE) && !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE);
++}
++
+ #else
+ static inline const char *spectre_v2_module_string(void) { return ""; }
++static inline bool retpoline_seq_enabled(void) { return false; }
+ #endif
+ #define SPECTRE_V2_LFENCE_MSG "WARNING: LFENCE mitigation is not recommended for this CPU, data leaks possible!\n"
+@@ -1780,8 +1794,7 @@ static void __init bhi_select_mitigation(void)
+               return;
+       /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
+-      if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
+-          !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) {
++      if (retpoline_seq_enabled()) {
+               spec_ctrl_disable_kernel_rrsba();
+               if (rrsba_disabled)
+                       return;
+@@ -1803,6 +1816,27 @@ static void __init bhi_select_mitigation(void)
+       pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n");
+ }
++#ifdef CONFIG_BPF_JIT
++static void __bpf_arch_ibpb(void *unused)
++{
++      entry_ibpb();
++}
++
++void bpf_arch_ibpb(void)
++{
++      on_each_cpu(__bpf_arch_ibpb, NULL, 1);
++}
++
++static bool __init cpu_wants_ibpb_bpf(void)
++{
++      /* A genuine retpoline already neutralizes ring0 indirect predictions */
++      if (retpoline_seq_enabled())
++              return false;
++
++      return boot_cpu_has(X86_FEATURE_IBPB);
++}
++#endif
++
+ static void __init spectre_v2_select_mitigation(void)
+ {
+       enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
+@@ -1985,6 +2019,14 @@ static void __init spectre_v2_select_mitigation(void)
+               pr_info("Enabling Restricted Speculation for firmware calls\n");
+       }
++#ifdef CONFIG_BPF_JIT
++      if (cpu_wants_ibpb_bpf()) {
++              static_call_update(bpf_arch_pred_flush, bpf_arch_ibpb);
++              static_branch_enable(&bpf_pred_flush_enabled);
++              pr_info("Enabling IBPB for BPF\n");
++      }
++#endif
++
+       /* Set up IBPB and STIBP depending on the general spectre V2 command */
+       spectre_v2_cmd = cmd;
+ }
+@@ -3157,9 +3199,7 @@ static const char *spectre_bhi_state(void)
+               return "; BHI: BHI_DIS_S";
+       else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
+               return "; BHI: SW loop, KVM: SW loop";
+-      else if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
+-               !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE) &&
+-               rrsba_disabled)
++      else if (retpoline_seq_enabled() && rrsba_disabled)
+               return "; BHI: Retpoline";
+       else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
+               return "; BHI: Vulnerable, KVM: SW loop";
+-- 
+2.53.0
+
diff --git a/queue-6.12/risc-v-kvm-serialize-virtual-interrupt-pending-state.patch b/queue-6.12/risc-v-kvm-serialize-virtual-interrupt-pending-state.patch
new file mode 100644 (file)
index 0000000..e1ba09a
--- /dev/null
@@ -0,0 +1,396 @@
+From 1c14dcdc3dac9189363a11f91d5e1891807b921d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 09:35:51 +0800
+Subject: RISC-V: KVM: Serialize virtual interrupt pending state updates
+
+From: Xie Bo <xb@ultrarisc.com>
+
+commit d024a0a7879e6f37c0152aacf6d8e37b214a1738 upstream.
+
+KVM RISC-V tracks guest local interrupt state with two bitmaps:
+
+  - irqs_pending: interrupts that should be visible to the guest
+  - irqs_pending_mask: interrupts whose pending state changed
+
+The current code updates those bitmaps with independent atomic bitops
+and assumes a multiple-producer, single-consumer protocol. That model
+does not actually hold.
+
+kvm_riscv_vcpu_sync_interrupts() is not a pure consumer. When the guest
+changes guest-visible HVIP state, sync_interrupts() writes both
+irqs_pending and irqs_pending_mask to reflect the new guest state back
+into KVM state. As a result, irqs_pending and irqs_pending_mask form a
+single logical state transition, but they are not updated atomically as
+a pair.
+
+This allows a race where a newly injected interrupt is lost. For
+example:
+
+  CPU0                              CPU1
+  ----                              ----
+  kvm_riscv_vcpu_set_interrupt(VS_SOFT)
+    set_bit(VS_SOFT, irqs_pending)
+                                    kvm_riscv_vcpu_sync_interrupts()
+                                      sees guest-cleared HVIP.VSSIP
+                                      sets irqs_pending_mask
+                                      clear_bit(IRQ_VS_SOFT, irqs_pending)
+    set_bit(VS_SOFT, irqs_pending_mask)
+    kvm_vcpu_kick()
+
+After that interleaving, a later flush can update HVIP without VSSIP
+even though a new virtual interrupt was injected. In practice, the
+guest can remain blocked in WFI with work pending.
+
+The same pending/mask protocol is shared by VS soft interrupts, PMU
+overflow delivery, and AIA high interrupt synchronization, so the race
+is not limited to one interrupt source.
+
+Fix this by serializing all updates to irqs_pending and irqs_pending_mask
+with a per-vCPU raw spinlock. This keeps the pending bit and the dirty
+mask as one state transition across:
+
+  - set/unset interrupt
+  - guest HVIP sync
+  - interrupt flush to guest CSR state
+  - vCPU reset
+  - AIA CSR writes that clear dirty state
+
+Use non-atomic bitmap operations while holding the lock. Hold the lock
+across the AIA sync, flush, and pending checks as well, so both bitmap
+words share the same serialization domain.
+
+This intentionally replaces the existing lockless protocol instead of
+trying to repair it with additional barriers. The problem is not memory
+ordering on a single field; it is that two separate bitmaps encode one
+shared state machine while both producers and sync paths can modify
+them. A per-vCPU raw spinlock keeps the fix small, local, and suitable
+for backporting.
+
+Fixes: cce69aff689e ("RISC-V: KVM: Implement VCPU interrupts and requests handling")
+Cc: stable@vger.kernel.org
+Signed-off-by: Xie Bo <xb@ultrarisc.com>
+Reviewed-by: Anup Patel <anup@brainfault.org>
+Link: https://lore.kernel.org/r/20260715020359.1521354-2-xb@ultrarisc.com
+Signed-off-by: Anup Patel <anup@brainfault.org>
+
+[ bo: Adapt the reset and CSR helpers to their older signatures. ]
+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/include/asm/kvm_host.h | 10 ++---
+ arch/riscv/kvm/aia.c              | 34 +++++++++++----
+ arch/riscv/kvm/vcpu.c             | 69 ++++++++++++++++++++++---------
+ arch/riscv/kvm/vcpu_onereg.c      |  8 +++-
+ 4 files changed, 87 insertions(+), 34 deletions(-)
+
+diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
+index 2e2254fd2a2aae..7beef600abad7c 100644
+--- a/arch/riscv/include/asm/kvm_host.h
++++ b/arch/riscv/include/asm/kvm_host.h
+@@ -232,13 +232,13 @@ struct kvm_vcpu_arch {
+       /*
+        * VCPU interrupts
+        *
+-       * We have a lockless approach for tracking pending VCPU interrupts
+-       * implemented using atomic bitops. The irqs_pending bitmap represent
+-       * pending interrupts whereas irqs_pending_mask represent bits changed
+-       * in irqs_pending. Our approach is modeled around multiple producer
+-       * and single consumer problem where the consumer is the VCPU itself.
++       * The irqs_pending bitmap represents pending interrupts whereas
++       * irqs_pending_mask represents bits changed in irqs_pending. Updates
++       * to these bitmaps are serialized so vcpu interrupt sync/flush cannot
++       * drop a newly injected interrupt while syncing guest-visible HVIP.
+        */
+ #define KVM_RISCV_VCPU_NR_IRQS        64
++      raw_spinlock_t irqs_pending_lock;
+       DECLARE_BITMAP(irqs_pending, KVM_RISCV_VCPU_NR_IRQS);
+       DECLARE_BITMAP(irqs_pending_mask, KVM_RISCV_VCPU_NR_IRQS);
+diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c
+index 9f3b527596ded8..01319d8d75b0a4 100644
+--- a/arch/riscv/kvm/aia.c
++++ b/arch/riscv/kvm/aia.c
+@@ -71,12 +71,15 @@ void kvm_riscv_vcpu_aia_flush_interrupts(struct kvm_vcpu *vcpu)
+       struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
+       unsigned long mask, val;
++      lockdep_assert_held(&vcpu->arch.irqs_pending_lock);
++
+       if (!kvm_riscv_aia_available())
+               return;
+-      if (READ_ONCE(vcpu->arch.irqs_pending_mask[1])) {
+-              mask = xchg_acquire(&vcpu->arch.irqs_pending_mask[1], 0);
+-              val = READ_ONCE(vcpu->arch.irqs_pending[1]) & mask;
++      mask = vcpu->arch.irqs_pending_mask[1];
++      if (mask) {
++              vcpu->arch.irqs_pending_mask[1] = 0;
++              val = vcpu->arch.irqs_pending[1] & mask;
+               csr->hviph &= ~mask;
+               csr->hviph |= val;
+@@ -87,6 +90,8 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
+ {
+       struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
++      lockdep_assert_held(&vcpu->arch.irqs_pending_lock);
++
+       if (kvm_riscv_aia_available())
+               csr->vsieh = csr_read(CSR_VSIEH);
+ }
+@@ -96,13 +101,21 @@ bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
+ {
+       int hgei;
+       unsigned long seip;
++#ifdef CONFIG_32BIT
++      unsigned long flags;
++      bool pending;
++#endif
+       if (!kvm_riscv_aia_available())
+               return false;
+ #ifdef CONFIG_32BIT
+-      if (READ_ONCE(vcpu->arch.irqs_pending[1]) &
+-          (vcpu->arch.aia_context.guest_csr.vsieh & upper_32_bits(mask)))
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++      pending = vcpu->arch.irqs_pending[1] &
++                (vcpu->arch.aia_context.guest_csr.vsieh &
++                 upper_32_bits(mask));
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
++      if (pending)
+               return true;
+ #endif
+@@ -190,6 +203,9 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
+                              unsigned long val)
+ {
+       struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
++#ifdef CONFIG_32BIT
++      unsigned long flags;
++#endif
+       if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long))
+               return -ENOENT;
+@@ -198,8 +214,12 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
+               ((unsigned long *)csr)[reg_num] = val;
+ #ifdef CONFIG_32BIT
+-              if (reg_num == KVM_REG_RISCV_CSR_AIA_REG(siph))
+-                      WRITE_ONCE(vcpu->arch.irqs_pending_mask[1], 0);
++              if (reg_num == KVM_REG_RISCV_CSR_AIA_REG(siph)) {
++                      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++                      vcpu->arch.irqs_pending_mask[1] = 0;
++                      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock,
++                                                 flags);
++              }
+ #endif
+       }
+diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
+index da01c81bf41676..ad519c9c31d05a 100644
+--- a/arch/riscv/kvm/vcpu.c
++++ b/arch/riscv/kvm/vcpu.c
+@@ -52,6 +52,7 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
+       struct kvm_vcpu_csr *reset_csr = &vcpu->arch.guest_reset_csr;
+       struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
+       struct kvm_cpu_context *reset_cntx = &vcpu->arch.guest_reset_context;
++      unsigned long flags;
+       bool loaded;
+       /**
+@@ -80,8 +81,10 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
+       kvm_riscv_vcpu_aia_reset(vcpu);
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+       bitmap_zero(vcpu->arch.irqs_pending, KVM_RISCV_VCPU_NR_IRQS);
+       bitmap_zero(vcpu->arch.irqs_pending_mask, KVM_RISCV_VCPU_NR_IRQS);
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+       kvm_riscv_vcpu_pmu_reset(vcpu);
+@@ -126,6 +129,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
+       /* Setup VCPU hfence queue */
+       spin_lock_init(&vcpu->arch.hfence_lock);
++      raw_spin_lock_init(&vcpu->arch.irqs_pending_lock);
++
+       /* Setup reset state of shadow SSTATUS and HSTATUS CSRs */
+       spin_lock_init(&vcpu->arch.reset_cntx_lock);
+@@ -341,10 +346,14 @@ void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu)
+ {
+       struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+       unsigned long mask, val;
++      unsigned long flags;
++
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+-      if (READ_ONCE(vcpu->arch.irqs_pending_mask[0])) {
+-              mask = xchg_acquire(&vcpu->arch.irqs_pending_mask[0], 0);
+-              val = READ_ONCE(vcpu->arch.irqs_pending[0]) & mask;
++      mask = vcpu->arch.irqs_pending_mask[0];
++      if (mask) {
++              vcpu->arch.irqs_pending_mask[0] = 0;
++              val = vcpu->arch.irqs_pending[0] & mask;
+               csr->hvip &= ~mask;
+               csr->hvip |= val;
+@@ -352,11 +361,14 @@ void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu)
+       /* Flush AIA high interrupts */
+       kvm_riscv_vcpu_aia_flush_interrupts(vcpu);
++
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+ }
+ void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
+ {
+       unsigned long hvip;
++      unsigned long flags;
+       struct kvm_vcpu_arch *v = &vcpu->arch;
+       struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+@@ -365,34 +377,41 @@ void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
+       /* Sync-up HVIP.VSSIP bit changes does by Guest */
+       hvip = csr_read(CSR_HVIP);
++
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++
+       if ((csr->hvip ^ hvip) & (1UL << IRQ_VS_SOFT)) {
+               if (hvip & (1UL << IRQ_VS_SOFT)) {
+-                      if (!test_and_set_bit(IRQ_VS_SOFT,
+-                                            v->irqs_pending_mask))
+-                              set_bit(IRQ_VS_SOFT, v->irqs_pending);
++                      if (!__test_and_set_bit(IRQ_VS_SOFT,
++                                              v->irqs_pending_mask))
++                              __set_bit(IRQ_VS_SOFT, v->irqs_pending);
+               } else {
+-                      if (!test_and_set_bit(IRQ_VS_SOFT,
+-                                            v->irqs_pending_mask))
+-                              clear_bit(IRQ_VS_SOFT, v->irqs_pending);
++                      if (!__test_and_set_bit(IRQ_VS_SOFT,
++                                              v->irqs_pending_mask))
++                              __clear_bit(IRQ_VS_SOFT, v->irqs_pending);
+               }
+       }
+       /* Sync up the HVIP.LCOFIP bit changes (only clear) by the guest */
+       if ((csr->hvip ^ hvip) & (1UL << IRQ_PMU_OVF)) {
+               if (!(hvip & (1UL << IRQ_PMU_OVF)) &&
+-                  !test_and_set_bit(IRQ_PMU_OVF, v->irqs_pending_mask))
+-                      clear_bit(IRQ_PMU_OVF, v->irqs_pending);
++                  !__test_and_set_bit(IRQ_PMU_OVF, v->irqs_pending_mask))
++                      __clear_bit(IRQ_PMU_OVF, v->irqs_pending);
+       }
+       /* Sync-up AIA high interrupts */
+       kvm_riscv_vcpu_aia_sync_interrupts(vcpu);
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
++
+       /* Sync-up timer CSRs */
+       kvm_riscv_vcpu_timer_sync(vcpu);
+ }
+ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
+ {
++      unsigned long flags;
++
+       /*
+        * We only allow VS-mode software, timer, and external
+        * interrupts when irq is one of the local interrupts
+@@ -405,9 +424,10 @@ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
+           irq != IRQ_PMU_OVF)
+               return -EINVAL;
+-      set_bit(irq, vcpu->arch.irqs_pending);
+-      smp_mb__before_atomic();
+-      set_bit(irq, vcpu->arch.irqs_pending_mask);
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++      __set_bit(irq, vcpu->arch.irqs_pending);
++      __set_bit(irq, vcpu->arch.irqs_pending_mask);
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+       kvm_vcpu_kick(vcpu);
+@@ -416,6 +436,8 @@ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
+ int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
+ {
++      unsigned long flags;
++
+       /*
+        * We only allow VS-mode software, timer, counter overflow and external
+        * interrupts when irq is one of the local interrupts
+@@ -428,26 +450,33 @@ int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
+           irq != IRQ_PMU_OVF)
+               return -EINVAL;
+-      clear_bit(irq, vcpu->arch.irqs_pending);
+-      smp_mb__before_atomic();
+-      set_bit(irq, vcpu->arch.irqs_pending_mask);
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++      __clear_bit(irq, vcpu->arch.irqs_pending);
++      __set_bit(irq, vcpu->arch.irqs_pending_mask);
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+       return 0;
+ }
+ bool kvm_riscv_vcpu_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
+ {
++      unsigned long flags;
+       unsigned long ie;
++      bool ret;
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+       ie = ((vcpu->arch.guest_csr.vsie & VSIP_VALID_MASK)
+               << VSIP_TO_HVIP_SHIFT) & (unsigned long)mask;
+       ie |= vcpu->arch.guest_csr.vsie & ~IRQ_LOCAL_MASK &
+               (unsigned long)mask;
+-      if (READ_ONCE(vcpu->arch.irqs_pending[0]) & ie)
+-              return true;
++      ret = vcpu->arch.irqs_pending[0] & ie;
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+       /* Check AIA high interrupts */
+-      return kvm_riscv_vcpu_aia_has_interrupts(vcpu, mask);
++      if (!ret)
++              ret = kvm_riscv_vcpu_aia_has_interrupts(vcpu, mask);
++
++      return ret;
+ }
+ void __kvm_riscv_vcpu_power_off(struct kvm_vcpu *vcpu)
+diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
+index b319c4c13c54ce..6223806fcbc2ba 100644
+--- a/arch/riscv/kvm/vcpu_onereg.c
++++ b/arch/riscv/kvm/vcpu_onereg.c
+@@ -445,6 +445,7 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
+                                         unsigned long reg_val)
+ {
+       struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
++      unsigned long flags;
+       if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
+               return -ENOENT;
+@@ -456,8 +457,11 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
+       ((unsigned long *)csr)[reg_num] = reg_val;
+-      if (reg_num == KVM_REG_RISCV_CSR_REG(sip))
+-              WRITE_ONCE(vcpu->arch.irqs_pending_mask[0], 0);
++      if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
++              raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++              vcpu->arch.irqs_pending_mask[0] = 0;
++              raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
++      }
+       return 0;
+ }
+-- 
+2.53.0
+
index 353924a5cf2c5f5fbcecf6cb1e0279e1b4429253..db6b2dc0e53d3617c02af71e0454d1a34ea5c841 100644 (file)
@@ -131,3 +131,5 @@ usb-serial-keyspan_pda-fix-data-loss-on-receive-throttling.patch
 usb-serial-option-add-tdtech-mt5710-cn.patch
 crypto-rsa-pkcs1pad-don-t-warn-on-an-empty-digest.patch
 revert-drm-amd-display-add-missing-kdoc-for-allm-par.patch
+risc-v-kvm-serialize-virtual-interrupt-pending-state.patch
+usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
diff --git a/queue-6.12/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch b/queue-6.12/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
new file mode 100644 (file)
index 0000000..21e26d1
--- /dev/null
@@ -0,0 +1,98 @@
+From 586bac10775ce3582f0022f995ab2c717680f3e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:42:10 +0800
+Subject: usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
+
+From: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+
+commit 1fc50f1ecde39feb4fccdaf4bc71aa6c0eb25c49 upstream.
+
+The VIA VL805/806 xHCI controller advertises AC64, but fails to handle
+DMA addresses at or above 0x1000000000. On systems with large amounts of
+RAM, this can cause USB device failures when the controller is given DMA
+addresses beyond its usable address width.
+
+Do not use XHCI_NO_64BIT_SUPPORT for this controller. That quirk clears
+the cached AC64 capability and limits DMA to 32 bits, causing unnecessary
+bouncing for addresses between 4GiB and 64GiB and hiding the controller's
+real AC64 capability from code that may need to distinguish register
+access width from usable DMA address width.
+
+Track the usable DMA address width separately from the AC64 capability.
+Initialize the generic xhci->dma_mask_bits field to 64 and let PCI quirks
+reduce it for controllers with narrower DMA support. Set VIA VL805/806 to
+36 bits so the DMA API only hands it addresses in the range it can handle
+while keeping HCCPARAMS1.AC64 visible.
+
+Cc: stable@kernel.org
+Signed-off-by: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+Link: https://patch.msgid.link/20260630-xhci-via-dma-fix-v3-1-690dcb8cf75a@ultrarisc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-pci.c |  1 +
+ drivers/usb/host/xhci.c     | 15 ++++++++++-----
+ drivers/usb/host/xhci.h     |  1 +
+ 3 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
+index 5f60528453e917..bd33cf6769cf6d 100644
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -454,6 +454,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+       if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == PCI_DEVICE_ID_VIA_VL805) {
+               xhci->quirks |= XHCI_LPM_SUPPORT;
+               xhci->quirks |= XHCI_TRB_OVERFETCH;
++              xhci->dma_mask_bits = 36;
+       }
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index aae3f1d1f11950..a50e813dda13a0 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -5259,6 +5259,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->hci_version > 0x100)
+               xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
++      xhci->dma_mask_bits = 64;
+       /* xhci-plat or xhci-pci might have set max_interrupters already */
+       if ((!xhci->max_interrupters) ||
+           xhci->max_interrupters > HCS_MAX_INTRS(xhci->hcs_params1))
+@@ -5300,12 +5301,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->quirks & XHCI_NO_64BIT_SUPPORT)
+               xhci->hcc_params &= ~BIT(0);
+-      /* Set dma_mask and coherent_dma_mask to 64-bits,
+-       * if xHC supports 64-bit addressing */
++      /*
++       * Set dma_mask and coherent_dma_mask to 64-bits if xHC supports
++       * 64-bit addressing, unless a controller-specific quirk callback
++       * limits the usable address width.
++       */
+       if (HCC_64BIT_ADDR(xhci->hcc_params) &&
+-                      !dma_set_mask(dev, DMA_BIT_MASK(64))) {
+-              xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+-              dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
++          !dma_set_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits))) {
++              xhci_dbg(xhci, "Enabling %u-bit DMA addresses.\n",
++                       xhci->dma_mask_bits);
++              dma_set_coherent_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits));
+       } else {
+               /*
+                * This is to avoid error in cases where a 32-bit USB
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index b4fa8e7e437639..1a3f2dfd5a711d 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1510,6 +1510,7 @@ struct xhci_hcd {
+       /* imod_interval in ns (I * 250ns) */
+       u32             imod_interval;
+       u32             page_size;
++      unsigned int    dma_mask_bits;
+       /* MSI-X/MSI vectors */
+       int             nvecs;
+       /* optional clocks */
+-- 
+2.53.0
+
diff --git a/queue-6.18/selftests-bpf-adjust-verifier_map_ptr-for-the-map-s-.patch b/queue-6.18/selftests-bpf-adjust-verifier_map_ptr-for-the-map-s-.patch
new file mode 100644 (file)
index 0000000..975af01
--- /dev/null
@@ -0,0 +1,62 @@
+From aaec921dfddf4dbd9b4ec078512330f90e44219e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 15:25:08 +0800
+Subject: selftests/bpf: Adjust verifier_map_ptr for the map's excl field
+
+From: KP Singh <kpsingh@kernel.org>
+
+commit 38498c0ebacd54dbaac3513a548a13f1a8455c4e upstream.
+
+Adding the u32 excl field at offset 32 of struct bpf_map right after the
+sha[SHA256_DIGEST_SIZE] hash shifts the ops pointer from offset 32 to 40.
+Therefore, fix up the test case.
+
+  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_map_ptr
+  [...]
+  #637/1   verifier_map_ptr/bpf_map_ptr: read with negative offset rejected:OK
+  #637/2   verifier_map_ptr/bpf_map_ptr: read with negative offset rejected @unpriv:OK
+  #637/3   verifier_map_ptr/bpf_map_ptr: write rejected:OK
+  #637/4   verifier_map_ptr/bpf_map_ptr: write rejected @unpriv:OK
+  #637/5   verifier_map_ptr/bpf_map_ptr: read non-existent field rejected:OK
+  #637/6   verifier_map_ptr/bpf_map_ptr: read non-existent field rejected @unpriv:OK
+  #637/7   verifier_map_ptr/bpf_map_ptr: read ops field accepted:OK
+  #637/8   verifier_map_ptr/bpf_map_ptr: read ops field accepted @unpriv:OK
+  [...]
+  Summary: 2/18 PASSED, 0 SKIPPED, 0 FAILED
+
+Signed-off-by: KP Singh <kpsingh@kernel.org>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260601150248.394863-7-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/progs/verifier_map_ptr.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/progs/verifier_map_ptr.c b/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
+index e2767d27d8aaf8..d8e822d1a8bab6 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
++++ b/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
+@@ -70,13 +70,15 @@ __naked void bpf_map_ptr_write_rejected(void)
+       : __clobber_all);
+ }
+-/* The first element of struct bpf_map is a SHA256 hash of 32 bytes, accessing
+- * into this array is valid. The opts field is now at offset 33.
++/*
++ * struct bpf_map starts with the SHA256 hash sha[32] at offset 0 (a readable
++ * byte array), followed by the u32 excl field at offset 32. Reading a u32 at
++ * offset 33 runs past the end of excl and is rejected.
+  */
+ SEC("socket")
+ __description("bpf_map_ptr: read non-existent field rejected")
+ __failure
+-__msg("cannot access ptr member ops with moff 32 in struct bpf_map with off 33 size 4")
++__msg("access beyond the end of member excl (mend:36) in struct bpf_map with off 33 size 4")
+ __failure_unpriv
+ __msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")
+ __flag(BPF_F_ANY_ALIGNMENT)
+-- 
+2.53.0
+
diff --git a/queue-6.18/selftests-bpf-keep-verifier_map_ptr-exercising-ops-p.patch b/queue-6.18/selftests-bpf-keep-verifier_map_ptr-exercising-ops-p.patch
new file mode 100644 (file)
index 0000000..5896804
--- /dev/null
@@ -0,0 +1,107 @@
+From 49dc6cace7c840b60fe16b4b29d76b82d01ea7dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 15:25:09 +0800
+Subject: selftests/bpf: Keep verifier_map_ptr exercising ops pointer access
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit 082c412097716b93ff1365689fc4ddcd1ce8296f upstream.
+
+sashiko complained that 38498c0ebacd ("selftests/bpf: Adjust verifier_map_ptr
+for the map's excl field") would slightly decrease the test coverage given
+before the test was against the verifier rejecting the ops pointer. Recover
+the old test with the right offsets and add the existing one as an additional
+test case.
+
+  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_map_ptr
+  [    1.672932] bpf_testmod: module verification failed: signature and/or required key missing - tainting kernel
+  #637/1   verifier_map_ptr/bpf_map_ptr: read with negative offset rejected:OK
+  #637/2   verifier_map_ptr/bpf_map_ptr: read with negative offset rejected @unpriv:OK
+  #637/3   verifier_map_ptr/bpf_map_ptr: write rejected:OK
+  #637/4   verifier_map_ptr/bpf_map_ptr: write rejected @unpriv:OK
+  #637/5   verifier_map_ptr/bpf_map_ptr: read non-existent field rejected:OK
+  #637/6   verifier_map_ptr/bpf_map_ptr: read non-existent field rejected @unpriv:OK
+  #637/7   verifier_map_ptr/bpf_map_ptr: read beyond excl field rejected:OK
+  #637/8   verifier_map_ptr/bpf_map_ptr: read beyond excl field rejected @unpriv:OK
+  #637/9   verifier_map_ptr/bpf_map_ptr: read ops field accepted:OK
+  #637/10  verifier_map_ptr/bpf_map_ptr: read ops field accepted @unpriv:OK
+  #637/11  verifier_map_ptr/bpf_map_ptr: r = 0, map_ptr = map_ptr + r:OK
+  #637/12  verifier_map_ptr/bpf_map_ptr: r = 0, map_ptr = map_ptr + r @unpriv:OK
+  #637/13  verifier_map_ptr/bpf_map_ptr: r = 0, r = r + map_ptr:OK
+  #637/14  verifier_map_ptr/bpf_map_ptr: r = 0, r = r + map_ptr @unpriv:OK
+  #637     verifier_map_ptr:OK
+  [...]
+  Summary: 2/20 PASSED, 0 SKIPPED, 0 FAILED
+
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260602133052.423725-4-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/progs/verifier_map_ptr.c    | 34 ++++++++++++++++---
+ 1 file changed, 30 insertions(+), 4 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/progs/verifier_map_ptr.c b/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
+index d8e822d1a8bab6..1661936598703c 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
++++ b/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
+@@ -72,17 +72,43 @@ __naked void bpf_map_ptr_write_rejected(void)
+ /*
+  * struct bpf_map starts with the SHA256 hash sha[32] at offset 0 (a readable
+- * byte array), followed by the u32 excl field at offset 32. Reading a u32 at
+- * offset 33 runs past the end of excl and is rejected.
++ * byte array), the u32 excl field at offset 32, and the ops pointer at offset
++ * 40. Reading a u32 at offset 41 reaches into the middle of the ops pointer,
++ * i.e. a partial pointer access, which is rejected.
+  */
+ SEC("socket")
+ __description("bpf_map_ptr: read non-existent field rejected")
+ __failure
+-__msg("access beyond the end of member excl (mend:36) in struct bpf_map with off 33 size 4")
++__msg("cannot access ptr member ops with moff 40 in struct bpf_map with off 41 size 4")
+ __failure_unpriv
+ __msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")
+ __flag(BPF_F_ANY_ALIGNMENT)
+ __naked void read_non_existent_field_rejected(void)
++{
++      asm volatile ("                                 \
++      r6 = 0;                                         \
++      r1 = %[map_array_48b] ll;                       \
++      r6 = *(u32*)(r1 + 41);                          \
++      r0 = 1;                                         \
++      exit;                                           \
++"     :
++      : __imm_addr(map_array_48b)
++      : __clobber_all);
++}
++
++/*
++ * The u32 excl field spans offsets 32..35 (mend 36). Reading a u32 at offset
++ * 33 starts inside excl but extends past its end, which the verifier rejects
++ * as an out-of-bounds scalar access.
++ */
++SEC("socket")
++__description("bpf_map_ptr: read beyond excl field rejected")
++__failure
++__msg("access beyond the end of member excl (mend:36) in struct bpf_map with off 33 size 4")
++__failure_unpriv
++__msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")
++__flag(BPF_F_ANY_ALIGNMENT)
++__naked void read_beyond_excl_field_rejected(void)
+ {
+       asm volatile ("                                 \
+       r6 = 0;                                         \
+@@ -105,7 +131,7 @@ __naked void ptr_read_ops_field_accepted(void)
+       asm volatile ("                                 \
+       r6 = 0;                                         \
+       r1 = %[map_array_48b] ll;                       \
+-      r6 = *(u64*)(r1 + 0);                           \
++      r6 = *(u64*)(r1 + 40);                          \
+       r0 = 1;                                         \
+       exit;                                           \
+ "     :
+-- 
+2.53.0
+
index 6577cefe1acea1c0504a192e6f82bbad2f4b22e4..4b83dd9083a261a4e2691dcda288cd16bed41739 100644 (file)
@@ -166,3 +166,6 @@ usb-typec-ucsi-add-duplicate-detection-to-nvidia-registration-path.patch
 wifi-mwifiex-fix-freeze-for-60-seconds-caused-by-req.patch
 risc-v-kvm-serialize-virtual-interrupt-pending-state.patch
 revert-drm-amd-display-add-missing-kdoc-for-allm-par.patch
+usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
+selftests-bpf-adjust-verifier_map_ptr-for-the-map-s-.patch
+selftests-bpf-keep-verifier_map_ptr-exercising-ops-p.patch
diff --git a/queue-6.18/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch b/queue-6.18/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
new file mode 100644 (file)
index 0000000..e367d70
--- /dev/null
@@ -0,0 +1,98 @@
+From ef549d84c970722249b8f90d768fdf5f8376ef2a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:43:41 +0800
+Subject: usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
+
+From: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+
+commit 1fc50f1ecde39feb4fccdaf4bc71aa6c0eb25c49 upstream.
+
+The VIA VL805/806 xHCI controller advertises AC64, but fails to handle
+DMA addresses at or above 0x1000000000. On systems with large amounts of
+RAM, this can cause USB device failures when the controller is given DMA
+addresses beyond its usable address width.
+
+Do not use XHCI_NO_64BIT_SUPPORT for this controller. That quirk clears
+the cached AC64 capability and limits DMA to 32 bits, causing unnecessary
+bouncing for addresses between 4GiB and 64GiB and hiding the controller's
+real AC64 capability from code that may need to distinguish register
+access width from usable DMA address width.
+
+Track the usable DMA address width separately from the AC64 capability.
+Initialize the generic xhci->dma_mask_bits field to 64 and let PCI quirks
+reduce it for controllers with narrower DMA support. Set VIA VL805/806 to
+36 bits so the DMA API only hands it addresses in the range it can handle
+while keeping HCCPARAMS1.AC64 visible.
+
+Cc: stable@kernel.org
+Signed-off-by: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+Link: https://patch.msgid.link/20260630-xhci-via-dma-fix-v3-1-690dcb8cf75a@ultrarisc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-pci.c |  1 +
+ drivers/usb/host/xhci.c     | 15 ++++++++++-----
+ drivers/usb/host/xhci.h     |  1 +
+ 3 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
+index f67a4d9562046f..734f7e74158354 100644
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -448,6 +448,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+       if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == PCI_DEVICE_ID_VIA_VL805) {
+               xhci->quirks |= XHCI_LPM_SUPPORT;
+               xhci->quirks |= XHCI_TRB_OVERFETCH;
++              xhci->dma_mask_bits = 36;
+       }
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index a06758addbf823..23b104c2956c7c 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -5459,6 +5459,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->hci_version > 0x100)
+               xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
++      xhci->dma_mask_bits = 64;
+       /* xhci-plat or xhci-pci might have set max_interrupters already */
+       if ((!xhci->max_interrupters) ||
+           xhci->max_interrupters > HCS_MAX_INTRS(xhci->hcs_params1))
+@@ -5505,12 +5506,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->quirks & XHCI_NO_64BIT_SUPPORT)
+               xhci->hcc_params &= ~BIT(0);
+-      /* Set dma_mask and coherent_dma_mask to 64-bits,
+-       * if xHC supports 64-bit addressing */
++      /*
++       * Set dma_mask and coherent_dma_mask to 64-bits if xHC supports
++       * 64-bit addressing, unless a controller-specific quirk callback
++       * limits the usable address width.
++       */
+       if (HCC_64BIT_ADDR(xhci->hcc_params) &&
+-                      !dma_set_mask(dev, DMA_BIT_MASK(64))) {
+-              xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+-              dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
++          !dma_set_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits))) {
++              xhci_dbg(xhci, "Enabling %u-bit DMA addresses.\n",
++                       xhci->dma_mask_bits);
++              dma_set_coherent_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits));
+       } else {
+               /*
+                * This is to avoid error in cases where a 32-bit USB
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 58a51f09cceb8f..4cd4cb0e431d17 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1524,6 +1524,7 @@ struct xhci_hcd {
+       /* imod_interval in ns (I * 250ns) */
+       u32             imod_interval;
+       u32             page_size;
++      unsigned int    dma_mask_bits;
+       /* MSI-X/MSI vectors */
+       int             nvecs;
+       /* optional clocks */
+-- 
+2.53.0
+
diff --git a/queue-6.6/risc-v-kvm-serialize-virtual-interrupt-pending-state.patch b/queue-6.6/risc-v-kvm-serialize-virtual-interrupt-pending-state.patch
new file mode 100644 (file)
index 0000000..98f8628
--- /dev/null
@@ -0,0 +1,386 @@
+From 1e5d7c82565e45d8fd6613921135040edc514141 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jul 2026 10:06:19 +0800
+Subject: RISC-V: KVM: Serialize virtual interrupt pending state updates
+
+From: Xie Bo <xb@ultrarisc.com>
+
+commit d024a0a7879e6f37c0152aacf6d8e37b214a1738 upstream.
+
+KVM RISC-V tracks guest local interrupt state with two bitmaps:
+
+  - irqs_pending: interrupts that should be visible to the guest
+  - irqs_pending_mask: interrupts whose pending state changed
+
+The current code updates those bitmaps with independent atomic bitops
+and assumes a multiple-producer, single-consumer protocol. That model
+does not actually hold.
+
+kvm_riscv_vcpu_sync_interrupts() is not a pure consumer. When the guest
+changes guest-visible HVIP state, sync_interrupts() writes both
+irqs_pending and irqs_pending_mask to reflect the new guest state back
+into KVM state. As a result, irqs_pending and irqs_pending_mask form a
+single logical state transition, but they are not updated atomically as
+a pair.
+
+This allows a race where a newly injected interrupt is lost. For
+example:
+
+  CPU0                              CPU1
+  ----                              ----
+  kvm_riscv_vcpu_set_interrupt(VS_SOFT)
+    set_bit(VS_SOFT, irqs_pending)
+                                    kvm_riscv_vcpu_sync_interrupts()
+                                      sees guest-cleared HVIP.VSSIP
+                                      sets irqs_pending_mask
+                                      clear_bit(IRQ_VS_SOFT, irqs_pending)
+    set_bit(VS_SOFT, irqs_pending_mask)
+    kvm_vcpu_kick()
+
+After that interleaving, a later flush can update HVIP without VSSIP
+even though a new virtual interrupt was injected. In practice, the
+guest can remain blocked in WFI with work pending.
+
+The same pending/mask protocol is shared by VS soft interrupts, PMU
+overflow delivery, and AIA high interrupt synchronization, so the race
+is not limited to one interrupt source.
+
+Fix this by serializing all updates to irqs_pending and irqs_pending_mask
+with a per-vCPU raw spinlock. This keeps the pending bit and the dirty
+mask as one state transition across:
+
+  - set/unset interrupt
+  - guest HVIP sync
+  - interrupt flush to guest CSR state
+  - vCPU reset
+  - AIA CSR writes that clear dirty state
+
+Use non-atomic bitmap operations while holding the lock. Hold the lock
+across the AIA sync, flush, and pending checks as well, so both bitmap
+words share the same serialization domain.
+
+This intentionally replaces the existing lockless protocol instead of
+trying to repair it with additional barriers. The problem is not memory
+ordering on a single field; it is that two separate bitmaps encode one
+shared state machine while both producers and sync paths can modify
+them. A per-vCPU raw spinlock keeps the fix small, local, and suitable
+for backporting.
+
+Fixes: cce69aff689e ("RISC-V: KVM: Implement VCPU interrupts and requests handling")
+Cc: stable@vger.kernel.org
+Signed-off-by: Xie Bo <xb@ultrarisc.com>
+Reviewed-by: Anup Patel <anup@brainfault.org>
+Link: https://lore.kernel.org/r/20260715020359.1521354-2-xb@ultrarisc.com
+Signed-off-by: Anup Patel <anup@brainfault.org>
+[ bo: Drop IRQ_PMU_OVF handling, which is not present in 6.6.y, and
+  adapt the reset and CSR helpers to their older signatures. ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/riscv/include/asm/kvm_host.h | 10 ++---
+ arch/riscv/kvm/aia.c              | 35 +++++++++++++----
+ arch/riscv/kvm/vcpu.c             | 64 ++++++++++++++++++++++---------
+ arch/riscv/kvm/vcpu_onereg.c      |  8 +++-
+ 4 files changed, 85 insertions(+), 32 deletions(-)
+
+diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
+index 459e61ad7d2b68..d2d7f9b4f7c043 100644
+--- a/arch/riscv/include/asm/kvm_host.h
++++ b/arch/riscv/include/asm/kvm_host.h
+@@ -202,13 +202,13 @@ struct kvm_vcpu_arch {
+       /*
+        * VCPU interrupts
+        *
+-       * We have a lockless approach for tracking pending VCPU interrupts
+-       * implemented using atomic bitops. The irqs_pending bitmap represent
+-       * pending interrupts whereas irqs_pending_mask represent bits changed
+-       * in irqs_pending. Our approach is modeled around multiple producer
+-       * and single consumer problem where the consumer is the VCPU itself.
++       * The irqs_pending bitmap represents pending interrupts whereas
++       * irqs_pending_mask represents bits changed in irqs_pending. Updates
++       * to these bitmaps are serialized so vcpu interrupt sync/flush cannot
++       * drop a newly injected interrupt while syncing guest-visible HVIP.
+        */
+ #define KVM_RISCV_VCPU_NR_IRQS        64
++      raw_spinlock_t irqs_pending_lock;
+       DECLARE_BITMAP(irqs_pending, KVM_RISCV_VCPU_NR_IRQS);
+       DECLARE_BITMAP(irqs_pending_mask, KVM_RISCV_VCPU_NR_IRQS);
+diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c
+index 74bb27440527b3..be133090306455 100644
+--- a/arch/riscv/kvm/aia.c
++++ b/arch/riscv/kvm/aia.c
+@@ -71,12 +71,15 @@ void kvm_riscv_vcpu_aia_flush_interrupts(struct kvm_vcpu *vcpu)
+       struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
+       unsigned long mask, val;
++      lockdep_assert_held(&vcpu->arch.irqs_pending_lock);
++
+       if (!kvm_riscv_aia_available())
+               return;
+-      if (READ_ONCE(vcpu->arch.irqs_pending_mask[1])) {
+-              mask = xchg_acquire(&vcpu->arch.irqs_pending_mask[1], 0);
+-              val = READ_ONCE(vcpu->arch.irqs_pending[1]) & mask;
++      mask = vcpu->arch.irqs_pending_mask[1];
++      if (mask) {
++              vcpu->arch.irqs_pending_mask[1] = 0;
++              val = vcpu->arch.irqs_pending[1] & mask;
+               csr->hviph &= ~mask;
+               csr->hviph |= val;
+@@ -87,6 +90,8 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
+ {
+       struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
++      lockdep_assert_held(&vcpu->arch.irqs_pending_lock);
++
+       if (kvm_riscv_aia_available())
+               csr->vsieh = csr_read(CSR_VSIEH);
+ }
+@@ -96,13 +101,22 @@ bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
+ {
+       int hgei;
+       unsigned long seip;
++#ifdef CONFIG_32BIT
++      unsigned long flags;
++      bool pending;
++#endif
+       if (!kvm_riscv_aia_available())
+               return false;
+ #ifdef CONFIG_32BIT
+-      if (READ_ONCE(vcpu->arch.irqs_pending[1]) &
+-          (vcpu->arch.aia_context.guest_csr.vsieh & upper_32_bits(mask)))
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++      pending = vcpu->arch.irqs_pending[1] &
++                (vcpu->arch.aia_context.guest_csr.vsieh &
++                 upper_32_bits(mask));
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
++
++      if (pending)
+               return true;
+ #endif
+@@ -190,6 +204,9 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
+                              unsigned long val)
+ {
+       struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
++#ifdef CONFIG_32BIT
++      unsigned long flags;
++#endif
+       if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long))
+               return -ENOENT;
+@@ -198,8 +215,12 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
+               ((unsigned long *)csr)[reg_num] = val;
+ #ifdef CONFIG_32BIT
+-              if (reg_num == KVM_REG_RISCV_CSR_AIA_REG(siph))
+-                      WRITE_ONCE(vcpu->arch.irqs_pending_mask[1], 0);
++              if (reg_num == KVM_REG_RISCV_CSR_AIA_REG(siph)) {
++                      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++                      vcpu->arch.irqs_pending_mask[1] = 0;
++                      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock,
++                                                 flags);
++              }
+ #endif
+       }
+diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
+index 9584d62c96ee74..da769ecfdd1083 100644
+--- a/arch/riscv/kvm/vcpu.c
++++ b/arch/riscv/kvm/vcpu.c
+@@ -44,6 +44,7 @@ const struct kvm_stats_header kvm_vcpu_stats_header = {
+ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
+ {
++      unsigned long flags;
+       struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+       struct kvm_vcpu_csr *reset_csr = &vcpu->arch.guest_reset_csr;
+       struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
+@@ -74,8 +75,10 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
+       kvm_riscv_vcpu_aia_reset(vcpu);
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+       bitmap_zero(vcpu->arch.irqs_pending, KVM_RISCV_VCPU_NR_IRQS);
+       bitmap_zero(vcpu->arch.irqs_pending_mask, KVM_RISCV_VCPU_NR_IRQS);
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+       kvm_riscv_vcpu_pmu_reset(vcpu);
+@@ -117,6 +120,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
+       /* Setup VCPU hfence queue */
+       spin_lock_init(&vcpu->arch.hfence_lock);
++      raw_spin_lock_init(&vcpu->arch.irqs_pending_lock);
+       /* Setup reset state of shadow SSTATUS and HSTATUS CSRs */
+       cntx = &vcpu->arch.guest_reset_context;
+@@ -323,10 +327,14 @@ void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu)
+ {
+       struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+       unsigned long mask, val;
++      unsigned long flags;
+-      if (READ_ONCE(vcpu->arch.irqs_pending_mask[0])) {
+-              mask = xchg_acquire(&vcpu->arch.irqs_pending_mask[0], 0);
+-              val = READ_ONCE(vcpu->arch.irqs_pending[0]) & mask;
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++
++      mask = vcpu->arch.irqs_pending_mask[0];
++      if (mask) {
++              vcpu->arch.irqs_pending_mask[0] = 0;
++              val = vcpu->arch.irqs_pending[0] & mask;
+               csr->hvip &= ~mask;
+               csr->hvip |= val;
+@@ -334,11 +342,14 @@ void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu)
+       /* Flush AIA high interrupts */
+       kvm_riscv_vcpu_aia_flush_interrupts(vcpu);
++
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+ }
+ void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
+ {
+       unsigned long hvip;
++      unsigned long flags;
+       struct kvm_vcpu_arch *v = &vcpu->arch;
+       struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+@@ -347,27 +358,34 @@ void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
+       /* Sync-up HVIP.VSSIP bit changes does by Guest */
+       hvip = csr_read(CSR_HVIP);
++
++      raw_spin_lock_irqsave(&v->irqs_pending_lock, flags);
++
+       if ((csr->hvip ^ hvip) & (1UL << IRQ_VS_SOFT)) {
+               if (hvip & (1UL << IRQ_VS_SOFT)) {
+-                      if (!test_and_set_bit(IRQ_VS_SOFT,
+-                                            v->irqs_pending_mask))
+-                              set_bit(IRQ_VS_SOFT, v->irqs_pending);
++                      if (!__test_and_set_bit(IRQ_VS_SOFT,
++                                              v->irqs_pending_mask))
++                              __set_bit(IRQ_VS_SOFT, v->irqs_pending);
+               } else {
+-                      if (!test_and_set_bit(IRQ_VS_SOFT,
+-                                            v->irqs_pending_mask))
+-                              clear_bit(IRQ_VS_SOFT, v->irqs_pending);
++                      if (!__test_and_set_bit(IRQ_VS_SOFT,
++                                              v->irqs_pending_mask))
++                              __clear_bit(IRQ_VS_SOFT, v->irqs_pending);
+               }
+       }
+       /* Sync-up AIA high interrupts */
+       kvm_riscv_vcpu_aia_sync_interrupts(vcpu);
++      raw_spin_unlock_irqrestore(&v->irqs_pending_lock, flags);
++
+       /* Sync-up timer CSRs */
+       kvm_riscv_vcpu_timer_sync(vcpu);
+ }
+ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
+ {
++      unsigned long flags;
++
+       /*
+        * We only allow VS-mode software, timer, and external
+        * interrupts when irq is one of the local interrupts
+@@ -379,9 +397,10 @@ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
+           irq != IRQ_VS_EXT)
+               return -EINVAL;
+-      set_bit(irq, vcpu->arch.irqs_pending);
+-      smp_mb__before_atomic();
+-      set_bit(irq, vcpu->arch.irqs_pending_mask);
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++      __set_bit(irq, vcpu->arch.irqs_pending);
++      __set_bit(irq, vcpu->arch.irqs_pending_mask);
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+       kvm_vcpu_kick(vcpu);
+@@ -390,6 +409,8 @@ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
+ int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
+ {
++      unsigned long flags;
++
+       /*
+        * We only allow VS-mode software, timer, and external
+        * interrupts when irq is one of the local interrupts
+@@ -401,26 +422,33 @@ int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
+           irq != IRQ_VS_EXT)
+               return -EINVAL;
+-      clear_bit(irq, vcpu->arch.irqs_pending);
+-      smp_mb__before_atomic();
+-      set_bit(irq, vcpu->arch.irqs_pending_mask);
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++      __clear_bit(irq, vcpu->arch.irqs_pending);
++      __set_bit(irq, vcpu->arch.irqs_pending_mask);
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+       return 0;
+ }
+ bool kvm_riscv_vcpu_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
+ {
++      unsigned long flags;
+       unsigned long ie;
++      bool ret;
++      raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+       ie = ((vcpu->arch.guest_csr.vsie & VSIP_VALID_MASK)
+               << VSIP_TO_HVIP_SHIFT) & (unsigned long)mask;
+       ie |= vcpu->arch.guest_csr.vsie & ~IRQ_LOCAL_MASK &
+               (unsigned long)mask;
+-      if (READ_ONCE(vcpu->arch.irqs_pending[0]) & ie)
+-              return true;
++      ret = vcpu->arch.irqs_pending[0] & ie;
++      raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+       /* Check AIA high interrupts */
+-      return kvm_riscv_vcpu_aia_has_interrupts(vcpu, mask);
++      if (!ret)
++              ret = kvm_riscv_vcpu_aia_has_interrupts(vcpu, mask);
++
++      return ret;
+ }
+ void __kvm_riscv_vcpu_power_off(struct kvm_vcpu *vcpu)
+diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
+index d520b25d856167..0e5853186365e2 100644
+--- a/arch/riscv/kvm/vcpu_onereg.c
++++ b/arch/riscv/kvm/vcpu_onereg.c
+@@ -361,6 +361,7 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
+                                         unsigned long reg_val)
+ {
+       struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
++      unsigned long flags;
+       if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
+               return -ENOENT;
+@@ -372,8 +373,11 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
+       ((unsigned long *)csr)[reg_num] = reg_val;
+-      if (reg_num == KVM_REG_RISCV_CSR_REG(sip))
+-              WRITE_ONCE(vcpu->arch.irqs_pending_mask[0], 0);
++      if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
++              raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
++              vcpu->arch.irqs_pending_mask[0] = 0;
++              raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
++      }
+       return 0;
+ }
+-- 
+2.53.0
+
index 39f8e6224635649aad0ab3247dca4335aa866bda..e9d9d6b586991c4c7b17ce2adea842f446b994ae 100644 (file)
@@ -112,3 +112,5 @@ usb-serial-option-add-tdtech-mt5710-cn.patch
 posix-cpu-timers-prevent-uaf-caused-by-non-leader-ex.patch
 crypto-rsa-pkcs1pad-don-t-warn-on-an-empty-digest.patch
 revert-drm-amd-display-add-missing-kdoc-for-allm-par.patch
+risc-v-kvm-serialize-virtual-interrupt-pending-state.patch
+usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
diff --git a/queue-6.6/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch b/queue-6.6/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
new file mode 100644 (file)
index 0000000..3dd9fa7
--- /dev/null
@@ -0,0 +1,98 @@
+From e60692a6513e848eb3fa0456ff17e22702785c0a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:41:00 +0800
+Subject: usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
+
+From: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+
+commit 1fc50f1ecde39feb4fccdaf4bc71aa6c0eb25c49 upstream.
+
+The VIA VL805/806 xHCI controller advertises AC64, but fails to handle
+DMA addresses at or above 0x1000000000. On systems with large amounts of
+RAM, this can cause USB device failures when the controller is given DMA
+addresses beyond its usable address width.
+
+Do not use XHCI_NO_64BIT_SUPPORT for this controller. That quirk clears
+the cached AC64 capability and limits DMA to 32 bits, causing unnecessary
+bouncing for addresses between 4GiB and 64GiB and hiding the controller's
+real AC64 capability from code that may need to distinguish register
+access width from usable DMA address width.
+
+Track the usable DMA address width separately from the AC64 capability.
+Initialize the generic xhci->dma_mask_bits field to 64 and let PCI quirks
+reduce it for controllers with narrower DMA support. Set VIA VL805/806 to
+36 bits so the DMA API only hands it addresses in the range it can handle
+while keeping HCCPARAMS1.AC64 visible.
+
+Cc: stable@kernel.org
+Signed-off-by: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+Link: https://patch.msgid.link/20260630-xhci-via-dma-fix-v3-1-690dcb8cf75a@ultrarisc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-pci.c |  1 +
+ drivers/usb/host/xhci.c     | 15 ++++++++++-----
+ drivers/usb/host/xhci.h     |  1 +
+ 3 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
+index 5abc48f148dcbc..d5ba5a34625bef 100644
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -510,6 +510,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+       if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == PCI_DEVICE_ID_VIA_VL805) {
+               xhci->quirks |= XHCI_LPM_SUPPORT;
+               xhci->quirks |= XHCI_TRB_OVERFETCH;
++              xhci->dma_mask_bits = 36;
+       }
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 31509845594e9f..210b5727d1a632 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -5267,6 +5267,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->hci_version > 0x100)
+               xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
++      xhci->dma_mask_bits = 64;
+       /* xhci-plat or xhci-pci might have set max_interrupters already */
+       if ((!xhci->max_interrupters) ||
+           xhci->max_interrupters > HCS_MAX_INTRS(xhci->hcs_params1))
+@@ -5308,12 +5309,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->quirks & XHCI_NO_64BIT_SUPPORT)
+               xhci->hcc_params &= ~BIT(0);
+-      /* Set dma_mask and coherent_dma_mask to 64-bits,
+-       * if xHC supports 64-bit addressing */
++      /*
++       * Set dma_mask and coherent_dma_mask to 64-bits if xHC supports
++       * 64-bit addressing, unless a controller-specific quirk callback
++       * limits the usable address width.
++       */
+       if (HCC_64BIT_ADDR(xhci->hcc_params) &&
+-                      !dma_set_mask(dev, DMA_BIT_MASK(64))) {
+-              xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+-              dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
++          !dma_set_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits))) {
++              xhci_dbg(xhci, "Enabling %u-bit DMA addresses.\n",
++                       xhci->dma_mask_bits);
++              dma_set_coherent_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits));
+       } else {
+               /*
+                * This is to avoid error in cases where a 32-bit USB
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 849a83e4013cca..bb7e73df297abc 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1538,6 +1538,7 @@ struct xhci_hcd {
+       int             event_ring_max;
+       /* 4KB min, 128MB max */
+       int             page_size;
++      unsigned int    dma_mask_bits;
+       /* Valid values are 12 to 20, inclusive */
+       int             page_shift;
+       /* msi-x vectors */
+-- 
+2.53.0
+
diff --git a/queue-7.1/selftests-bpf-adjust-verifier_map_ptr-for-the-map-s-.patch b/queue-7.1/selftests-bpf-adjust-verifier_map_ptr-for-the-map-s-.patch
new file mode 100644 (file)
index 0000000..ee89b0f
--- /dev/null
@@ -0,0 +1,62 @@
+From 4d619b836061cd599df1425eb32e052bbb841260 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 15:25:08 +0800
+Subject: selftests/bpf: Adjust verifier_map_ptr for the map's excl field
+
+From: KP Singh <kpsingh@kernel.org>
+
+commit 38498c0ebacd54dbaac3513a548a13f1a8455c4e upstream.
+
+Adding the u32 excl field at offset 32 of struct bpf_map right after the
+sha[SHA256_DIGEST_SIZE] hash shifts the ops pointer from offset 32 to 40.
+Therefore, fix up the test case.
+
+  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_map_ptr
+  [...]
+  #637/1   verifier_map_ptr/bpf_map_ptr: read with negative offset rejected:OK
+  #637/2   verifier_map_ptr/bpf_map_ptr: read with negative offset rejected @unpriv:OK
+  #637/3   verifier_map_ptr/bpf_map_ptr: write rejected:OK
+  #637/4   verifier_map_ptr/bpf_map_ptr: write rejected @unpriv:OK
+  #637/5   verifier_map_ptr/bpf_map_ptr: read non-existent field rejected:OK
+  #637/6   verifier_map_ptr/bpf_map_ptr: read non-existent field rejected @unpriv:OK
+  #637/7   verifier_map_ptr/bpf_map_ptr: read ops field accepted:OK
+  #637/8   verifier_map_ptr/bpf_map_ptr: read ops field accepted @unpriv:OK
+  [...]
+  Summary: 2/18 PASSED, 0 SKIPPED, 0 FAILED
+
+Signed-off-by: KP Singh <kpsingh@kernel.org>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260601150248.394863-7-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/bpf/progs/verifier_map_ptr.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/progs/verifier_map_ptr.c b/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
+index e2767d27d8aaf8..d8e822d1a8bab6 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
++++ b/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
+@@ -70,13 +70,15 @@ __naked void bpf_map_ptr_write_rejected(void)
+       : __clobber_all);
+ }
+-/* The first element of struct bpf_map is a SHA256 hash of 32 bytes, accessing
+- * into this array is valid. The opts field is now at offset 33.
++/*
++ * struct bpf_map starts with the SHA256 hash sha[32] at offset 0 (a readable
++ * byte array), followed by the u32 excl field at offset 32. Reading a u32 at
++ * offset 33 runs past the end of excl and is rejected.
+  */
+ SEC("socket")
+ __description("bpf_map_ptr: read non-existent field rejected")
+ __failure
+-__msg("cannot access ptr member ops with moff 32 in struct bpf_map with off 33 size 4")
++__msg("access beyond the end of member excl (mend:36) in struct bpf_map with off 33 size 4")
+ __failure_unpriv
+ __msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")
+ __flag(BPF_F_ANY_ALIGNMENT)
+-- 
+2.53.0
+
diff --git a/queue-7.1/selftests-bpf-keep-verifier_map_ptr-exercising-ops-p.patch b/queue-7.1/selftests-bpf-keep-verifier_map_ptr-exercising-ops-p.patch
new file mode 100644 (file)
index 0000000..697cf23
--- /dev/null
@@ -0,0 +1,107 @@
+From 60d662120c20ca34fd253b72d836e781f29ff287 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 15:25:09 +0800
+Subject: selftests/bpf: Keep verifier_map_ptr exercising ops pointer access
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit 082c412097716b93ff1365689fc4ddcd1ce8296f upstream.
+
+sashiko complained that 38498c0ebacd ("selftests/bpf: Adjust verifier_map_ptr
+for the map's excl field") would slightly decrease the test coverage given
+before the test was against the verifier rejecting the ops pointer. Recover
+the old test with the right offsets and add the existing one as an additional
+test case.
+
+  # LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_map_ptr
+  [    1.672932] bpf_testmod: module verification failed: signature and/or required key missing - tainting kernel
+  #637/1   verifier_map_ptr/bpf_map_ptr: read with negative offset rejected:OK
+  #637/2   verifier_map_ptr/bpf_map_ptr: read with negative offset rejected @unpriv:OK
+  #637/3   verifier_map_ptr/bpf_map_ptr: write rejected:OK
+  #637/4   verifier_map_ptr/bpf_map_ptr: write rejected @unpriv:OK
+  #637/5   verifier_map_ptr/bpf_map_ptr: read non-existent field rejected:OK
+  #637/6   verifier_map_ptr/bpf_map_ptr: read non-existent field rejected @unpriv:OK
+  #637/7   verifier_map_ptr/bpf_map_ptr: read beyond excl field rejected:OK
+  #637/8   verifier_map_ptr/bpf_map_ptr: read beyond excl field rejected @unpriv:OK
+  #637/9   verifier_map_ptr/bpf_map_ptr: read ops field accepted:OK
+  #637/10  verifier_map_ptr/bpf_map_ptr: read ops field accepted @unpriv:OK
+  #637/11  verifier_map_ptr/bpf_map_ptr: r = 0, map_ptr = map_ptr + r:OK
+  #637/12  verifier_map_ptr/bpf_map_ptr: r = 0, map_ptr = map_ptr + r @unpriv:OK
+  #637/13  verifier_map_ptr/bpf_map_ptr: r = 0, r = r + map_ptr:OK
+  #637/14  verifier_map_ptr/bpf_map_ptr: r = 0, r = r + map_ptr @unpriv:OK
+  #637     verifier_map_ptr:OK
+  [...]
+  Summary: 2/20 PASSED, 0 SKIPPED, 0 FAILED
+
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20260602133052.423725-4-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/bpf/progs/verifier_map_ptr.c    | 34 ++++++++++++++++---
+ 1 file changed, 30 insertions(+), 4 deletions(-)
+
+diff --git a/tools/testing/selftests/bpf/progs/verifier_map_ptr.c b/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
+index d8e822d1a8bab6..1661936598703c 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
++++ b/tools/testing/selftests/bpf/progs/verifier_map_ptr.c
+@@ -72,17 +72,43 @@ __naked void bpf_map_ptr_write_rejected(void)
+ /*
+  * struct bpf_map starts with the SHA256 hash sha[32] at offset 0 (a readable
+- * byte array), followed by the u32 excl field at offset 32. Reading a u32 at
+- * offset 33 runs past the end of excl and is rejected.
++ * byte array), the u32 excl field at offset 32, and the ops pointer at offset
++ * 40. Reading a u32 at offset 41 reaches into the middle of the ops pointer,
++ * i.e. a partial pointer access, which is rejected.
+  */
+ SEC("socket")
+ __description("bpf_map_ptr: read non-existent field rejected")
+ __failure
+-__msg("access beyond the end of member excl (mend:36) in struct bpf_map with off 33 size 4")
++__msg("cannot access ptr member ops with moff 40 in struct bpf_map with off 41 size 4")
+ __failure_unpriv
+ __msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")
+ __flag(BPF_F_ANY_ALIGNMENT)
+ __naked void read_non_existent_field_rejected(void)
++{
++      asm volatile ("                                 \
++      r6 = 0;                                         \
++      r1 = %[map_array_48b] ll;                       \
++      r6 = *(u32*)(r1 + 41);                          \
++      r0 = 1;                                         \
++      exit;                                           \
++"     :
++      : __imm_addr(map_array_48b)
++      : __clobber_all);
++}
++
++/*
++ * The u32 excl field spans offsets 32..35 (mend 36). Reading a u32 at offset
++ * 33 starts inside excl but extends past its end, which the verifier rejects
++ * as an out-of-bounds scalar access.
++ */
++SEC("socket")
++__description("bpf_map_ptr: read beyond excl field rejected")
++__failure
++__msg("access beyond the end of member excl (mend:36) in struct bpf_map with off 33 size 4")
++__failure_unpriv
++__msg_unpriv("access is allowed only to CAP_PERFMON and CAP_SYS_ADMIN")
++__flag(BPF_F_ANY_ALIGNMENT)
++__naked void read_beyond_excl_field_rejected(void)
+ {
+       asm volatile ("                                 \
+       r6 = 0;                                         \
+@@ -105,7 +131,7 @@ __naked void ptr_read_ops_field_accepted(void)
+       asm volatile ("                                 \
+       r6 = 0;                                         \
+       r1 = %[map_array_48b] ll;                       \
+-      r6 = *(u64*)(r1 + 0);                           \
++      r6 = *(u64*)(r1 + 40);                          \
+       r0 = 1;                                         \
+       exit;                                           \
+ "     :
+-- 
+2.53.0
+
index ab5db8cdbe119121ad2979c3db49161fc7a48ef1..bca54f633839c0cce14259668552cfa6af914618 100644 (file)
@@ -162,3 +162,6 @@ drm-amd-display-add-dp_skip_rbr-flag-for-nutmeg.patch
 wifi-mwifiex-fix-freeze-for-60-seconds-caused-by-req.patch
 risc-v-kvm-serialize-virtual-interrupt-pending-state.patch
 revert-drm-amd-display-add-missing-kdoc-for-allm-par.patch
+usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
+selftests-bpf-adjust-verifier_map_ptr-for-the-map-s-.patch
+selftests-bpf-keep-verifier_map_ptr-exercising-ops-p.patch
diff --git a/queue-7.1/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch b/queue-7.1/usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch
new file mode 100644 (file)
index 0000000..479c7d4
--- /dev/null
@@ -0,0 +1,98 @@
+From 6bfa2043f130d971f495789fce705e684c9e004f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jul 2026 13:46:07 +0800
+Subject: usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
+
+From: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+
+commit 1fc50f1ecde39feb4fccdaf4bc71aa6c0eb25c49 upstream.
+
+The VIA VL805/806 xHCI controller advertises AC64, but fails to handle
+DMA addresses at or above 0x1000000000. On systems with large amounts of
+RAM, this can cause USB device failures when the controller is given DMA
+addresses beyond its usable address width.
+
+Do not use XHCI_NO_64BIT_SUPPORT for this controller. That quirk clears
+the cached AC64 capability and limits DMA to 32 bits, causing unnecessary
+bouncing for addresses between 4GiB and 64GiB and hiding the controller's
+real AC64 capability from code that may need to distinguish register
+access width from usable DMA address width.
+
+Track the usable DMA address width separately from the AC64 capability.
+Initialize the generic xhci->dma_mask_bits field to 64 and let PCI quirks
+reduce it for controllers with narrower DMA support. Set VIA VL805/806 to
+36 bits so the DMA API only hands it addresses in the range it can handle
+while keeping HCCPARAMS1.AC64 visible.
+
+Cc: stable@kernel.org
+Signed-off-by: Xincheng Zhang <zhangxincheng@ultrarisc.com>
+Link: https://patch.msgid.link/20260630-xhci-via-dma-fix-v3-1-690dcb8cf75a@ultrarisc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-pci.c |  1 +
+ drivers/usb/host/xhci.c     | 15 ++++++++++-----
+ drivers/usb/host/xhci.h     |  1 +
+ 3 files changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
+index 585b2f3117b08a..b0377701a94042 100644
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -448,6 +448,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
+       if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == PCI_DEVICE_ID_VIA_VL805) {
+               xhci->quirks |= XHCI_LPM_SUPPORT;
+               xhci->quirks |= XHCI_TRB_OVERFETCH;
++              xhci->dma_mask_bits = 36;
+       }
+       if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 15346fdd66bc43..5b15eae233d3f6 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -5469,6 +5469,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->hci_version > 0x100)
+               xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
++      xhci->dma_mask_bits = 64;
+       xhci->max_slots = HCS_MAX_SLOTS(hcs_params1);
+       xhci->max_ports = min(HCS_MAX_PORTS(hcs_params1), MAX_HC_PORTS);
+       /* xhci-plat or xhci-pci might have set max_interrupters already */
+@@ -5518,12 +5519,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
+       if (xhci->quirks & XHCI_NO_64BIT_SUPPORT)
+               xhci->hcc_params &= ~BIT(0);
+-      /* Set dma_mask and coherent_dma_mask to 64-bits,
+-       * if xHC supports 64-bit addressing */
++      /*
++       * Set dma_mask and coherent_dma_mask to 64-bits if xHC supports
++       * 64-bit addressing, unless a controller-specific quirk callback
++       * limits the usable address width.
++       */
+       if ((xhci->hcc_params & HCC_64BIT_ADDR) &&
+-                      !dma_set_mask(dev, DMA_BIT_MASK(64))) {
+-              xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+-              dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
++          !dma_set_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits))) {
++              xhci_dbg(xhci, "Enabling %u-bit DMA addresses.\n",
++                       xhci->dma_mask_bits);
++              dma_set_coherent_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits));
+       } else {
+               /*
+                * This is to avoid error in cases where a 32-bit USB
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index aeecd301f20707..d0f14fc2324572 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1524,6 +1524,7 @@ struct xhci_hcd {
+       /* imod_interval in ns (I * 250ns) */
+       u32             imod_interval;
+       u32             page_size;
++      unsigned int    dma_mask_bits;
+       /* MSI-X/MSI vectors */
+       int             nvecs;
+       /* optional clocks */
+-- 
+2.53.0
+