* Re: [PATCH v3 03/24] PCI: Require Live Update preserved devices are in singleton iommu_groups
From: David Matlack @ 2026-03-24 18:00 UTC (permalink / raw)
To: Yi Liu
Cc: Alex Williamson, Bjorn Helgaas, Adithya Jayachandran,
Alexander Graf, Alex Mastro, Andrew Morton, Ankit Agrawal,
Arnd Bergmann, Askar Safin, Borislav Petkov (AMD), Chris Li,
Dapeng Mi, David Rientjes, Feng Tang, Jacob Pan, Jason Gunthorpe,
Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Kees Cook,
Kevin Tian, kexec, kvm, Leon Romanovsky, Leon Romanovsky,
linux-doc, linux-kernel, linux-kselftest, linux-mm, linux-pci,
Li RongQing, Lukas Wunner, Marco Elver, Michał Winiarski,
Mike Rapoport, Parav Pandit, Pasha Tatashin, Paul E. McKenney,
Pawan Gupta, Peter Zijlstra (Intel), Pranjal Shrivastava,
Pratyush Yadav, Raghavendra Rao Ananta, Randy Dunlap,
Rodrigo Vivi, Saeed Mahameed, Samiullah Khawaja, Shuah Khan,
Vipin Sharma, Vivek Kasireddy, William Tu, Zhu Yanjun
In-Reply-To: <376910fa-4232-4e58-bf87-0504202866a5@intel.com>
On 2026-03-24 09:07 PM, Yi Liu wrote:
> On 3/24/26 07:57, David Matlack wrote:
> > Require that Live Update preserved devices are in singleton iommu_groups
> > during preservation (outgoing kernel) and retrieval (incoming kernel).
> >
> > PCI devices preserved across Live Update will be allowed to perform
> > memory transactions throughout the Live Update. Thus IOMMU groups for
> > preserved devices must remain fixed. Since all current use cases for
> > Live Update are for PCI devices in singleton iommu_groups, require that
> > as a starting point. This avoids the complexity of needing to enforce
> > arbitrary iommu_group topologies while still allowing all current use
> > cases.
> >
> > Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
> > Signed-off-by: David Matlack <dmatlack@google.com>
> > ---
> > drivers/pci/liveupdate.c | 34 +++++++++++++++++++++++++++++++++-
> > 1 file changed, 33 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c
> > index bec7b3500057..a3dbe06650ff 100644
> > --- a/drivers/pci/liveupdate.c
> > +++ b/drivers/pci/liveupdate.c
> > @@ -75,6 +75,8 @@
> > *
> > * * The device must not be a Physical Function (PF).
> > *
> > + * * The device must be the only device in its IOMMU group.
> > + *
> > * Preservation Behavior
> > * =====================
> > *
> > @@ -105,6 +107,7 @@
> > #include <linux/bsearch.h>
> > #include <linux/io.h>
> > +#include <linux/iommu.h>
> > #include <linux/kexec_handover.h>
> > #include <linux/kho/abi/pci.h>
> > #include <linux/liveupdate.h>
> > @@ -222,6 +225,31 @@ static void pci_ser_delete(struct pci_ser *ser, struct pci_dev *dev)
> > ser->nr_devices--;
> > }
> > +static int count_devices(struct device *dev, void *__nr_devices)
> > +{
> > + (*(int *)__nr_devices)++;
> > + return 0;
> > +}
> > +
>
> there was a related discussion on the singleton group check. have you
> considered the device_group_immutable_singleton() in below link?
>
> https://lore.kernel.org/linux-iommu/20220421052121.3464100-4-baolu.lu@linux.intel.com/
Thanks for the link.
Based on the discussion in the follow-up threads, I think the only check
in that function that is needed on top of what is in this patch to
ensure group immutability is this one:
/*
* The device could be considered to be fully isolated if
* all devices on the path from the device to the host-PCI
* bridge are protected from peer-to-peer DMA by ACS.
*/
if (!pci_acs_path_enabled(pdev, NULL, REQ_ACS_FLAGS))
return false;
However, this would restrict Live Update support to only device
topologies that have these flags enabled. I am not yet sure if this
would be overly restrictive for the scenarios we care about supporting.
An alternative way to ensure immutability would be to block adding
devices at probe time. i.e. Fail pci_device_group() if the device being
added has liveupdate_incoming=True, or if the group already contains a
device with liveupdate_{incoming,outgoing}=True. We would still need the
check in pci_liveupdate_preserve() to pretect against setting
liveupdate_outgoing=True on a device in a multi-device group.
^ permalink raw reply
* [PATCH v7 5/5] Documentation: laptops: Update documentation for uniwill laptops
From: Werner Sembach @ 2026-03-24 18:02 UTC (permalink / raw)
To: W_Armin, hansg, ilpo.jarvinen, Jonathan Corbet, Shuah Khan
Cc: platform-driver-x86, linux-kernel, Werner Sembach, linux-doc
In-Reply-To: <20260324180437.69594-1-wse@tuxedocomputers.com>
Adds short description for two new sysfs entries, ctgp_offset and
usb_c_power_priority, to the documentation of uniwill laptops.
Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
---
.../ABI/testing/sysfs-driver-uniwill-laptop | 25 +++++++++++++++++++
.../admin-guide/laptops/uniwill-laptop.rst | 12 +++++++++
2 files changed, 37 insertions(+)
diff --git a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
index 2df70792968f3..cba4138604601 100644
--- a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
+++ b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
@@ -51,3 +51,28 @@ Description:
Reading this file returns the current status of the breathing animation
functionality.
+
+What: /sys/bus/platform/devices/INOU0000:XX/ctgp_offset
+Date: January 2026
+KernelVersion: 7.0
+Contact: Werner Sembach <wse@tuxedocomputers.com>
+Description:
+ Allows userspace applications to set the configurable TGP offset on top of the base
+ TGP. Base TGP and max TGP and therefore the max cTGP offset are device specific.
+ Note that setting the maximal cTGP leaves no window open for Dynamic Boost,
+ effectively disabling that feature for the GPU to always be prioritized.
+
+ Reading this file returns the current configurable TGP offset.
+
+What: /sys/bus/platform/devices/INOU0000:XX/usb_c_power_priority
+Date: February 2026
+KernelVersion: 7.1
+Contact: Werner Sembach <wse@tuxedocomputers.com>
+Description:
+ Allows userspace applications to choose the USB-C power distribution profile between
+ one that offers a bigger share of the power to the battery and one that offers more
+ of it to the CPU. Writing "charging"/"performance" into this file selects the
+ respective profile.
+
+ Reading this file returns the profile names with the currently active one in
+ brackets.
diff --git a/Documentation/admin-guide/laptops/uniwill-laptop.rst b/Documentation/admin-guide/laptops/uniwill-laptop.rst
index aff5f57a6bd47..561334865feb7 100644
--- a/Documentation/admin-guide/laptops/uniwill-laptop.rst
+++ b/Documentation/admin-guide/laptops/uniwill-laptop.rst
@@ -50,6 +50,10 @@ between 1 and 100 percent are supported.
Additionally the driver signals the presence of battery charging issues through the standard
``health`` power supply sysfs attribute.
+It also lets you set whether a USB-C power source should prioritise charging the battery or
+delivering immediate power to the cpu. See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for
+details.
+
Lightbar
--------
@@ -58,3 +62,11 @@ LED class device. The default name of this LED class device is ``uniwill:multico
See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details on how to control the various
animation modes of the lightbar.
+
+Configurable TGP
+----------------
+
+The ``uniwill-laptop`` driver allows to set the configurable TGP for devices with NVIDIA GPUs that
+allow it.
+
+See Documentation/ABI/testing/sysfs-driver-uniwill-laptop for details.
--
2.43.0
^ permalink raw reply related
* Re: [PATCH net-next v3 03/13] net: introduce ndo_set_rx_mode_async and dev_rx_mode_work
From: Stanislav Fomichev @ 2026-03-24 18:13 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Stanislav Fomichev, netdev, davem, edumazet, pabeni, horms,
corbet, skhan, andrew+netdev, michael.chan, pavan.chebbi,
anthony.l.nguyen, przemyslaw.kitszel, saeedm, tariqt, mbloch,
alexanderduyck, kernel-team, johannes, sd, jianbol, dtatulea,
mohsin.bashr, jacob.e.keller, willemb, skhawaja, bestswngs,
aleksandr.loktionov, kees, linux-doc, linux-kernel,
intel-wired-lan, linux-rdma, linux-wireless, linux-kselftest,
leon
In-Reply-To: <20260323162003.0d155055@kernel.org>
On 03/23, Jakub Kicinski wrote:
> On Thu, 19 Mar 2026 18:24:51 -0700 Stanislav Fomichev wrote:
> > diff --git a/Documentation/networking/netdevices.rst b/Documentation/networking/netdevices.rst
> > index 35704d115312..dc83d78d3b27 100644
> > --- a/Documentation/networking/netdevices.rst
> > +++ b/Documentation/networking/netdevices.rst
> > @@ -289,6 +289,14 @@ struct net_device synchronization rules
> > ndo_set_rx_mode:
> > Synchronization: netif_addr_lock spinlock.
> > Context: BHs disabled
> > + Notes: Deprecated in favor of sleepable ndo_set_rx_mode_async.
> >
> > +ndo_set_rx_mode_async:
> > + Synchronization: rtnl_lock() semaphore. In addition, netdev instance
> > + lock if the driver implements queue management or shaper API.
> > + Context: process (from a work queue)
> > + Notes: Sleepable version of ndo_set_rx_mode. Receives snapshots
>
> It's probably just my weirdness but I find creating adjectives out
> of random nouns by adding "-able" to be in poor taste. "sleepable"
> took root in certain three letter subsystems but I hope it won't
> in netdev.
>
> Please use your words:
>
> Notes: Async version of ndo_set_rx_mode which runs in process
> context. Receives snapshots f the unicast and multicast address lists.
SG, will do!
> > + of the unicast and multicast address lists.
> >
> > ndo_setup_tc:
> > ``TC_SETUP_BLOCK`` and ``TC_SETUP_FT`` are running under NFT locks
> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > index 469b7cdb3237..b05bdd67b807 100644
> > --- a/include/linux/netdevice.h
> > +++ b/include/linux/netdevice.h
> > @@ -1117,6 +1117,16 @@ struct netdev_net_notifier {
> > * This function is called device changes address list filtering.
> > * If driver handles unicast address filtering, it should set
> > * IFF_UNICAST_FLT in its priv_flags.
> > + * Cannot sleep, called with netif_addr_lock_bh held.
> > + * Deprecated in favor of sleepable ndo_set_rx_mode_async.
> > + *
> > + * void (*ndo_set_rx_mode_async)(struct net_device *dev,
> > + * struct netdev_hw_addr_list *uc,
> > + * struct netdev_hw_addr_list *mc);
> > + * Sleepable version of ndo_set_rx_mode. Called from a work queue
> > + * with rtnl_lock and netdev_lock_ops(dev) held. The uc/mc parameters
> > + * are snapshots of the address lists - iterate with
> > + * netdev_hw_addr_list_for_each(ha, uc).
> > *
> > * int (*ndo_set_mac_address)(struct net_device *dev, void *addr);
> > * This function is called when the Media Access Control address
> > @@ -1437,6 +1447,9 @@ struct net_device_ops {
> > void (*ndo_change_rx_flags)(struct net_device *dev,
> > int flags);
> > void (*ndo_set_rx_mode)(struct net_device *dev);
> > + void (*ndo_set_rx_mode_async)(struct net_device *dev,
> > + struct netdev_hw_addr_list *uc,
> > + struct netdev_hw_addr_list *mc);
> > int (*ndo_set_mac_address)(struct net_device *dev,
> > void *addr);
> > int (*ndo_validate_addr)(struct net_device *dev);
> > @@ -1903,6 +1916,7 @@ enum netdev_reg_state {
> > * has been enabled due to the need to listen to
> > * additional unicast addresses in a device that
> > * does not implement ndo_set_rx_mode()
> > + * @rx_mode_work: Work queue entry for ndo_set_rx_mode_async()
> > * @uc: unicast mac addresses
> > * @mc: multicast mac addresses
> > * @dev_addrs: list of device hw addresses
> > @@ -2293,6 +2307,7 @@ struct net_device {
> > unsigned int promiscuity;
> > unsigned int allmulti;
> > bool uc_promisc;
> > + struct work_struct rx_mode_work;
> > #ifdef CONFIG_LOCKDEP
> > unsigned char nested_level;
> > #endif
> > @@ -4661,6 +4676,11 @@ static inline bool netif_device_present(const struct net_device *dev)
> > return test_bit(__LINK_STATE_PRESENT, &dev->state);
> > }
> >
> > +static inline bool netif_up_and_present(const struct net_device *dev)
> > +{
> > + return (dev->flags & IFF_UP) && netif_device_present(dev);
>
> Is this really worth a dedicated helper? What are you trying to express
> here semantically?
I mostly added it to avoid repeating the same present & UP check. Will
undo.
> > +
> > void netif_device_detach(struct net_device *dev);
> >
> > void netif_device_attach(struct net_device *dev);
> > diff --git a/net/core/dev.c b/net/core/dev.c
> > index 200d44883fc1..fedc423306fc 100644
> > --- a/net/core/dev.c
> > +++ b/net/core/dev.c
> > @@ -2381,6 +2381,8 @@ static void netstamp_clear(struct work_struct *work)
> > static DECLARE_WORK(netstamp_work, netstamp_clear);
> > #endif
> >
> > +static struct workqueue_struct *rx_mode_wq;
> > +
> > void net_enable_timestamp(void)
> > {
> > #ifdef CONFIG_JUMP_LABEL
> > @@ -9669,22 +9671,84 @@ int netif_set_allmulti(struct net_device *dev, int inc, bool notify)
> > return 0;
> > }
> >
> > -/*
> > - * Upload unicast and multicast address lists to device and
> > - * configure RX filtering. When the device doesn't support unicast
> > - * filtering it is put in promiscuous mode while unicast addresses
> > - * are present.
> > +static void dev_rx_mode_work(struct work_struct *work)
> > +{
> > + struct net_device *dev = container_of(work, struct net_device,
> > + rx_mode_work);
> > + struct netdev_hw_addr_list uc_snap, mc_snap, uc_ref, mc_ref;
> > + const struct net_device_ops *ops = dev->netdev_ops;
> > + int err;
> > +
> > + __hw_addr_init(&uc_snap);
> > + __hw_addr_init(&mc_snap);
> > + __hw_addr_init(&uc_ref);
> > + __hw_addr_init(&mc_ref);
> > +
> > + rtnl_lock();
> > + netdev_lock_ops(dev);
> > +
> > + if (!netif_up_and_present(dev))
> > + goto out;
> > +
> > + if (ops->ndo_set_rx_mode_async) {
>
> How did we get here if we don't have this op?
> Are you planning to plumb more code thru this work in the future?
> If yes the whole rx_mode handling should be in a dedicated helper
> rather than indenting most of the function.
I do expand this, yes, in the subsequent patches. With promisc
handling (ndo_change_rx_flags) and ndo_set_rx_mode fallback. Let me try
to see if I can add some helper+struct to manage a set of snapshots
to make it a bit more clear.
> > + netif_addr_lock_bh(dev);
> > +
> > + err = __hw_addr_list_snapshot(&uc_snap, &dev->uc,
> > + dev->addr_len);
> > + if (!err)
> > + err = __hw_addr_list_snapshot(&uc_ref, &dev->uc,
> > + dev->addr_len);
> > + if (!err)
> > + err = __hw_addr_list_snapshot(&mc_snap, &dev->mc,
> > + dev->addr_len);
> > + if (!err)
> > + err = __hw_addr_list_snapshot(&mc_ref, &dev->mc,
> > + dev->addr_len);
>
> This doesn't get slow with a few thousands of addresses?
I can add kunit benchmark and attach the output? Although not sure where
to go from that. The alternative to this is allocating an array of entries.
I started with that initially but __hw_addr_sync_dev wants to kfree the
individual entries and I decided not to have a separate helpers to
manage the snapshots.
> > + netif_addr_unlock_bh(dev);
> > +
> > + if (err) {
> > + netdev_WARN(dev, "failed to sync uc/mc addresses\n");
> > + __hw_addr_flush(&uc_snap);
> > + __hw_addr_flush(&uc_ref);
> > + __hw_addr_flush(&mc_snap);
> > + goto out;
> > + }
> > +
> > + ops->ndo_set_rx_mode_async(dev, &uc_snap, &mc_snap);
> > +
> > + netif_addr_lock_bh(dev);
> > + __hw_addr_list_reconcile(&dev->uc, &uc_snap,
> > + &uc_ref, dev->addr_len);
> > + __hw_addr_list_reconcile(&dev->mc, &mc_snap,
> > + &mc_ref, dev->addr_len);
> > + netif_addr_unlock_bh(dev);
> > + }
> > +
> > +out:
> > + netdev_unlock_ops(dev);
> > + rtnl_unlock();
> > +}
> > +
> > +/**
> > + * __dev_set_rx_mode() - upload unicast and multicast address lists to device
> > + * and configure RX filtering.
> > + * @dev: device
> > + *
> > + * When the device doesn't support unicast filtering it is put in promiscuous
> > + * mode while unicast addresses are present.
> > */
> > void __dev_set_rx_mode(struct net_device *dev)
> > {
> > const struct net_device_ops *ops = dev->netdev_ops;
> >
> > /* dev_open will call this function so the list will stay sane. */
> > - if (!(dev->flags&IFF_UP))
> > + if (!netif_up_and_present(dev))
> > return;
> >
> > - if (!netif_device_present(dev))
> > + if (ops->ndo_set_rx_mode_async) {
> > + queue_work(rx_mode_wq, &dev->rx_mode_work);
> > return;
> > + }
> >
> > if (!(dev->priv_flags & IFF_UNICAST_FLT)) {
> > /* Unicast addresses changes may only happen under the rtnl,
> > @@ -11708,6 +11772,16 @@ void netdev_run_todo(void)
> >
> > __rtnl_unlock();
> >
> > + /* Make sure all pending rx_mode work completes before returning.
> > + *
> > + * rx_mode_wq may be NULL during early boot:
> > + * core_initcall(netlink_proto_init) vs subsys_initcall(net_dev_init).
> > + *
> > + * Check current_work() to avoid flushing from the wq.
> > + */
> > + if (rx_mode_wq && !current_work())
> > + flush_workqueue(rx_mode_wq);
>
> Can we give the work a reference on the netdev (at init time) and
> cancel + release it here instead of flushing / waiting?
Not sure why cancel+release, maybe you're thinking about the unregister
path? This is rtnl_unlock -> netdev_run_todo -> __rtnl_unlock + some
extras.
And the flush is here to plumb the addresses to the real devices
before we return to the callers. Mostly because of the following
things we have in the tests:
# TEST: team cleanup mode lacp [FAIL]
# macvlan unicast address not found on a slave
Can you explain a bit more on the suggestion?
> > /* Wait for rcu callbacks to finish before next phase */
> > if (!list_empty(&list))
> > rcu_barrier();
> > @@ -12099,6 +12173,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
> > #endif
> >
> > mutex_init(&dev->lock);
> > + INIT_WORK(&dev->rx_mode_work, dev_rx_mode_work);
> >
> > dev->priv_flags = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM;
> > setup(dev);
> > @@ -12203,6 +12278,8 @@ void free_netdev(struct net_device *dev)
> >
> > kfree(rcu_dereference_protected(dev->ingress_queue, 1));
> >
> > + cancel_work_sync(&dev->rx_mode_work);
>
> Should never happen so maybe wrap it in a WARN ?
Or maybe just flush_workqueue here as well? To signal the intent that we
are mostly waiting for the wq entry to be unused to be able to kfree it?
^ permalink raw reply
* Re: [PATCH net-next v3 01/13] net: add address list snapshot and reconciliation infrastructure
From: Stanislav Fomichev @ 2026-03-24 18:13 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Stanislav Fomichev, netdev, davem, edumazet, pabeni, horms,
corbet, skhan, andrew+netdev, michael.chan, pavan.chebbi,
anthony.l.nguyen, przemyslaw.kitszel, saeedm, tariqt, mbloch,
alexanderduyck, kernel-team, johannes, sd, jianbol, dtatulea,
mohsin.bashr, jacob.e.keller, willemb, skhawaja, bestswngs,
aleksandr.loktionov, kees, linux-doc, linux-kernel,
intel-wired-lan, linux-rdma, linux-wireless, linux-kselftest,
leon
In-Reply-To: <20260323162053.62a148c2@kernel.org>
On 03/23, Jakub Kicinski wrote:
> On Thu, 19 Mar 2026 18:24:49 -0700 Stanislav Fomichev wrote:
> > +EXPORT_SYMBOL(__hw_addr_list_snapshot);
> > +EXPORT_SYMBOL(__hw_addr_list_reconcile);
>
> Why? For the kunit tests?
Yeah, no good reason, will remove!
^ permalink raw reply
* [PATCH v8 00/10] VMSCAPE optimization for BHI variant
From: Pawan Gupta @ 2026-03-24 18:16 UTC (permalink / raw)
To: x86, Jon Kohler, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Peter Zijlstra, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, KP Singh, Jiri Olsa, David S. Miller,
David Laight, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
David Ahern, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, Stanislav Fomichev, Hao Luo,
Paolo Bonzini, Jonathan Corbet
Cc: linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
v8:
- Use helper in KVM to convey the mitigation status. (PeterZ/Borisov)
- Fix the documentation for default vmscape mitigation. (BPF bot)
- Remove the stray lines in bug.c (BPF bot).
- Updated commit messages and comments.
- Rebased to v7.0-rc5.
v7: https://lore.kernel.org/r/20260319-vmscape-bhb-v7-0-b76a777a98af@linux.intel.com
- s/This allows/Allow/ and s/This does adds/This adds/ in patch 1/10 commit
message (Borislav).
- Minimize register usage in BHB clearing seq. (David Laight)
- Instead of separate ecx/eax counters, use al/ah.
- Adjust the alignment of RET due to register size change.
- save/restore rax in the seq itself.
- Remove the save/restore of rax/rcx for BPF callers.
- Rename clear_bhb_loop() to clear_bhb_loop_nofence() to make it
obvious that the LFENCE is not part of the sequence (Borislav).
- Fix Kconfig: s/select/depends on/ HAVE_STATIC_CALL (PeterZ).
- Rebased to v7.0-rc4.
v6: https://lore.kernel.org/r/20251201-vmscape-bhb-v6-0-d610dd515714@linux.intel.com
- Remove semicolon at the end of asm in ALTERNATIVE (Uros).
- Fix build warning in vmscape_select_mitigation() (LKP).
- Rebased to v6.18.
v5: https://lore.kernel.org/r/20251126-vmscape-bhb-v5-2-02d66e423b00@linux.intel.com
- For BHI seq, limit runtime-patching to loop counts only (Dave).
Dropped 2 patches that moved the BHB seq to a macro.
- Remove redundant switch cases in vmscape_select_mitigation() (Nikolay).
- Improve commit message (Nikolay).
- Collected tags.
v4: https://lore.kernel.org/r/20251119-vmscape-bhb-v4-0-1adad4e69ddc@linux.intel.com
- Move LFENCE to the callsite, out of clear_bhb_loop(). (Dave)
- Make clear_bhb_loop() work for larger BHB. (Dave)
This now uses hardware enumeration to determine the BHB size to clear.
- Use write_ibpb() instead of indirect_branch_prediction_barrier() when
IBPB is known to be available. (Dave)
- Use static_call() to simplify mitigation at exit-to-userspace. (Dave)
- Refactor vmscape_select_mitigation(). (Dave)
- Fix vmscape=on which was wrongly behaving as AUTO. (Dave)
- Split the patches. (Dave)
- Patch 1-4 prepares for making the sequence flexible for VMSCAPE use.
- Patch 5 trivial rename of variable.
- Patch 6-8 prepares for deploying BHB mitigation for VMSCAPE.
- Patch 9 deploys the mitigation.
- Patch 10-11 fixes ON Vs AUTO mode.
v3: https://lore.kernel.org/r/20251027-vmscape-bhb-v3-0-5793c2534e93@linux.intel.com
- s/x86_pred_flush_pending/x86_predictor_flush_exit_to_user/ (Sean).
- Removed IBPB & BHB-clear mutual exclusion at exit-to-userspace.
- Collected tags.
v2: https://lore.kernel.org/r/20251015-vmscape-bhb-v2-0-91cbdd9c3a96@linux.intel.com
- Added check for IBPB feature in vmscape_select_mitigation(). (David)
- s/vmscape=auto/vmscape=on/ (David)
- Added patch to remove LFENCE from VMSCAPE BHB-clear sequence.
- Rebased to v6.18-rc1.
v1: https://lore.kernel.org/r/20250924-vmscape-bhb-v1-0-da51f0e1934d@linux.intel.com
Hi All,
These patches aim to improve the performance of a recent mitigation for
VMSCAPE[1] vulnerability. This improvement is relevant for BHI variant of
VMSCAPE that affect Alder Lake and newer processors.
The current mitigation approach uses IBPB on kvm-exit-to-userspace for all
affected range of CPUs. This is an overkill for CPUs that are only affected
by the BHI variant. On such CPUs clearing the branch history is sufficient
for VMSCAPE, and also more apt as the underlying issue is due to poisoned
branch history.
Below is the iPerf data for transfer between guest and host, comparing IBPB
and BHB-clear mitigation. BHB-clear shows performance improvement over IBPB
in most cases.
Platform: Emerald Rapids
Baseline: vmscape=off
Target: IBPB at VMexit-to-userspace Vs the new BHB-clear at
VMexit-to-userspace mitigation (both compared against baseline).
(pN = N parallel connections)
| iPerf user-net | IBPB | BHB Clear |
|----------------|---------|-----------|
| UDP 1-vCPU_p1 | -12.5% | 1.3% |
| TCP 1-vCPU_p1 | -10.4% | -1.5% |
| TCP 1-vCPU_p1 | -7.5% | -3.0% |
| UDP 4-vCPU_p16 | -3.7% | -3.7% |
| TCP 4-vCPU_p4 | -2.9% | -1.4% |
| UDP 4-vCPU_p4 | -0.6% | 0.0% |
| TCP 4-vCPU_p4 | 3.5% | 0.0% |
| iPerf bridge-net | IBPB | BHB Clear |
|------------------|---------|-----------|
| UDP 1-vCPU_p1 | -9.4% | -0.4% |
| TCP 1-vCPU_p1 | -3.9% | -0.5% |
| UDP 4-vCPU_p16 | -2.2% | -3.8% |
| TCP 4-vCPU_p4 | -1.0% | -1.0% |
| TCP 4-vCPU_p4 | 0.5% | 0.5% |
| UDP 4-vCPU_p4 | 0.0% | 0.9% |
| TCP 1-vCPU_p1 | 0.0% | 0.9% |
| iPerf vhost-net | IBPB | BHB Clear |
|-----------------|---------|-----------|
| UDP 1-vCPU_p1 | -4.3% | 1.0% |
| TCP 1-vCPU_p1 | -3.8% | -0.5% |
| TCP 1-vCPU_p1 | -2.7% | -0.7% |
| UDP 4-vCPU_p16 | -0.7% | -2.2% |
| TCP 4-vCPU_p4 | -0.4% | 0.8% |
| UDP 4-vCPU_p4 | 0.4% | -0.7% |
| TCP 4-vCPU_p4 | 0.0% | 0.6% |
[1] https://comsec.ethz.ch/research/microarch/vmscape-exposing-and-exploiting-incomplete-branch-predictor-isolation-in-cloud-environments/
---
Pawan Gupta (10):
x86/bhi: x86/vmscape: Move LFENCE out of clear_bhb_loop()
x86/bhi: Make clear_bhb_loop() effective on newer CPUs
x86/bhi: Rename clear_bhb_loop() to clear_bhb_loop_nofence()
x86/vmscape: Rename x86_ibpb_exit_to_user to x86_predictor_flush_exit_to_user
x86/vmscape: Move mitigation selection to a switch()
x86/vmscape: Use write_ibpb() instead of indirect_branch_prediction_barrier()
x86/vmscape: Use static_call() for predictor flush
x86/vmscape: Deploy BHB clearing mitigation
x86/vmscape: Resolve conflict between attack-vectors and vmscape=force
x86/vmscape: Add cmdline vmscape=on to override attack vector controls
Documentation/admin-guide/hw-vuln/vmscape.rst | 15 ++++-
Documentation/admin-guide/kernel-parameters.txt | 6 +-
arch/x86/Kconfig | 1 +
arch/x86/entry/entry_64.S | 34 +++++++----
arch/x86/include/asm/cpufeatures.h | 2 +-
arch/x86/include/asm/entry-common.h | 9 ++-
arch/x86/include/asm/nospec-branch.h | 13 +++--
arch/x86/include/asm/processor.h | 1 +
arch/x86/kernel/cpu/bugs.c | 76 ++++++++++++++++++++-----
arch/x86/kvm/x86.c | 4 +-
arch/x86/net/bpf_jit_comp.c | 11 +---
11 files changed, 127 insertions(+), 45 deletions(-)
---
base-commit: c369299895a591d96745d6492d4888259b004a9e
change-id: 20250916-vmscape-bhb-d7d469977f2f
Best regards,
--
Thanks,
Pawan
^ permalink raw reply
* [PATCH v8 01/10] x86/bhi: x86/vmscape: Move LFENCE out of clear_bhb_loop()
From: Pawan Gupta @ 2026-03-24 18:16 UTC (permalink / raw)
To: x86, Jon Kohler, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Peter Zijlstra, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, KP Singh, Jiri Olsa, David S. Miller,
David Laight, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
David Ahern, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, Stanislav Fomichev, Hao Luo,
Paolo Bonzini, Jonathan Corbet
Cc: linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <20260324-vmscape-bhb-v8-0-68bb524b3ab9@linux.intel.com>
Currently, BHB clearing sequence is followed by an LFENCE to prevent
transient execution of subsequent indirect branches prematurely. However,
LFENCE barrier could be unnecessary in certain cases. For example, when
kernel is using BHI_DIS_S mitigation, and BHB clearing is only needed for
userspace. In such cases, LFENCE is redundant because ring transitions
would provide the necessary serialization.
Below is a quick recap of BHI mitigation options:
On Alder Lake and newer
- BHI_DIS_S: Hardware control to mitigate BHI in ring0. This has low
performance overhead.
- Long loop: Alternatively, longer version of BHB clearing sequence
can be used to mitigate BHI. It can also be used to mitigate
BHI variant of VMSCAPE. This is not yet implemented in
Linux.
On older CPUs
- Short loop: Clears BHB at kernel entry and VMexit. The "Long loop" is
effective on older CPUs as well, but should be avoided
because of unnecessary overhead.
On Alder Lake and newer CPUs, eIBRS isolates the indirect targets between
guest and host. But when affected by the BHI variant of VMSCAPE, a guest's
branch history may still influence indirect branches in userspace. This
also means the big hammer IBPB could be replaced with a cheaper option that
clears the BHB at exit-to-userspace after a VMexit.
In preparation for adding the support for BHB sequence (without LFENCE) on
newer CPUs, move the LFENCE to the caller side after clear_bhb_loop() is
executed. Allow callers to decide whether they need the LFENCE or
not. This adds a few extra bytes to the call sites, but it obviates
the need for multiple variants of clear_bhb_loop().
Suggested-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
---
arch/x86/entry/entry_64.S | 5 ++++-
arch/x86/include/asm/nospec-branch.h | 4 ++--
arch/x86/net/bpf_jit_comp.c | 2 ++
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 42447b1e1dff..3a180a36ca0e 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -1528,6 +1528,9 @@ SYM_CODE_END(rewind_stack_and_make_dead)
* refactored in the future if needed. The .skips are for safety, to ensure
* that all RETs are in the second half of a cacheline to mitigate Indirect
* Target Selection, rather than taking the slowpath via its_return_thunk.
+ *
+ * Note, callers should use a speculation barrier like LFENCE immediately after
+ * a call to this function to ensure BHB is cleared before indirect branches.
*/
SYM_FUNC_START(clear_bhb_loop)
ANNOTATE_NOENDBR
@@ -1562,7 +1565,7 @@ SYM_FUNC_START(clear_bhb_loop)
sub $1, %ecx
jnz 1b
.Lret2: RET
-5: lfence
+5:
pop %rbp
RET
SYM_FUNC_END(clear_bhb_loop)
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 4f4b5e8a1574..70b377fcbc1c 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -331,11 +331,11 @@
#ifdef CONFIG_X86_64
.macro CLEAR_BRANCH_HISTORY
- ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP
+ ALTERNATIVE "", "call clear_bhb_loop; lfence", X86_FEATURE_CLEAR_BHB_LOOP
.endm
.macro CLEAR_BRANCH_HISTORY_VMEXIT
- ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_VMEXIT
+ ALTERNATIVE "", "call clear_bhb_loop; lfence", X86_FEATURE_CLEAR_BHB_VMEXIT
.endm
#else
#define CLEAR_BRANCH_HISTORY
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index e9b78040d703..63d6c9fa5e80 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -1624,6 +1624,8 @@ static int emit_spectre_bhb_barrier(u8 **pprog, u8 *ip,
if (emit_call(&prog, func, ip))
return -EINVAL;
+ /* Don't speculate past this until BHB is cleared */
+ EMIT_LFENCE();
EMIT1(0x59); /* pop rcx */
EMIT1(0x58); /* pop rax */
}
--
2.34.1
^ permalink raw reply related
* [PATCH v8 02/10] x86/bhi: Make clear_bhb_loop() effective on newer CPUs
From: Pawan Gupta @ 2026-03-24 18:16 UTC (permalink / raw)
To: x86, Jon Kohler, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Peter Zijlstra, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, KP Singh, Jiri Olsa, David S. Miller,
David Laight, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
David Ahern, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, Stanislav Fomichev, Hao Luo,
Paolo Bonzini, Jonathan Corbet
Cc: linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <20260324-vmscape-bhb-v8-0-68bb524b3ab9@linux.intel.com>
As a mitigation for BHI, clear_bhb_loop() executes branches that overwrites
the Branch History Buffer (BHB). On Alder Lake and newer parts this
sequence is not sufficient because it doesn't clear enough entries. This
was not an issue because these CPUs have a hardware control (BHI_DIS_S)
that mitigates BHI in kernel.
BHI variant of VMSCAPE requires isolating branch history between guests and
userspace. Note that there is no equivalent hardware control for userspace.
To effectively isolate branch history on newer CPUs, clear_bhb_loop()
should execute sufficient number of branches to clear a larger BHB.
Dynamically set the loop count of clear_bhb_loop() such that it is
effective on newer CPUs too. Use the hardware control enumeration
X86_FEATURE_BHI_CTRL to select the appropriate loop count.
Suggested-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
---
arch/x86/entry/entry_64.S | 21 ++++++++++++++++-----
arch/x86/net/bpf_jit_comp.c | 7 -------
2 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 3a180a36ca0e..8128e00ca73f 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -1535,8 +1535,17 @@ SYM_CODE_END(rewind_stack_and_make_dead)
SYM_FUNC_START(clear_bhb_loop)
ANNOTATE_NOENDBR
push %rbp
+ /* BPF caller may require %rax to be preserved */
+ push %rax
mov %rsp, %rbp
- movl $5, %ecx
+
+ /*
+ * Between the long and short version of BHB clear sequence, just the
+ * loop count differs based on BHI_CTRL, see Intel's BHI guidance.
+ */
+ ALTERNATIVE "movb $5, %al", \
+ "movb $12, %al", X86_FEATURE_BHI_CTRL
+
ANNOTATE_INTRA_FUNCTION_CALL
call 1f
jmp 5f
@@ -1556,16 +1565,18 @@ SYM_FUNC_START(clear_bhb_loop)
* This should be ideally be: .skip 32 - (.Lret2 - 2f), 0xcc
* but some Clang versions (e.g. 18) don't like this.
*/
- .skip 32 - 18, 0xcc
-2: movl $5, %eax
+ .skip 32 - 14, 0xcc
+2: ALTERNATIVE "movb $5, %ah", \
+ "movb $7, %ah", X86_FEATURE_BHI_CTRL
3: jmp 4f
nop
-4: sub $1, %eax
+4: sub $1, %ah
jnz 3b
- sub $1, %ecx
+ sub $1, %al
jnz 1b
.Lret2: RET
5:
+ pop %rax
pop %rbp
RET
SYM_FUNC_END(clear_bhb_loop)
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 63d6c9fa5e80..e2cceabb23e8 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -1614,11 +1614,6 @@ static int emit_spectre_bhb_barrier(u8 **pprog, u8 *ip,
u8 *func;
if (cpu_feature_enabled(X86_FEATURE_CLEAR_BHB_LOOP)) {
- /* The clearing sequence clobbers eax and ecx. */
- EMIT1(0x50); /* push rax */
- EMIT1(0x51); /* push rcx */
- ip += 2;
-
func = (u8 *)clear_bhb_loop;
ip += x86_call_depth_emit_accounting(&prog, func, ip);
@@ -1626,8 +1621,6 @@ static int emit_spectre_bhb_barrier(u8 **pprog, u8 *ip,
return -EINVAL;
/* Don't speculate past this until BHB is cleared */
EMIT_LFENCE();
- EMIT1(0x59); /* pop rcx */
- EMIT1(0x58); /* pop rax */
}
/* Insert IBHF instruction */
if ((cpu_feature_enabled(X86_FEATURE_CLEAR_BHB_LOOP) &&
--
2.34.1
^ permalink raw reply related
* [PATCH v8 03/10] x86/bhi: Rename clear_bhb_loop() to clear_bhb_loop_nofence()
From: Pawan Gupta @ 2026-03-24 18:17 UTC (permalink / raw)
To: x86, Jon Kohler, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Peter Zijlstra, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, KP Singh, Jiri Olsa, David S. Miller,
David Laight, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
David Ahern, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, Stanislav Fomichev, Hao Luo,
Paolo Bonzini, Jonathan Corbet
Cc: linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <20260324-vmscape-bhb-v8-0-68bb524b3ab9@linux.intel.com>
To reflect the recent change that moved LFENCE to the caller side.
Suggested-by: Borislav Petkov <bp@alien8.de>
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
---
arch/x86/entry/entry_64.S | 8 ++++----
arch/x86/include/asm/nospec-branch.h | 6 +++---
arch/x86/net/bpf_jit_comp.c | 2 +-
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 8128e00ca73f..e9b81b95fcc8 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -1532,7 +1532,7 @@ SYM_CODE_END(rewind_stack_and_make_dead)
* Note, callers should use a speculation barrier like LFENCE immediately after
* a call to this function to ensure BHB is cleared before indirect branches.
*/
-SYM_FUNC_START(clear_bhb_loop)
+SYM_FUNC_START(clear_bhb_loop_nofence)
ANNOTATE_NOENDBR
push %rbp
/* BPF caller may require %rax to be preserved */
@@ -1579,6 +1579,6 @@ SYM_FUNC_START(clear_bhb_loop)
pop %rax
pop %rbp
RET
-SYM_FUNC_END(clear_bhb_loop)
-EXPORT_SYMBOL_FOR_KVM(clear_bhb_loop)
-STACK_FRAME_NON_STANDARD(clear_bhb_loop)
+SYM_FUNC_END(clear_bhb_loop_nofence)
+EXPORT_SYMBOL_FOR_KVM(clear_bhb_loop_nofence)
+STACK_FRAME_NON_STANDARD(clear_bhb_loop_nofence)
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 70b377fcbc1c..0f5e6ed6c9c2 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -331,11 +331,11 @@
#ifdef CONFIG_X86_64
.macro CLEAR_BRANCH_HISTORY
- ALTERNATIVE "", "call clear_bhb_loop; lfence", X86_FEATURE_CLEAR_BHB_LOOP
+ ALTERNATIVE "", "call clear_bhb_loop_nofence; lfence", X86_FEATURE_CLEAR_BHB_LOOP
.endm
.macro CLEAR_BRANCH_HISTORY_VMEXIT
- ALTERNATIVE "", "call clear_bhb_loop; lfence", X86_FEATURE_CLEAR_BHB_VMEXIT
+ ALTERNATIVE "", "call clear_bhb_loop_nofence; lfence", X86_FEATURE_CLEAR_BHB_VMEXIT
.endm
#else
#define CLEAR_BRANCH_HISTORY
@@ -389,7 +389,7 @@ extern void entry_untrain_ret(void);
extern void write_ibpb(void);
#ifdef CONFIG_X86_64
-extern void clear_bhb_loop(void);
+extern void clear_bhb_loop_nofence(void);
#endif
extern void (*x86_return_thunk)(void);
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index e2cceabb23e8..b57e9ab51c5d 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -1614,7 +1614,7 @@ static int emit_spectre_bhb_barrier(u8 **pprog, u8 *ip,
u8 *func;
if (cpu_feature_enabled(X86_FEATURE_CLEAR_BHB_LOOP)) {
- func = (u8 *)clear_bhb_loop;
+ func = (u8 *)clear_bhb_loop_nofence;
ip += x86_call_depth_emit_accounting(&prog, func, ip);
if (emit_call(&prog, func, ip))
--
2.34.1
^ permalink raw reply related
* [PATCH v8 04/10] x86/vmscape: Rename x86_ibpb_exit_to_user to x86_predictor_flush_exit_to_user
From: Pawan Gupta @ 2026-03-24 18:17 UTC (permalink / raw)
To: x86, Jon Kohler, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Peter Zijlstra, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, KP Singh, Jiri Olsa, David S. Miller,
David Laight, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
David Ahern, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, Stanislav Fomichev, Hao Luo,
Paolo Bonzini, Jonathan Corbet
Cc: linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <20260324-vmscape-bhb-v8-0-68bb524b3ab9@linux.intel.com>
With the upcoming changes x86_ibpb_exit_to_user will also be used when BHB
clearing sequence is used. Rename it cover both the cases.
No functional change.
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
---
arch/x86/include/asm/entry-common.h | 6 +++---
arch/x86/include/asm/nospec-branch.h | 2 +-
arch/x86/kernel/cpu/bugs.c | 4 ++--
arch/x86/kvm/x86.c | 2 +-
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/entry-common.h b/arch/x86/include/asm/entry-common.h
index ce3eb6d5fdf9..c45858db16c9 100644
--- a/arch/x86/include/asm/entry-common.h
+++ b/arch/x86/include/asm/entry-common.h
@@ -94,11 +94,11 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
*/
choose_random_kstack_offset(rdtsc());
- /* Avoid unnecessary reads of 'x86_ibpb_exit_to_user' */
+ /* Avoid unnecessary reads of 'x86_predictor_flush_exit_to_user' */
if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER) &&
- this_cpu_read(x86_ibpb_exit_to_user)) {
+ this_cpu_read(x86_predictor_flush_exit_to_user)) {
indirect_branch_prediction_barrier();
- this_cpu_write(x86_ibpb_exit_to_user, false);
+ this_cpu_write(x86_predictor_flush_exit_to_user, false);
}
}
#define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 0f5e6ed6c9c2..0a55b1c64741 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -533,7 +533,7 @@ void alternative_msr_write(unsigned int msr, u64 val, unsigned int feature)
: "memory");
}
-DECLARE_PER_CPU(bool, x86_ibpb_exit_to_user);
+DECLARE_PER_CPU(bool, x86_predictor_flush_exit_to_user);
static inline void indirect_branch_prediction_barrier(void)
{
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 83f51cab0b1e..47c020b80371 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -65,8 +65,8 @@ EXPORT_PER_CPU_SYMBOL_GPL(x86_spec_ctrl_current);
* be needed to before running userspace. That IBPB will flush the branch
* predictor content.
*/
-DEFINE_PER_CPU(bool, x86_ibpb_exit_to_user);
-EXPORT_PER_CPU_SYMBOL_GPL(x86_ibpb_exit_to_user);
+DEFINE_PER_CPU(bool, x86_predictor_flush_exit_to_user);
+EXPORT_PER_CPU_SYMBOL_GPL(x86_predictor_flush_exit_to_user);
u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index fd1c4a36b593..45d7cfedc507 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -11464,7 +11464,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
* may migrate to.
*/
if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER))
- this_cpu_write(x86_ibpb_exit_to_user, true);
+ this_cpu_write(x86_predictor_flush_exit_to_user, true);
/*
* Consume any pending interrupts, including the possible source of
--
2.34.1
^ permalink raw reply related
* [PATCH v8 05/10] x86/vmscape: Move mitigation selection to a switch()
From: Pawan Gupta @ 2026-03-24 18:17 UTC (permalink / raw)
To: x86, Jon Kohler, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Peter Zijlstra, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, KP Singh, Jiri Olsa, David S. Miller,
David Laight, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
David Ahern, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, Stanislav Fomichev, Hao Luo,
Paolo Bonzini, Jonathan Corbet
Cc: linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <20260324-vmscape-bhb-v8-0-68bb524b3ab9@linux.intel.com>
This ensures that all mitigation modes are explicitly handled, while
keeping the mitigation selection for each mode together. This also prepares
for adding BHB-clearing mitigation mode for VMSCAPE.
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
---
arch/x86/kernel/cpu/bugs.c | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 47c020b80371..68e2df3e3bf5 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -3084,17 +3084,33 @@ early_param("vmscape", vmscape_parse_cmdline);
static void __init vmscape_select_mitigation(void)
{
- if (!boot_cpu_has_bug(X86_BUG_VMSCAPE) ||
- !boot_cpu_has(X86_FEATURE_IBPB)) {
+ if (!boot_cpu_has_bug(X86_BUG_VMSCAPE)) {
vmscape_mitigation = VMSCAPE_MITIGATION_NONE;
return;
}
- if (vmscape_mitigation == VMSCAPE_MITIGATION_AUTO) {
- if (should_mitigate_vuln(X86_BUG_VMSCAPE))
+ if ((vmscape_mitigation == VMSCAPE_MITIGATION_AUTO) &&
+ !should_mitigate_vuln(X86_BUG_VMSCAPE))
+ vmscape_mitigation = VMSCAPE_MITIGATION_NONE;
+
+ switch (vmscape_mitigation) {
+ case VMSCAPE_MITIGATION_NONE:
+ break;
+
+ case VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER:
+ if (!boot_cpu_has(X86_FEATURE_IBPB))
+ vmscape_mitigation = VMSCAPE_MITIGATION_NONE;
+ break;
+
+ case VMSCAPE_MITIGATION_AUTO:
+ if (boot_cpu_has(X86_FEATURE_IBPB))
vmscape_mitigation = VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER;
else
vmscape_mitigation = VMSCAPE_MITIGATION_NONE;
+ break;
+
+ default:
+ break;
}
}
--
2.34.1
^ permalink raw reply related
* [PATCH v8 06/10] x86/vmscape: Use write_ibpb() instead of indirect_branch_prediction_barrier()
From: Pawan Gupta @ 2026-03-24 18:17 UTC (permalink / raw)
To: x86, Jon Kohler, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Peter Zijlstra, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, KP Singh, Jiri Olsa, David S. Miller,
David Laight, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
David Ahern, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, Stanislav Fomichev, Hao Luo,
Paolo Bonzini, Jonathan Corbet
Cc: linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <20260324-vmscape-bhb-v8-0-68bb524b3ab9@linux.intel.com>
indirect_branch_prediction_barrier() is a wrapper to write_ibpb(), which
also checks if the CPU supports IBPB. For VMSCAPE, call to
indirect_branch_prediction_barrier() is only possible when CPU supports
IBPB.
Simply call write_ibpb() directly to avoid unnecessary alternative
patching.
Suggested-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
---
arch/x86/include/asm/entry-common.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/entry-common.h b/arch/x86/include/asm/entry-common.h
index c45858db16c9..78b143673ca7 100644
--- a/arch/x86/include/asm/entry-common.h
+++ b/arch/x86/include/asm/entry-common.h
@@ -97,7 +97,7 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
/* Avoid unnecessary reads of 'x86_predictor_flush_exit_to_user' */
if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER) &&
this_cpu_read(x86_predictor_flush_exit_to_user)) {
- indirect_branch_prediction_barrier();
+ write_ibpb();
this_cpu_write(x86_predictor_flush_exit_to_user, false);
}
}
--
2.34.1
^ permalink raw reply related
* [PATCH v8 07/10] x86/vmscape: Use static_call() for predictor flush
From: Pawan Gupta @ 2026-03-24 18:18 UTC (permalink / raw)
To: x86, Jon Kohler, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Peter Zijlstra, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, KP Singh, Jiri Olsa, David S. Miller,
David Laight, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
David Ahern, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, Stanislav Fomichev, Hao Luo,
Paolo Bonzini, Jonathan Corbet
Cc: linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <20260324-vmscape-bhb-v8-0-68bb524b3ab9@linux.intel.com>
Adding more mitigation options at exit-to-userspace for VMSCAPE would
usually require a series of checks to decide which mitigation to use. In
this case, the mitigation is done by calling a function, which is decided
at boot. So, adding more feature flags and multiple checks can be avoided
by using static_call() to the mitigating function.
Replace the flag-based mitigation selector with a static_call(). This also
frees the existing X86_FEATURE_IBPB_EXIT_TO_USER.
Suggested-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
---
arch/x86/Kconfig | 1 +
arch/x86/include/asm/cpufeatures.h | 2 +-
arch/x86/include/asm/entry-common.h | 7 +++----
arch/x86/include/asm/nospec-branch.h | 3 +++
arch/x86/include/asm/processor.h | 1 +
arch/x86/kernel/cpu/bugs.c | 14 +++++++++++++-
arch/x86/kvm/x86.c | 2 +-
7 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index e2df1b147184..5b8def9ddb98 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2720,6 +2720,7 @@ config MITIGATION_TSA
config MITIGATION_VMSCAPE
bool "Mitigate VMSCAPE"
depends on KVM
+ depends on HAVE_STATIC_CALL
default y
help
Enable mitigation for VMSCAPE attacks. VMSCAPE is a hardware security
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index dbe104df339b..b4d529dd6d30 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -503,7 +503,7 @@
#define X86_FEATURE_TSA_SQ_NO (21*32+11) /* AMD CPU not vulnerable to TSA-SQ */
#define X86_FEATURE_TSA_L1_NO (21*32+12) /* AMD CPU not vulnerable to TSA-L1 */
#define X86_FEATURE_CLEAR_CPU_BUF_VM (21*32+13) /* Clear CPU buffers using VERW before VMRUN */
-#define X86_FEATURE_IBPB_EXIT_TO_USER (21*32+14) /* Use IBPB on exit-to-userspace, see VMSCAPE bug */
+/* Free */
#define X86_FEATURE_ABMC (21*32+15) /* Assignable Bandwidth Monitoring Counters */
#define X86_FEATURE_MSR_IMM (21*32+16) /* MSR immediate form instructions */
#define X86_FEATURE_SGX_EUPDATESVN (21*32+17) /* Support for ENCLS[EUPDATESVN] instruction */
diff --git a/arch/x86/include/asm/entry-common.h b/arch/x86/include/asm/entry-common.h
index 78b143673ca7..783e7cb50cae 100644
--- a/arch/x86/include/asm/entry-common.h
+++ b/arch/x86/include/asm/entry-common.h
@@ -4,6 +4,7 @@
#include <linux/randomize_kstack.h>
#include <linux/user-return-notifier.h>
+#include <linux/static_call_types.h>
#include <asm/nospec-branch.h>
#include <asm/io_bitmap.h>
@@ -94,10 +95,8 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
*/
choose_random_kstack_offset(rdtsc());
- /* Avoid unnecessary reads of 'x86_predictor_flush_exit_to_user' */
- if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER) &&
- this_cpu_read(x86_predictor_flush_exit_to_user)) {
- write_ibpb();
+ if (unlikely(this_cpu_read(x86_predictor_flush_exit_to_user))) {
+ static_call_cond(vmscape_predictor_flush)();
this_cpu_write(x86_predictor_flush_exit_to_user, false);
}
}
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 0a55b1c64741..e45e49f1e0c9 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -542,6 +542,9 @@ static inline void indirect_branch_prediction_barrier(void)
:: "rax", "rcx", "rdx", "memory");
}
+#include <linux/static_call_types.h>
+DECLARE_STATIC_CALL(vmscape_predictor_flush, write_ibpb);
+
/* The Intel SPEC CTRL MSR base value cache */
extern u64 x86_spec_ctrl_base;
DECLARE_PER_CPU(u64, x86_spec_ctrl_current);
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index a24c7805acdb..20ab4dd588c6 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -753,6 +753,7 @@ enum mds_mitigations {
};
extern bool gds_ucode_mitigated(void);
+extern bool vmscape_mitigation_enabled(void);
/*
* Make previous memory operations globally visible before
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 68e2df3e3bf5..a7dee7ec6ea3 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -144,6 +144,12 @@ EXPORT_SYMBOL_GPL(cpu_buf_idle_clear);
*/
DEFINE_STATIC_KEY_FALSE(switch_mm_cond_l1d_flush);
+/*
+ * Controls how vmscape is mitigated e.g. via IBPB or BHB-clear
+ * sequence. This defaults to no mitigation.
+ */
+DEFINE_STATIC_CALL_NULL(vmscape_predictor_flush, write_ibpb);
+
#undef pr_fmt
#define pr_fmt(fmt) "mitigations: " fmt
@@ -3129,8 +3135,14 @@ static void __init vmscape_update_mitigation(void)
static void __init vmscape_apply_mitigation(void)
{
if (vmscape_mitigation == VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER)
- setup_force_cpu_cap(X86_FEATURE_IBPB_EXIT_TO_USER);
+ static_call_update(vmscape_predictor_flush, write_ibpb);
+}
+
+bool vmscape_mitigation_enabled(void)
+{
+ return !!static_call_query(vmscape_predictor_flush);
}
+EXPORT_SYMBOL_FOR_KVM(vmscape_mitigation_enabled);
#undef pr_fmt
#define pr_fmt(fmt) fmt
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 45d7cfedc507..e204482e64f3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -11463,7 +11463,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
* set for the CPU that actually ran the guest, and not the CPU that it
* may migrate to.
*/
- if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER))
+ if (vmscape_mitigation_enabled())
this_cpu_write(x86_predictor_flush_exit_to_user, true);
/*
--
2.34.1
^ permalink raw reply related
* [PATCH v8 08/10] x86/vmscape: Deploy BHB clearing mitigation
From: Pawan Gupta @ 2026-03-24 18:18 UTC (permalink / raw)
To: x86, Jon Kohler, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Peter Zijlstra, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, KP Singh, Jiri Olsa, David S. Miller,
David Laight, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
David Ahern, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, Stanislav Fomichev, Hao Luo,
Paolo Bonzini, Jonathan Corbet
Cc: linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <20260324-vmscape-bhb-v8-0-68bb524b3ab9@linux.intel.com>
IBPB mitigation for VMSCAPE is an overkill on CPUs that are only affected
by the BHI variant of VMSCAPE. On such CPUs, eIBRS already provides
indirect branch isolation between guest and host userspace. However, branch
history from guest may also influence the indirect branches in host
userspace.
To mitigate the BHI aspect, use the BHB clearing sequence. Since now, IBPB
is not the only mitigation for VMSCAPE, update the documentation to reflect
that =auto could select either IBPB or BHB clear mitigation based on the
CPU.
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
---
Documentation/admin-guide/hw-vuln/vmscape.rst | 11 ++++++++-
Documentation/admin-guide/kernel-parameters.txt | 4 +++-
arch/x86/include/asm/nospec-branch.h | 2 ++
arch/x86/kernel/cpu/bugs.c | 30 +++++++++++++++++++------
4 files changed, 38 insertions(+), 9 deletions(-)
diff --git a/Documentation/admin-guide/hw-vuln/vmscape.rst b/Documentation/admin-guide/hw-vuln/vmscape.rst
index d9b9a2b6c114..7c40cf70ad7a 100644
--- a/Documentation/admin-guide/hw-vuln/vmscape.rst
+++ b/Documentation/admin-guide/hw-vuln/vmscape.rst
@@ -86,6 +86,10 @@ The possible values in this file are:
run a potentially malicious guest and issues an IBPB before the first
exit to userspace after VM-exit.
+ * 'Mitigation: Clear BHB before exit to userspace':
+
+ As above, conditional BHB clearing mitigation is enabled.
+
* 'Mitigation: IBPB on VMEXIT':
IBPB is issued on every VM-exit. This occurs when other mitigations like
@@ -102,9 +106,14 @@ The mitigation can be controlled via the ``vmscape=`` command line parameter:
* ``vmscape=ibpb``:
- Enable conditional IBPB mitigation (default when CONFIG_MITIGATION_VMSCAPE=y).
+ Enable conditional IBPB mitigation.
* ``vmscape=force``:
Force vulnerability detection and mitigation even on processors that are
not known to be affected.
+
+ * ``vmscape=auto``:
+
+ Choose the mitigation based on the VMSCAPE variant the CPU is affected by.
+ (default when CONFIG_MITIGATION_VMSCAPE=y)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 03a550630644..3853c7109419 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -8378,9 +8378,11 @@ Kernel parameters
off - disable the mitigation
ibpb - use Indirect Branch Prediction Barrier
- (IBPB) mitigation (default)
+ (IBPB) mitigation
force - force vulnerability detection even on
unaffected processors
+ auto - (default) use IBPB or BHB clear
+ mitigation based on CPU
vsyscall= [X86-64,EARLY]
Controls the behavior of vsyscalls (i.e. calls to
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index e45e49f1e0c9..7be812a73326 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -390,6 +390,8 @@ extern void write_ibpb(void);
#ifdef CONFIG_X86_64
extern void clear_bhb_loop_nofence(void);
+#else
+static inline void clear_bhb_loop_nofence(void) {}
#endif
extern void (*x86_return_thunk)(void);
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index a7dee7ec6ea3..8cacd9474fdf 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -61,9 +61,8 @@ DEFINE_PER_CPU(u64, x86_spec_ctrl_current);
EXPORT_PER_CPU_SYMBOL_GPL(x86_spec_ctrl_current);
/*
- * Set when the CPU has run a potentially malicious guest. An IBPB will
- * be needed to before running userspace. That IBPB will flush the branch
- * predictor content.
+ * Set when the CPU has run a potentially malicious guest. Indicates that a
+ * branch predictor flush is needed before running userspace.
*/
DEFINE_PER_CPU(bool, x86_predictor_flush_exit_to_user);
EXPORT_PER_CPU_SYMBOL_GPL(x86_predictor_flush_exit_to_user);
@@ -3056,13 +3055,15 @@ enum vmscape_mitigations {
VMSCAPE_MITIGATION_AUTO,
VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER,
VMSCAPE_MITIGATION_IBPB_ON_VMEXIT,
+ VMSCAPE_MITIGATION_BHB_CLEAR_EXIT_TO_USER,
};
static const char * const vmscape_strings[] = {
- [VMSCAPE_MITIGATION_NONE] = "Vulnerable",
+ [VMSCAPE_MITIGATION_NONE] = "Vulnerable",
/* [VMSCAPE_MITIGATION_AUTO] */
- [VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER] = "Mitigation: IBPB before exit to userspace",
- [VMSCAPE_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT",
+ [VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER] = "Mitigation: IBPB before exit to userspace",
+ [VMSCAPE_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT",
+ [VMSCAPE_MITIGATION_BHB_CLEAR_EXIT_TO_USER] = "Mitigation: Clear BHB before exit to userspace",
};
static enum vmscape_mitigations vmscape_mitigation __ro_after_init =
@@ -3080,6 +3081,8 @@ static int __init vmscape_parse_cmdline(char *str)
} else if (!strcmp(str, "force")) {
setup_force_cpu_bug(X86_BUG_VMSCAPE);
vmscape_mitigation = VMSCAPE_MITIGATION_AUTO;
+ } else if (!strcmp(str, "auto")) {
+ vmscape_mitigation = VMSCAPE_MITIGATION_AUTO;
} else {
pr_err("Ignoring unknown vmscape=%s option.\n", str);
}
@@ -3109,7 +3112,17 @@ static void __init vmscape_select_mitigation(void)
break;
case VMSCAPE_MITIGATION_AUTO:
- if (boot_cpu_has(X86_FEATURE_IBPB))
+ /*
+ * CPUs with BHI_CTRL(ADL and newer) can avoid the IBPB and use
+ * BHB clear sequence. These CPUs are only vulnerable to the BHI
+ * variant of the VMSCAPE attack, and thus they do not require a
+ * full predictor flush.
+ *
+ * Note, in 32-bit mode BHB clear sequence is not supported.
+ */
+ if (boot_cpu_has(X86_FEATURE_BHI_CTRL) && IS_ENABLED(CONFIG_X86_64))
+ vmscape_mitigation = VMSCAPE_MITIGATION_BHB_CLEAR_EXIT_TO_USER;
+ else if (boot_cpu_has(X86_FEATURE_IBPB))
vmscape_mitigation = VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER;
else
vmscape_mitigation = VMSCAPE_MITIGATION_NONE;
@@ -3136,6 +3149,8 @@ static void __init vmscape_apply_mitigation(void)
{
if (vmscape_mitigation == VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER)
static_call_update(vmscape_predictor_flush, write_ibpb);
+ else if (vmscape_mitigation == VMSCAPE_MITIGATION_BHB_CLEAR_EXIT_TO_USER)
+ static_call_update(vmscape_predictor_flush, clear_bhb_loop_nofence);
}
bool vmscape_mitigation_enabled(void)
@@ -3233,6 +3248,7 @@ void cpu_bugs_smt_update(void)
break;
case VMSCAPE_MITIGATION_IBPB_ON_VMEXIT:
case VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER:
+ case VMSCAPE_MITIGATION_BHB_CLEAR_EXIT_TO_USER:
/*
* Hypervisors can be attacked across-threads, warn for SMT when
* STIBP is not already enabled system-wide.
--
2.34.1
^ permalink raw reply related
* [PATCH v8 09/10] x86/vmscape: Resolve conflict between attack-vectors and vmscape=force
From: Pawan Gupta @ 2026-03-24 18:18 UTC (permalink / raw)
To: x86, Jon Kohler, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Peter Zijlstra, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, KP Singh, Jiri Olsa, David S. Miller,
David Laight, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
David Ahern, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, Stanislav Fomichev, Hao Luo,
Paolo Bonzini, Jonathan Corbet
Cc: linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <20260324-vmscape-bhb-v8-0-68bb524b3ab9@linux.intel.com>
vmscape=force option currently defaults to AUTO mitigation. This lets
attack-vector controls to override the vmscape mitigation. Preventing the
user from being able to force VMSCAPE mitigation.
When vmscape mitigation is forced, allow it be deployed irrespective of
attack vectors. Introduce VMSCAPE_MITIGATION_ON that wins over
attack-vector controls.
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
---
arch/x86/kernel/cpu/bugs.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 8cacd9474fdf..ba714f600249 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -3053,6 +3053,7 @@ static void __init srso_apply_mitigation(void)
enum vmscape_mitigations {
VMSCAPE_MITIGATION_NONE,
VMSCAPE_MITIGATION_AUTO,
+ VMSCAPE_MITIGATION_ON,
VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER,
VMSCAPE_MITIGATION_IBPB_ON_VMEXIT,
VMSCAPE_MITIGATION_BHB_CLEAR_EXIT_TO_USER,
@@ -3061,6 +3062,7 @@ enum vmscape_mitigations {
static const char * const vmscape_strings[] = {
[VMSCAPE_MITIGATION_NONE] = "Vulnerable",
/* [VMSCAPE_MITIGATION_AUTO] */
+ /* [VMSCAPE_MITIGATION_ON] */
[VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER] = "Mitigation: IBPB before exit to userspace",
[VMSCAPE_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT",
[VMSCAPE_MITIGATION_BHB_CLEAR_EXIT_TO_USER] = "Mitigation: Clear BHB before exit to userspace",
@@ -3080,7 +3082,7 @@ static int __init vmscape_parse_cmdline(char *str)
vmscape_mitigation = VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER;
} else if (!strcmp(str, "force")) {
setup_force_cpu_bug(X86_BUG_VMSCAPE);
- vmscape_mitigation = VMSCAPE_MITIGATION_AUTO;
+ vmscape_mitigation = VMSCAPE_MITIGATION_ON;
} else if (!strcmp(str, "auto")) {
vmscape_mitigation = VMSCAPE_MITIGATION_AUTO;
} else {
@@ -3112,6 +3114,7 @@ static void __init vmscape_select_mitigation(void)
break;
case VMSCAPE_MITIGATION_AUTO:
+ case VMSCAPE_MITIGATION_ON:
/*
* CPUs with BHI_CTRL(ADL and newer) can avoid the IBPB and use
* BHB clear sequence. These CPUs are only vulnerable to the BHI
@@ -3245,6 +3248,7 @@ void cpu_bugs_smt_update(void)
switch (vmscape_mitigation) {
case VMSCAPE_MITIGATION_NONE:
case VMSCAPE_MITIGATION_AUTO:
+ case VMSCAPE_MITIGATION_ON:
break;
case VMSCAPE_MITIGATION_IBPB_ON_VMEXIT:
case VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER:
--
2.34.1
^ permalink raw reply related
* [PATCH v8 10/10] x86/vmscape: Add cmdline vmscape=on to override attack vector controls
From: Pawan Gupta @ 2026-03-24 18:19 UTC (permalink / raw)
To: x86, Jon Kohler, Nikolay Borisov, H. Peter Anvin, Josh Poimboeuf,
David Kaplan, Sean Christopherson, Borislav Petkov, Dave Hansen,
Peter Zijlstra, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, KP Singh, Jiri Olsa, David S. Miller,
David Laight, Andy Lutomirski, Thomas Gleixner, Ingo Molnar,
David Ahern, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, Stanislav Fomichev, Hao Luo,
Paolo Bonzini, Jonathan Corbet
Cc: linux-kernel, kvm, Asit Mallick, Tao Zhang, bpf, netdev,
linux-doc
In-Reply-To: <20260324-vmscape-bhb-v8-0-68bb524b3ab9@linux.intel.com>
In general, individual mitigation knobs override the attack vector
controls. For VMSCAPE, =ibpb exists but nothing to select BHB clearing
mitigation. The =force option would select BHB clearing when supported, but
with a side-effect of also forcing the bug, hence deploying the mitigation
on unaffected parts too.
Add a new cmdline option vmscape=on to enable the mitigation based on the
VMSCAPE variant the CPU is affected by.
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
---
Documentation/admin-guide/hw-vuln/vmscape.rst | 4 ++++
Documentation/admin-guide/kernel-parameters.txt | 2 ++
arch/x86/kernel/cpu/bugs.c | 2 ++
3 files changed, 8 insertions(+)
diff --git a/Documentation/admin-guide/hw-vuln/vmscape.rst b/Documentation/admin-guide/hw-vuln/vmscape.rst
index 7c40cf70ad7a..a15d1bc91cce 100644
--- a/Documentation/admin-guide/hw-vuln/vmscape.rst
+++ b/Documentation/admin-guide/hw-vuln/vmscape.rst
@@ -117,3 +117,7 @@ The mitigation can be controlled via the ``vmscape=`` command line parameter:
Choose the mitigation based on the VMSCAPE variant the CPU is affected by.
(default when CONFIG_MITIGATION_VMSCAPE=y)
+
+ * ``vmscape=on``:
+
+ Same as `auto`, except that it overrides attack vector controls.
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 3853c7109419..98204d464477 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -8383,6 +8383,8 @@ Kernel parameters
unaffected processors
auto - (default) use IBPB or BHB clear
mitigation based on CPU
+ on - same as "auto", but override attack
+ vector control
vsyscall= [X86-64,EARLY]
Controls the behavior of vsyscalls (i.e. calls to
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index ba714f600249..84bf89ca278b 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -3083,6 +3083,8 @@ static int __init vmscape_parse_cmdline(char *str)
} else if (!strcmp(str, "force")) {
setup_force_cpu_bug(X86_BUG_VMSCAPE);
vmscape_mitigation = VMSCAPE_MITIGATION_ON;
+ } else if (!strcmp(str, "on")) {
+ vmscape_mitigation = VMSCAPE_MITIGATION_ON;
} else if (!strcmp(str, "auto")) {
vmscape_mitigation = VMSCAPE_MITIGATION_AUTO;
} else {
--
2.34.1
^ permalink raw reply related
* Re: [PATCH] cpufreq: CPPC: add autonomous mode boot parameter support
From: Pierre Gondois @ 2026-03-24 18:18 UTC (permalink / raw)
To: Sumit Gupta
Cc: linux-tegra, linux-kernel, linux-doc, zhenglifeng1, treding,
viresh.kumar, jonathanh, vsethi, ionela.voinescu, ksitaraman,
sanjayc, zhanjie9, nhartman, corbet, mochs, skhan, bbasu, rdunlap,
linux-pm, mario.limonciello, rafael
In-Reply-To: <20260317151053.2361475-1-sumitg@nvidia.com>
Hello Sumit,
On 3/17/26 16:10, Sumit Gupta wrote:
> Add kernel boot parameter 'cppc_cpufreq.auto_sel_mode' to enable CPPC
> autonomous performance selection on all CPUs at system startup without
> requiring runtime sysfs manipulation. When autonomous mode is enabled,
> the hardware automatically adjusts CPU performance based on workload
> demands using Energy Performance Preference (EPP) hints.
>
> When auto_sel_mode=1:
> - Configure all CPUs for autonomous operation on first init
> - Set EPP to performance preference (0x0)
> - Use HW min/max when set; otherwise program from policy limits (caps)
> - Clamp desired_perf to bounds before enabling autonomous mode
> - Hardware controls frequency instead of the OS governor
>
> The boot parameter is applied only during first policy initialization.
> On hotplug, skip applying it so that the user's runtime sysfs
> configuration is preserved.
>
> Reviewed-by: Randy Dunlap <rdunlap@infradead.org> (Documentation)
> Signed-off-by: Sumit Gupta <sumitg@nvidia.com>
> ---
> Part 1 [1] of this series was applied for 7.1 and present in next.
> Sending this patch as reworked version of 'patch 11' from [2] based
> on next.
>
> [1] https://lore.kernel.org/lkml/20260206142658.72583-1-sumitg@nvidia.com/
> [2] https://lore.kernel.org/lkml/20251223121307.711773-1-sumitg@nvidia.com/
> ---
> .../admin-guide/kernel-parameters.txt | 13 +++
> drivers/cpufreq/cppc_cpufreq.c | 84 +++++++++++++++++--
> 2 files changed, 92 insertions(+), 5 deletions(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index fa6171b5fdd5..de4b4c89edfe 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -1060,6 +1060,19 @@ Kernel parameters
> policy to use. This governor must be registered in the
> kernel before the cpufreq driver probes.
>
> + cppc_cpufreq.auto_sel_mode=
> + [CPU_FREQ] Enable ACPI CPPC autonomous performance
> + selection. When enabled, hardware automatically adjusts
> + CPU frequency on all CPUs based on workload demands.
> + In Autonomous mode, Energy Performance Preference (EPP)
> + hints guide hardware toward performance (0x0) or energy
> + efficiency (0xff).
> + Requires ACPI CPPC autonomous selection register support.
> + Format: <bool>
> + Default: 0 (disabled)
> + 0: use cpufreq governors
> + 1: enable if supported by hardware
> +
> cpu_init_udelay=N
> [X86,EARLY] Delay for N microsec between assert and de-assert
> of APIC INIT to start processors. This delay occurs
> diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
> index 5dfb109cf1f4..49c148b2a0a4 100644
> --- a/drivers/cpufreq/cppc_cpufreq.c
> +++ b/drivers/cpufreq/cppc_cpufreq.c
> @@ -28,6 +28,9 @@
>
> static struct cpufreq_driver cppc_cpufreq_driver;
>
> +/* Autonomous Selection boot parameter */
> +static bool auto_sel_mode;
> +
> #ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
> static enum {
> FIE_UNSET = -1,
> @@ -708,11 +711,74 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
> policy->cur = cppc_perf_to_khz(caps, caps->highest_perf);
> cpu_data->perf_ctrls.desired_perf = caps->highest_perf;
>
> - ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
> - if (ret) {
> - pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
> - caps->highest_perf, cpu, ret);
> - goto out;
> + /*
> + * Enable autonomous mode on first init if boot param is set.
> + * Check last_governor to detect first init and skip if auto_sel
> + * is already enabled.
> + */
If the goal is to set autosel only once at the driver init,
shouldn't this be done in cppc_cpufreq_init() ?
I understand that cpu_data doesn't exist yet in
cppc_cpufreq_init(), but this seems more appropriate to do
it there IMO.
This means the cpudata should be updated accordingly
in this cppc_cpufreq_cpu_init() function.
> + if (auto_sel_mode && policy->last_governor[0] == '\0' &&
> + !cpu_data->perf_ctrls.auto_sel) {
> + /* Enable CPPC - optional register, some platforms need it */
The documentation of the CPPC Enable Register is subject to
interpretation, but IIUC the field should be set to use the CPPC
controls, so I assume this should be set in cppc_cpufreq_init()
instead ?
> + ret = cppc_set_enable(cpu, true);
> + if (ret && ret != -EOPNOTSUPP)
> + pr_warn("Failed to enable CPPC for CPU%d (%d)\n", cpu, ret);
> +
> + /*
> + * Prefer HW min/max_perf when set; otherwise program from
> + * policy limits derived earlier from caps.
> + * Clamp desired_perf to bounds and sync policy->cur.
> + */
> + if (!cpu_data->perf_ctrls.min_perf || !cpu_data->perf_ctrls.max_perf)
The function doesn't seem to exist.
> + cppc_cpufreq_update_perf_limits(cpu_data, policy);
> +
> + cpu_data->perf_ctrls.desired_perf =
> + clamp_t(u32, cpu_data->perf_ctrls.desired_perf,
> + cpu_data->perf_ctrls.min_perf,
> + cpu_data->perf_ctrls.max_perf);
> +
> + policy->cur = cppc_perf_to_khz(caps,
> + cpu_data->perf_ctrls.desired_perf);
> +
Maybe this should also be done in cppc_cpufreq_init()
if the auto_sel_mode parameter is set ?
> + /* EPP is optional - some platforms may not support it */
> + ret = cppc_set_epp(cpu, CPPC_EPP_PERFORMANCE_PREF);
> + if (ret && ret != -EOPNOTSUPP)
> + pr_warn("Failed to set EPP for CPU%d (%d)\n", cpu, ret);
> + else if (!ret)
> + cpu_data->perf_ctrls.energy_perf = CPPC_EPP_PERFORMANCE_PREF;
> +
> + ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
> + if (ret) {
> + pr_debug("Err setting perf for autonomous mode CPU:%d ret:%d\n",
> + cpu, ret);
> + goto out;
> + }
> +
> + ret = cppc_set_auto_sel(cpu, true);
> + if (ret && ret != -EOPNOTSUPP) {
> + pr_warn("Failed autonomous config for CPU%d (%d)\n",
> + cpu, ret);
> + goto out;
> + }
> + if (!ret)
> + cpu_data->perf_ctrls.auto_sel = true;
> + }
> +
> + if (cpu_data->perf_ctrls.auto_sel) {
There is a patchset ongoing which tries to remove
setting policy->min/max from driver initialization.
Indeed, these values are only temporarily valid,
until the governor override them.
It is not sure yet the patch will be accepted though.
https://lore.kernel.org/lkml/20260317101753.2284763-4-pierre.gondois@arm.com/
> + /* Sync policy limits from HW when autonomous mode is active */
> + policy->min = cppc_perf_to_khz(caps,
> + cpu_data->perf_ctrls.min_perf ?:
> + caps->lowest_nonlinear_perf);
> + policy->max = cppc_perf_to_khz(caps,
> + cpu_data->perf_ctrls.max_perf ?:
> + caps->nominal_perf);
> + } else {
> + /* Normal mode: governors control frequency */
> + ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
> + if (ret) {
> + pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
> + caps->highest_perf, cpu, ret);
> + goto out;
> + }
> }
>
> cppc_cpufreq_cpu_fie_init(policy);
> @@ -1038,10 +1104,18 @@ static int __init cppc_cpufreq_init(void)
>
> static void __exit cppc_cpufreq_exit(void)
> {
> + unsigned int cpu;
> +
> + for_each_present_cpu(cpu)
> + cppc_set_auto_sel(cpu, false);
If the firmware has a default EPP value, it means that loading
and the unloading the driver will reset this default EPP value.
Maybe the initial EPP value and/or the auto_sel value should be
cached somewhere and restored on exit ?
I don't know if this is actually an issue, this is just to signal it.
> +
> cpufreq_unregister_driver(&cppc_cpufreq_driver);
> cppc_freq_invariance_exit();
> }
>
> +module_param(auto_sel_mode, bool, 0444);
> +MODULE_PARM_DESC(auto_sel_mode, "Enable CPPC autonomous performance selection at boot");
> +
> module_exit(cppc_cpufreq_exit);
> MODULE_AUTHOR("Ashwin Chaugule");
> MODULE_DESCRIPTION("CPUFreq driver based on the ACPI CPPC v5.0+ spec");
^ permalink raw reply
* Re: [PATCH v7 5/5] Documentation: laptops: Update documentation for uniwill laptops
From: Shuah Khan @ 2026-03-24 18:26 UTC (permalink / raw)
To: Werner Sembach, W_Armin, hansg, ilpo.jarvinen, Jonathan Corbet
Cc: platform-driver-x86, linux-kernel, linux-doc, Shuah Khan
In-Reply-To: <20260324180437.69594-6-wse@tuxedocomputers.com>
On 3/24/26 12:02, Werner Sembach wrote:
> Adds short description for two new sysfs entries, ctgp_offset and
> usb_c_power_priority, to the documentation of uniwill laptops.
>
> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> Reviewed-by: Armin Wolf <W_Armin@gmx.de>
> ---
> .../ABI/testing/sysfs-driver-uniwill-laptop | 25 +++++++++++++++++++
> .../admin-guide/laptops/uniwill-laptop.rst | 12 +++++++++
> 2 files changed, 37 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
> index 2df70792968f3..cba4138604601 100644
> --- a/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
> +++ b/Documentation/ABI/testing/sysfs-driver-uniwill-laptop
> @@ -51,3 +51,28 @@ Description:
>
> Reading this file returns the current status of the breathing animation
> functionality.
> +
> +What: /sys/bus/platform/devices/INOU0000:XX/ctgp_offset
> +Date: January 2026
> +KernelVersion: 7.0
> +Contact: Werner Sembach <wse@tuxedocomputers.com>
> +Description:
> + Allows userspace applications to set the configurable TGP offset on top of the base
> + TGP. Base TGP and max TGP and therefore the max cTGP offset are device specific.
> + Note that setting the maximal cTGP leaves no window open for Dynamic Boost,
> + effectively disabling that feature for the GPU to always be prioritized.
This sentence read a bit complex to me. Something like this might
make it easier to read?
"Note that setting cTGP to its maximum value effectively disables
Dynamic Boost for the GPU is always be prioritized.
Maybe elaborate what "leaves no window open for Dynamic Boost"
Rest looks good to me.
Reviewed-by: Shuah Khan <skhan@linuxfoundation.org>
thanks,
-- Shuah
^ permalink raw reply
* Re: [PATCH net-next v3 08/13] bnxt: use snapshot in bnxt_cfg_rx_mode
From: Stanislav Fomichev @ 2026-03-24 18:29 UTC (permalink / raw)
To: Michael Chan
Cc: Stanislav Fomichev, netdev, davem, edumazet, kuba, pabeni, horms,
corbet, skhan, andrew+netdev, pavan.chebbi, anthony.l.nguyen,
przemyslaw.kitszel, saeedm, tariqt, mbloch, alexanderduyck,
kernel-team, johannes, sd, jianbol, dtatulea, mohsin.bashr,
jacob.e.keller, willemb, skhawaja, bestswngs, aleksandr.loktionov,
kees, linux-doc, linux-kernel, intel-wired-lan, linux-rdma,
linux-wireless, linux-kselftest, leon
In-Reply-To: <CACKFLi=j7DO_d46jwZnmZ=OfmkoFA3AXUoX4nmF0tQuYt5Y3UQ@mail.gmail.com>
On 03/23, Michael Chan wrote:
> On Thu, Mar 19, 2026 at 6:25 PM Stanislav Fomichev <sdf@fomichev.me> wrote:
> >
> > With the introduction of ndo_set_rx_mode_async (as discussed in [0])
> > we can call bnxt_cfg_rx_mode directly. Convert bnxt_cfg_rx_mode to
> > use uc/mc snapshots and move its call in bnxt_sp_task to the
> > section that resets BNXT_STATE_IN_SP_TASK. Switch to direct call in
> > bnxt_set_rx_mode.
> >
> > 0: https://lore.kernel.org/netdev/CACKFLi=5vj8hPqEUKDd8RTw3au5G+zRgQEqjF+6NZnyoNm90KA@mail.gmail.com/
> >
> > Cc: Michael Chan <michael.chan@broadcom.com>
> > Cc: Pavan Chebbi <pavan.chebbi@broadcom.com>
> > Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
> > ---
> > drivers/net/ethernet/broadcom/bnxt/bnxt.c | 26 ++++++++++++++---------
> > 1 file changed, 16 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> > index 225217b32e4b..12265bd7fda4 100644
> > --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> > +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
> > @@ -11039,7 +11039,8 @@ static int bnxt_setup_nitroa0_vnic(struct bnxt *bp)
> > return rc;
> > }
> >
> > -static int bnxt_cfg_rx_mode(struct bnxt *);
> > +static int bnxt_cfg_rx_mode(struct bnxt *, struct netdev_hw_addr_list *,
> > + struct netdev_hw_addr_list *);
> > static bool bnxt_mc_list_updated(struct bnxt *, u32 *,
> > const struct netdev_hw_addr_list *);
> >
> > @@ -11135,7 +11136,7 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init)
> > vnic->rx_mask |= mask;
> > }
> >
> > - rc = bnxt_cfg_rx_mode(bp);
> > + rc = bnxt_cfg_rx_mode(bp, &bp->dev->uc, &bp->dev->mc);
> > if (rc)
> > goto err_out;
> >
> > @@ -13610,11 +13611,12 @@ static void bnxt_set_rx_mode(struct net_device *dev,
> > if (mask != vnic->rx_mask || uc_update || mc_update) {
> > vnic->rx_mask = mask;
> >
> > - bnxt_queue_sp_work(bp, BNXT_RX_MASK_SP_EVENT);
> > + bnxt_cfg_rx_mode(bp, uc, mc);
> > }
> > }
> >
> > -static int bnxt_cfg_rx_mode(struct bnxt *bp)
> > +static int bnxt_cfg_rx_mode(struct bnxt *bp, struct netdev_hw_addr_list *uc,
> > + struct netdev_hw_addr_list *mc)
> > {
> > struct net_device *dev = bp->dev;
> > struct bnxt_vnic_info *vnic = &bp->vnic_info[BNXT_VNIC_DEFAULT];
> > @@ -13623,7 +13625,7 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp)
> > bool uc_update;
> >
> > netif_addr_lock_bh(dev);
> > - uc_update = bnxt_uc_list_updated(bp, &dev->uc);
> > + uc_update = bnxt_uc_list_updated(bp, uc);
>
> Will the uc list snapshot change between bnxt_set_rx_mode() and
> bnxt_cfg_rx_mode() with the direct call now? In the original deferred
> update implementation, the uc list can change and that's why we check
> in both functions.
The snapshot is gonna be the same for bnxt_set_rx_mode->bnxt_cfg_rx_mode path.
So you're saying that it's ok to remove the one in bnxt_cfg_rx_mode
because it's called either from bnxt_set_rx_mode (with a new list) or,
explicitly, via the BNXT_RX_MASK_SP_EVENT retry mechanism (where we know
that we need to redo the updates anyway)?
This makes me wonder whether I need to push the retrying mechanism to
the core stack... Right now, if some of the allocations in wq handler
fail, we just give up, maybe I should handle it better. And I can plug
the signal from the driver (make ndo_set_rx_mode_async return int)
in the same retry mechanism.
^ permalink raw reply
* Re: [PATCH v3 1/2] tracing: preserve repeated boot-time tracing parameters
From: Steven Rostedt @ 2026-03-24 18:43 UTC (permalink / raw)
To: Wesley Atwell
Cc: mhiramat, mark.rutland, mathieu.desnoyers, corbet, skhan,
linux-doc, linux-kernel, linux-trace-kernel
In-Reply-To: <20260310064715.527906-2-atwellwea@gmail.com>
On Tue, 10 Mar 2026 00:47:14 -0600
Wesley Atwell <atwellwea@gmail.com> wrote:
Hi,
FYI, the tracing subsystem uses capital letters in subjects:
tracing: Preserve repeated boot-time tracing parameters
> Some tracing boot parameters already accept delimited value lists, but
> their __setup() handlers keep only the last instance seen at boot.
> Make repeated instances append to the same boot-time buffer in the
> format each parser already consumes, and document that behavior in
> admin-guide/kernel-parameters.txt.
>
> Use a shared trace_append_boot_param() helper for the ftrace filters,
> trace_options, and kprobe_event boot parameters. trace_trigger=
> tokenizes its backing storage in place, so keep a running offset and
> only parse the newly appended chunk into bootup_triggers[].
>
> This also lets Bootconfig array values work naturally when they expand
> to repeated param=value entries.
>
> Signed-off-by: Wesley Atwell <atwellwea@gmail.com>
> ---
> .../admin-guide/kernel-parameters.txt | 18 ++++++++++--
> kernel/trace/ftrace.c | 12 +++++---
> kernel/trace/trace.c | 3 +-
> kernel/trace/trace.h | 29 +++++++++++++++++++
> kernel/trace/trace_events.c | 26 +++++++++++++++--
> kernel/trace/trace_kprobe.c | 3 +-
> 6 files changed, 79 insertions(+), 12 deletions(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 55ffc0f8858a..203863c1839b 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -1803,13 +1803,15 @@ Kernel parameters
> tracer at boot up. function-list is a comma-separated
> list of functions. This list can be changed at run
> time by the set_ftrace_filter file in the debugfs
> - tracing directory.
> + tracing directory. Repeated instances append more
> + functions to the same list.
>
> ftrace_notrace=[function-list]
> [FTRACE] Do not trace the functions specified in
> function-list. This list can be changed at run time
> by the set_ftrace_notrace file in the debugfs
> - tracing directory.
> + tracing directory. Repeated instances append more
> + functions to the same list.
>
> ftrace_graph_filter=[function-list]
> [FTRACE] Limit the top level callers functions traced
> @@ -1817,12 +1819,16 @@ Kernel parameters
> function-list is a comma-separated list of functions
> that can be changed at run time by the
> set_graph_function file in the debugfs tracing directory.
> + Repeated instances append more functions to the same
> + list.
>
> ftrace_graph_notrace=[function-list]
> [FTRACE] Do not trace from the functions specified in
> function-list. This list is a comma-separated list of
> functions that can be changed at run time by the
> set_graph_notrace file in the debugfs tracing directory.
> + Repeated instances append more functions to the same
> + list.
>
> ftrace_graph_max_depth=<uint>
> [FTRACE] Used with the function graph tracer. This is
> @@ -3053,6 +3059,8 @@ Kernel parameters
> The probe-list is a semicolon delimited list of probe
> definitions. Each definition is same as kprobe_events
> interface, but the parameters are comma delimited.
> + Repeated instances append more probe definitions to
> + the same boot-time list.
> For example, to add a kprobe event on vfs_read with
> arg1 and arg2, add to the command line;
>
> @@ -7820,6 +7828,9 @@ Kernel parameters
>
> /sys/kernel/tracing/trace_options
>
> + Repeated instances append more options to the same
> + boot-time list.
> +
> For example, to enable stacktrace option (to dump the
> stack trace of each event), add to the command line:
>
> @@ -7831,7 +7842,8 @@ Kernel parameters
> trace_trigger=[trigger-list]
> [FTRACE] Add an event trigger on specific events.
> Set a trigger on top of a specific event, with an optional
> - filter.
> + filter. Repeated instances append more triggers to
> + the same boot-time list.
I know Masami mentioned to document this, but honestly, I don't think this
update is needed. Please remove it.
>
> The format is "trace_trigger=<event>.<trigger>[ if <filter>],..."
> Where more than one trigger may be specified that are comma delimited.
> diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
> index 8df69e702706..d0a486b63ed6 100644
> --- a/kernel/trace/ftrace.c
> +++ b/kernel/trace/ftrace.c
> @@ -6841,7 +6841,8 @@ bool ftrace_filter_param __initdata;
> static int __init set_ftrace_notrace(char *str)
> {
> ftrace_filter_param = true;
> - strscpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);
> + trace_append_boot_param(ftrace_notrace_buf, str, ',',
> + FTRACE_FILTER_SIZE);
> return 1;
> }
> __setup("ftrace_notrace=", set_ftrace_notrace);
> @@ -6849,7 +6850,8 @@ __setup("ftrace_notrace=", set_ftrace_notrace);
> static int __init set_ftrace_filter(char *str)
> {
> ftrace_filter_param = true;
> - strscpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);
> + trace_append_boot_param(ftrace_filter_buf, str, ',',
> + FTRACE_FILTER_SIZE);
> return 1;
> }
> __setup("ftrace_filter=", set_ftrace_filter);
> @@ -6861,14 +6863,16 @@ static int ftrace_graph_set_hash(struct ftrace_hash *hash, char *buffer);
>
> static int __init set_graph_function(char *str)
> {
> - strscpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
> + trace_append_boot_param(ftrace_graph_buf, str, ',',
> + FTRACE_FILTER_SIZE);
> return 1;
> }
> __setup("ftrace_graph_filter=", set_graph_function);
>
> static int __init set_graph_notrace_function(char *str)
> {
> - strscpy(ftrace_graph_notrace_buf, str, FTRACE_FILTER_SIZE);
> + trace_append_boot_param(ftrace_graph_notrace_buf, str, ',',
> + FTRACE_FILTER_SIZE);
> return 1;
> }
> __setup("ftrace_graph_notrace=", set_graph_notrace_function);
> diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
> index ebd996f8710e..5086239a75dc 100644
> --- a/kernel/trace/trace.c
> +++ b/kernel/trace/trace.c
> @@ -329,7 +329,8 @@ static char trace_boot_options_buf[MAX_TRACER_SIZE] __initdata;
>
> static int __init set_trace_boot_options(char *str)
> {
> - strscpy(trace_boot_options_buf, str, MAX_TRACER_SIZE);
> + trace_append_boot_param(trace_boot_options_buf, str, ',',
> + MAX_TRACER_SIZE);
> return 1;
> }
> __setup("trace_options=", set_trace_boot_options);
> diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
> index b8f3804586a0..4f5abac4bd19 100644
> --- a/kernel/trace/trace.h
> +++ b/kernel/trace/trace.h
> @@ -23,6 +23,7 @@
> #include <linux/once_lite.h>
> #include <linux/ftrace_regs.h>
> #include <linux/llist.h>
> +#include <linux/string.h>
>
> #include "pid_list.h"
>
> @@ -262,6 +263,34 @@ static inline bool still_need_pid_events(int type, struct trace_pid_list *pid_li
> (!(type & TRACE_NO_PIDS) && no_pid_list);
> }
>
> +/*
> + * Repeated boot parameters, including Bootconfig array expansions, need
> + * to stay in the delimiter form that the existing parser consumes.
> + */
> +static inline void __init trace_append_boot_param(char *buf, const char *str,
> + char sep, size_t size)
> +{
Masami said:
Please make a generic append function in kernel/trace/trace.h, e.g.
void trace_append_boot_param(char *buf, const char *str, char sep, size_t ssize);
and use it instead of strscpy.
He did not say to make a static inline in the header. Please make this a
normal function in trace.c and just add the prototype in the header.
-- Steve
> + size_t len, str_len;
> +
> + if (buf[0] == '\0') {
> + strscpy(buf, str, size);
> + return;
> + }
> +
> + str_len = strlen(str);
> + if (!str_len)
> + return;
> +
> + len = strlen(buf);
> + if (len >= size - 1)
> + return;
> + if (str_len >= size - len - 1)
> + return;
> +
> + buf[len] = sep;
> + strscpy(buf + len + 1, str, size - len - 1);
> +}
> +
> typedef bool (*cond_update_fn_t)(struct trace_array *tr, void *cond_data);
>
> /**
> diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
> index 249d1cba72c0..5f72be33f2d1 100644
> --- a/kernel/trace/trace_events.c
> +++ b/kernel/trace/trace_events.c
> @@ -3679,20 +3679,40 @@ static struct boot_triggers {
> } bootup_triggers[MAX_BOOT_TRIGGERS];
>
> static char bootup_trigger_buf[COMMAND_LINE_SIZE];
> +static size_t bootup_trigger_buf_len;
> static int nr_boot_triggers;
>
> static __init int setup_trace_triggers(char *str)
> {
> char *trigger;
> char *buf;
> + size_t start, str_len;
> int i;
>
> - strscpy(bootup_trigger_buf, str, COMMAND_LINE_SIZE);
> + if (bootup_trigger_buf_len >= COMMAND_LINE_SIZE)
> + return 1;
> +
> + start = bootup_trigger_buf_len;
> + if (start && !*str)
> + return 1;
> +
> + str_len = strlen(str);
> + if (start && str_len >= COMMAND_LINE_SIZE - start)
> + return 1;
> +
> + /*
> + * trace_trigger= parsing tokenizes the backing storage in place.
> + * Copy each repeated parameter into fresh space and only parse that
> + * newly copied chunk here.
> + */
> + trace_append_boot_param(bootup_trigger_buf + start, str, '\0',
> + COMMAND_LINE_SIZE - start);
> + bootup_trigger_buf_len += strlen(bootup_trigger_buf + start) + 1;
> trace_set_ring_buffer_expanded(NULL);
> disable_tracing_selftest("running event triggers");
>
> - buf = bootup_trigger_buf;
> - for (i = 0; i < MAX_BOOT_TRIGGERS; i++) {
> + buf = bootup_trigger_buf + start;
> + for (i = nr_boot_triggers; i < MAX_BOOT_TRIGGERS; i++) {
> trigger = strsep(&buf, ",");
> if (!trigger)
> break;
> diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
> index a5dbb72528e0..e9f1c55aea64 100644
> --- a/kernel/trace/trace_kprobe.c
> +++ b/kernel/trace/trace_kprobe.c
> @@ -31,7 +31,8 @@ static char kprobe_boot_events_buf[COMMAND_LINE_SIZE] __initdata;
>
> static int __init set_kprobe_boot_events(char *str)
> {
> - strscpy(kprobe_boot_events_buf, str, COMMAND_LINE_SIZE);
> + trace_append_boot_param(kprobe_boot_events_buf, str, ';',
> + COMMAND_LINE_SIZE);
> disable_tracing_selftest("running kprobe events");
>
> return 1;
^ permalink raw reply
* Re: [PATCH 1/2] kallsyms: show function parameter info in oops/WARN dumps
From: Sasha Levin @ 2026-03-24 18:44 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Andrew Morton, Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Peter Zijlstra, Josh Poimboeuf, Petr Mladek,
Alexei Starovoitov, Jonathan Corbet, David Gow, Kees Cook,
Greg KH, Luis Chamberlain, Steven Rostedt, Helge Deller,
Randy Dunlap, Geert Uytterhoeven, Juergen Gross, James Bottomley,
Alexey Dobriyan, Vlastimil Babka, Laurent Pinchart, Petr Pavlu,
X86 ML, LKML, Linux Kbuild mailing list, open list:DOCUMENTATION,
linux-modules, bpf
In-Reply-To: <CAADnVQLr5Sx+vG6D4Jxm8r2vPxu7ygFz60LGwmqfkc=VB0-Miw@mail.gmail.com>
On Tue, Mar 24, 2026 at 09:04:03AM -0700, Alexei Starovoitov wrote:
>On Tue, Mar 24, 2026 at 9:00 AM Sasha Levin <sashal@kernel.org> wrote:
>>
>> On Tue, Mar 24, 2026 at 08:03:30AM -0700, Alexei Starovoitov wrote:
>> >On Mon, Mar 23, 2026 at 9:49 AM Sasha Levin <sashal@kernel.org> wrote:
>> >>
>> >> Embed DWARF-derived function parameter name and type information in the
>> >> kernel image so that oops and WARN dumps display the crashing function's
>> >> register-passed arguments with their names, types, and values.
>> >>
>> >> A new build-time tool (scripts/gen_paraminfo.c) parses DW_TAG_subprogram
>> >> and DW_TAG_formal_parameter entries from DWARF .debug_info, extracting
>> >> parameter names and human-readable type strings. The resulting tables are
>> >> stored in .rodata using the same two-phase link approach as lineinfo.
>> >>
>> >> At runtime, kallsyms_show_paraminfo() performs a binary search on the
>> >> paraminfo tables, maps parameters to x86-64 calling convention registers
>> >> (RDI, RSI, RDX, RCX, R8, R9), and prints each parameter's name, type,
>> >> and value from pt_regs. If a parameter value matches the page fault
>> >> address (CR2), it is highlighted with "<-- fault address".
>> >>
>> >> Integration at show_regs() means this works for both oops and WARN()
>> >> automatically, since both paths provide full pt_regs at the exception
>> >> point.
>> >>
>> >> Example output:
>> >>
>> >> Function parameters (ext4_readdir):
>> >> file (struct file *) = 0xffff888123456000
>> >> ctx (struct dir_context *) = 0x0000000000001234 <-- fault address
>> >>
>> >> Gated behind CONFIG_KALLSYMS_PARAMINFO (depends on CONFIG_KALLSYMS_LINEINFO).
>> >> Adds approximately 1-2 MB to the kernel image for ~58K functions.
>> >>
>> >> Assisted-by: Claude:claude-opus-4-6
>> >> Signed-off-by: Sasha Levin <sashal@kernel.org>
>> >
>> >Nack.
>> >
>> >You asked claude to reinvent pahole and BTF and it did it
>> >completely missing years of fine tuning that pahole does.
>>
>> Let's keep this on the technical side please.
>>
>> >dwarf cannot be trusted as-is. pahole converts it carefully
>> >by analyzing optimized out arguments and dropping signatures
>>
>> Fair point about pahole and optimized-out args. The problem is that BTF depends
>> on BPF_SYSCALL, and the environments I care about can't enable either.
>
>This is trivially fixable without reinventing pahole.
Hmm...
Looking at the code, I'd need to:
- Split BTF parsing from kernel/bpf/btf.c to somewhere outside of kernel/bpf/.
- New init path for btf_vmlinux outside BPF verifier.
- Refactor btf_parse_vmlinux() BPF-specific bits.
- Remove BPF_SYSCALL dependency from DEBUG_INFO_BTF.
- Somehow make BTF work with DEBUG_INFO_REDUCED.
I suppose that the first 4 are straightforward, but I don't have an idea about
DEBUG_INFO_REDUCED. Though we can probably tackle it later.
Does that make sense? Did I miss anything?
--
Thanks,
Sasha
^ permalink raw reply
* Re: [PATCH] docs: Document pahole v1.26 requirement for KF_IMPLICIT_ARGS kfuncs
From: zhidao su @ 2026-03-24 18:46 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Jonathan Corbet, linux-doc, linux-kernel, sched-ext, bpf
In-Reply-To: <CAADnVQLbtuD=7mtGZFR25ULhjZ-3ifBpkyRcqu9jPSd2Mt3fBw@mail.gmail.com>
On Tue, 24 Mar 2026 08:12:12 -0700, Alexei Starovoitov wrote:
> I don't think that's true.
> At least when implicit args were designed the goal was to avoid
> pahole dependencies.
> Please share exact steps to reproduce.
Here are the exact reproduction steps and code path analysis.
Reproduction (Ubuntu 24.04, pahole v1.25):
$ git clone https://github.com/sched-ext/sched_ext.git
$ cd sched_ext && make -j$(nproc) LOCALVERSION=-test
$ make -C tools/testing/selftests/sched_ext
$ vng --run arch/x86/boot/bzImage --cpus 4 --memory 4G -- \
tools/testing/selftests/sched_ext/build/runner 2>&1 | grep "func_proto"
Result: 23/30 tests fail with:
libbpf: extern (func ksym) 'scx_bpf_create_dsq': func_proto [382]
incompatible with vmlinux [53813]
Root cause:
The KF_IMPLICIT_ARGS mechanism requires pahole v1.26 for the DECL_TAG
generation step that enables resolve_btfids to do its btf2btf work:
1. scripts/Makefile.btf gates decl_tag_kfuncs on pahole >= 1.26:
pahole-flags-$(call test-ge, $(pahole-ver), 126) = ... decl_tag_kfuncs
2. Without decl_tag_kfuncs, pahole does not emit DECL_TAG BTF entries
for __bpf_kfunc-annotated functions.
3. resolve_btfids/main.c::collect_kfuncs() (line 1002) early-returns
when nr_decl_tags == 0:
if (!link->nr_decl_tags)
return 0;
4. With no bpf_kfunc DECL_TAGs, btf2btf() never calls
process_kfunc_with_implicit_args() to create _impl variants and
strip 'aux' from the original proto.
5. Result: vmlinux retains the 3-param proto (with 'aux') for all
KF_IMPLICIT_ARGS kfuncs.
BTF evidence from our pahole v1.25-compiled vmlinux:
$ bpftool btf dump file vmlinux | grep -A5 '[53813]'
[53813] FUNC_PROTO '(anon)' ret_type_id=... vlen=3
'dsq_id' type_id=...
'node' type_id=...
'aux' type_id=... <-- implicit arg still present, 3-param
(no scx_bpf_create_dsq_impl exists)
With pahole v1.26, resolve_btfids creates scx_bpf_create_dsq_impl
(3-param, for verifier's find_kfunc_impl_proto) and rewrites
scx_bpf_create_dsq to 2-param (for libbpf ksym matching).
You're right that the design goal was to avoid pahole dependencies -
the implementation could be fixed in resolve_btfids to handle the
no-DECL_TAG case. But until such a fix lands, the dependency exists
in practice. Jonathan Corbet suggested raising the minimum version in
the requirements table to 1.26, which seems the cleanest fix.
Signed-off-by: zhidao su <suzhidao@xiaomi.com>
^ permalink raw reply
* [PATCH] docs: Raise minimum pahole version to 1.26 for KF_IMPLICIT_ARGS kfuncs
From: zhidao su @ 2026-03-24 18:47 UTC (permalink / raw)
To: linux-doc
Cc: corbet, linux-kernel, sched-ext, bpf, alexei.starovoitov, tj,
zhidao su
In-Reply-To: <CAADnVQLbtuD=7mtGZFR25ULhjZ-3ifBpkyRcqu9jPSd2Mt3fBw@mail.gmail.com>
Since Linux 7.0, kfuncs annotated with KF_IMPLICIT_ARGS require pahole
v1.26 or later. Without it, such kfuncs will have incorrect BTF
prototypes in vmlinux, causing BPF programs to fail to load with a
"func_proto incompatible with vmlinux" error. Many sched_ext kfuncs
are affected (e.g. scx_bpf_create_dsq, scx_bpf_kick_cpu).
The root cause: scripts/Makefile.btf passes --btf_features=decl_tag_kfuncs
to pahole only when pahole >= 1.26. Without that flag, pahole emits no
DECL_TAG BTF entries for __bpf_kfunc-annotated functions. As a result,
resolve_btfids/main.c::collect_kfuncs() finds no bpf_kfunc DECL_TAGs,
short-circuits at line 1002, and btf2btf() never creates the _impl
variants or strips the implicit 'aux' argument from the visible proto.
The vmlinux BTF retains the 3-param prototype while BPF programs declare
the 2-param version, triggering the mismatch.
Raise the minimum version in the requirements table from 1.22 to 1.26
and add a note explaining the failure mode, so users understand why
their BPF programs fail on distributions shipping pahole v1.25 (e.g.
Ubuntu 24.04 LTS).
Suggested-by: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: zhidao su <suzhidao@xiaomi.com>
---
Documentation/process/changes.rst | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst
index 6b373e193548..02068d72a101 100644
--- a/Documentation/process/changes.rst
+++ b/Documentation/process/changes.rst
@@ -38,7 +38,7 @@ bash 4.2 bash --version
binutils 2.30 ld -v
flex 2.5.35 flex --version
bison 2.0 bison --version
-pahole 1.22 pahole --version
+pahole 1.26 pahole --version
util-linux 2.10o mount --version
kmod 13 depmod -V
e2fsprogs 1.41.4 e2fsck -V
@@ -145,6 +145,11 @@ Since Linux 5.2, if CONFIG_DEBUG_INFO_BTF is selected, the build system
generates BTF (BPF Type Format) from DWARF in vmlinux, a bit later from kernel
modules as well. This requires pahole v1.22 or later.
+Since Linux 7.0, kfuncs annotated with KF_IMPLICIT_ARGS require pahole v1.26
+or later. Without it, such kfuncs will have incorrect BTF prototypes in
+vmlinux, causing BPF programs to fail to load with a "func_proto incompatible
+with vmlinux" error. Many sched_ext kfuncs are affected.
+
It is found in the 'dwarves' or 'pahole' distro packages or from
https://fedorapeople.org/~acme/dwarves/.
--
2.43.0
^ permalink raw reply related
* [PATCH net-next 0/3] net: bridge: add stp_mode attribute for STP mode selection
From: Andy Roulin @ 2026-03-24 18:49 UTC (permalink / raw)
To: netdev
Cc: bridge, Nikolay Aleksandrov, Ido Schimmel, Andrew Lunn,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Jonathan Corbet, Shuah Khan, Petr Machata,
linux-doc, linux-kselftest, linux-kernel, Andy Roulin
The bridge-stp usermode helper is currently restricted to the initial
network namespace, preventing userspace STP daemons like mstpd from
operating on bridges in other namespaces. Since commit ff62198553e4
("bridge: Only call /sbin/bridge-stp for the initial network
namespace"), bridges in non-init namespaces silently fall back to
kernel STP with no way to request userspace STP.
This series adds a new IFLA_BR_STP_MODE bridge attribute that allows
explicit per-bridge control over STP mode selection. Three modes are
supported:
- auto (default): existing behavior, try /sbin/bridge-stp in
init_net, fall back to kernel STP otherwise
- user: directly enable BR_USER_STP without invoking the helper,
works in any network namespace
- kernel: directly enable BR_KERNEL_STP without invoking the helper
The user and kernel modes bypass call_usermodehelper() entirely,
addressing the security concerns discussed at [1]. The caller is
responsible for managing the userspace STP daemon directly, rather
than relying on the kernel to invoke /sbin/bridge-stp.
Patch 1 adds the kernel support. The mode can only be changed while
STP is disabled and is processed before IFLA_BR_STP_STATE in
br_changelink() so both can be set atomically in a single netlink
message.
Patch 2 adds documentation for the new attribute in the bridge docs.
Patch 3 adds a selftest with 8 test cases. The test requires iproute2
with IFLA_BR_STP_MODE support and can be run with virtme-ng:
vng --run arch/x86/boot/bzImage --skip-modules \
--overlay-rwdir /sbin --overlay-rwdir /tmp --overlay-rwdir /bin \
--exec 'cp /path/to/iproute2-next/ip/ip /bin/ip && \
cd tools/testing/selftests/net && \
bash bridge_stp_mode.sh'
iproute2 support can be found here [2].
[1] https://lore.kernel.org/netdev/565B7F7D.80208@nod.at/
[2] https://github.com/aroulin/iproute2-next/tree/bridge-stp-mode
Suggested-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Andy Roulin <aroulin@nvidia.com>
Andy Roulin (3):
net: bridge: add stp_mode attribute for STP mode selection
docs: net: bridge: document stp_mode attribute
selftests: net: add bridge STP mode selection test
Documentation/networking/bridge.rst | 22 ++
include/uapi/linux/if_link.h | 40 +++
net/bridge/br_device.c | 1 +
net/bridge/br_netlink.c | 18 +-
net/bridge/br_private.h | 1 +
net/bridge/br_stp_if.c | 17 +-
tools/testing/selftests/net/Makefile | 1 +
.../testing/selftests/net/bridge_stp_mode.sh | 261 ++++++++++++++++++
8 files changed, 353 insertions(+), 8 deletions(-)
create mode 100755 tools/testing/selftests/net/bridge_stp_mode.sh
--
2.43.0
^ permalink raw reply
* [PATCH net-next 2/3] docs: net: bridge: document stp_mode attribute
From: Andy Roulin @ 2026-03-24 18:49 UTC (permalink / raw)
To: netdev
Cc: bridge, Nikolay Aleksandrov, Ido Schimmel, Andrew Lunn,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Jonathan Corbet, Shuah Khan, Petr Machata,
linux-doc, linux-kselftest, linux-kernel, Andy Roulin
In-Reply-To: <20260324184942.2828691-1-aroulin@nvidia.com>
Add documentation for the IFLA_BR_STP_MODE bridge attribute in the
"User space STP helper" section of the bridge documentation. Reference
the BR_STP_MODE_* values via kernel-doc and describe the use case for
network namespace environments.
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Andy Roulin <aroulin@nvidia.com>
---
Documentation/networking/bridge.rst | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/Documentation/networking/bridge.rst b/Documentation/networking/bridge.rst
index ef8b73e157b26..c1e6ea52c9e59 100644
--- a/Documentation/networking/bridge.rst
+++ b/Documentation/networking/bridge.rst
@@ -148,6 +148,28 @@ called by the kernel when STP is enabled/disabled on a bridge
stp_state <0|1>``). The kernel enables user_stp mode if that command returns
0, or enables kernel_stp mode if that command returns any other value.
+STP mode selection
+------------------
+
+The ``IFLA_BR_STP_MODE`` bridge attribute allows explicit control over how
+STP operates when enabled, bypassing the ``/sbin/bridge-stp`` helper
+entirely for the ``user`` and ``kernel`` modes.
+
+.. kernel-doc:: include/uapi/linux/if_link.h
+ :doc: Bridge STP mode values
+
+The default mode is ``BR_STP_MODE_AUTO``, which preserves the traditional
+behavior of invoking the ``/sbin/bridge-stp`` helper. The ``user`` and
+``kernel`` modes are particularly useful in network namespace environments
+where the helper mechanism is not available, as ``call_usermodehelper()``
+is restricted to the initial network namespace.
+
+Example::
+
+ ip link set dev br0 type bridge stp_mode user stp_state 1
+
+The mode can only be changed while STP is disabled.
+
VLAN
====
--
2.43.0
^ permalink raw reply related
* [PATCH net-next 1/3] net: bridge: add stp_mode attribute for STP mode selection
From: Andy Roulin @ 2026-03-24 18:49 UTC (permalink / raw)
To: netdev
Cc: bridge, Nikolay Aleksandrov, Ido Schimmel, Andrew Lunn,
David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Jonathan Corbet, Shuah Khan, Petr Machata,
linux-doc, linux-kselftest, linux-kernel, Andy Roulin
In-Reply-To: <20260324184942.2828691-1-aroulin@nvidia.com>
The bridge-stp usermode helper is currently restricted to the initial
network namespace, preventing userspace STP daemons (e.g. mstpd) from
operating on bridges in other network namespaces. Since commit
ff62198553e4 ("bridge: Only call /sbin/bridge-stp for the initial
network namespace"), bridges in non-init namespaces silently fall back
to kernel STP with no way to use userspace STP.
Add a new bridge attribute IFLA_BR_STP_MODE that allows explicit
per-bridge control over STP mode selection:
BR_STP_MODE_AUTO (default) - Existing behavior: invoke the
/sbin/bridge-stp helper in init_net only; fall back to kernel STP
if it fails or in non-init namespaces.
BR_STP_MODE_USER - Directly enable userspace STP (BR_USER_STP)
without invoking the helper. Works in any network namespace. The
caller is responsible for registering the bridge with the STP
daemon after enabling STP.
BR_STP_MODE_KERNEL - Directly enable kernel STP (BR_KERNEL_STP)
without invoking the helper.
The mode can only be changed while STP is disabled (-EBUSY otherwise).
IFLA_BR_STP_MODE is processed before IFLA_BR_STP_STATE in
br_changelink(), so both can be set atomically in a single netlink
message.
This eliminates the need for call_usermodehelper() in user/kernel
modes, addressing the security concerns discussed in the thread at
https://lore.kernel.org/netdev/565B7F7D.80208@nod.at/ and providing
a cleaner alternative to extending the helper into namespaces.
Suggested-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Andy Roulin <aroulin@nvidia.com>
---
include/uapi/linux/if_link.h | 40 ++++++++++++++++++++++++++++++++++++
net/bridge/br_device.c | 1 +
net/bridge/br_netlink.c | 18 +++++++++++++++-
net/bridge/br_private.h | 1 +
net/bridge/br_stp_if.c | 17 ++++++++-------
5 files changed, 69 insertions(+), 8 deletions(-)
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 83a96c56b8cad..87b2b671ec182 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -744,6 +744,11 @@ enum in6_addr_gen_mode {
* @IFLA_BR_FDB_MAX_LEARNED
* Set the number of max dynamically learned FDB entries for the current
* bridge.
+ *
+ * @IFLA_BR_STP_MODE
+ * Set the STP mode for the bridge, which controls how the bridge
+ * selects between userspace and kernel STP. The valid values are
+ * documented below in the ``BR_STP_MODE_*`` constants.
*/
enum {
IFLA_BR_UNSPEC,
@@ -796,11 +801,46 @@ enum {
IFLA_BR_MCAST_QUERIER_STATE,
IFLA_BR_FDB_N_LEARNED,
IFLA_BR_FDB_MAX_LEARNED,
+ IFLA_BR_STP_MODE,
__IFLA_BR_MAX,
};
#define IFLA_BR_MAX (__IFLA_BR_MAX - 1)
+/**
+ * DOC: Bridge STP mode values
+ *
+ * @BR_STP_MODE_AUTO
+ * Default. The kernel invokes the ``/sbin/bridge-stp`` helper to hand
+ * the bridge to a userspace STP daemon (e.g. mstpd). Only attempted in
+ * the initial network namespace; in other namespaces this falls back to
+ * kernel STP.
+ *
+ * @BR_STP_MODE_USER
+ * Directly enable userspace STP (``BR_USER_STP``) without invoking the
+ * ``/sbin/bridge-stp`` helper. Works in any network namespace. The
+ * caller is responsible for registering the bridge with the userspace
+ * STP daemon after enabling STP, and for deregistering it before
+ * disabling STP.
+ *
+ * @BR_STP_MODE_KERNEL
+ * Directly enable kernel STP (``BR_KERNEL_STP``) without invoking the
+ * helper.
+ *
+ * The mode controls how the bridge selects between userspace and kernel
+ * STP when STP is enabled via ``IFLA_BR_STP_STATE``. It can only be
+ * changed while STP is disabled (``IFLA_BR_STP_STATE`` == 0), returns
+ * ``-EBUSY`` otherwise. The default value is ``BR_STP_MODE_AUTO``.
+ */
+enum {
+ BR_STP_MODE_AUTO,
+ BR_STP_MODE_USER,
+ BR_STP_MODE_KERNEL,
+ __BR_STP_MODE_MAX
+};
+
+#define BR_STP_MODE_MAX (__BR_STP_MODE_MAX - 1)
+
struct ifla_bridge_id {
__u8 prio[2];
__u8 addr[6]; /* ETH_ALEN */
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index f7502e62dd357..a35ceae0a6f2c 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -518,6 +518,7 @@ void br_dev_setup(struct net_device *dev)
ether_addr_copy(br->group_addr, eth_stp_addr);
br->stp_enabled = BR_NO_STP;
+ br->stp_mode = BR_STP_MODE_AUTO;
br->group_fwd_mask = BR_GROUPFWD_DEFAULT;
br->group_fwd_mask_required = BR_GROUPFWD_DEFAULT;
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 0264730938f4b..4c607d5d17a49 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -1270,6 +1270,9 @@ static const struct nla_policy br_policy[IFLA_BR_MAX + 1] = {
NLA_POLICY_EXACT_LEN(sizeof(struct br_boolopt_multi)),
[IFLA_BR_FDB_N_LEARNED] = { .type = NLA_REJECT },
[IFLA_BR_FDB_MAX_LEARNED] = { .type = NLA_U32 },
+ [IFLA_BR_STP_MODE] = NLA_POLICY_RANGE(NLA_U32,
+ BR_STP_MODE_AUTO,
+ BR_STP_MODE_MAX),
};
static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
@@ -1306,6 +1309,17 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
return err;
}
+ if (data[IFLA_BR_STP_MODE]) {
+ u32 mode = nla_get_u32(data[IFLA_BR_STP_MODE]);
+
+ if (br->stp_enabled != BR_NO_STP) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Can't change STP mode while STP is enabled");
+ return -EBUSY;
+ }
+ br->stp_mode = mode;
+ }
+
if (data[IFLA_BR_STP_STATE]) {
u32 stp_enabled = nla_get_u32(data[IFLA_BR_STP_STATE]);
@@ -1634,6 +1648,7 @@ static size_t br_get_size(const struct net_device *brdev)
nla_total_size(sizeof(u8)) + /* IFLA_BR_NF_CALL_ARPTABLES */
#endif
nla_total_size(sizeof(struct br_boolopt_multi)) + /* IFLA_BR_MULTI_BOOLOPT */
+ nla_total_size(sizeof(u32)) + /* IFLA_BR_STP_MODE */
0;
}
@@ -1686,7 +1701,8 @@ static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev)
nla_put(skb, IFLA_BR_MULTI_BOOLOPT, sizeof(bm), &bm) ||
nla_put_u32(skb, IFLA_BR_FDB_N_LEARNED,
atomic_read(&br->fdb_n_learned)) ||
- nla_put_u32(skb, IFLA_BR_FDB_MAX_LEARNED, br->fdb_max_learned))
+ nla_put_u32(skb, IFLA_BR_FDB_MAX_LEARNED, br->fdb_max_learned) ||
+ nla_put_u32(skb, IFLA_BR_STP_MODE, br->stp_mode))
return -EMSGSIZE;
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 6dbca845e625d..e4bb9c3f28726 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -540,6 +540,7 @@ struct net_bridge {
BR_KERNEL_STP, /* old STP in kernel */
BR_USER_STP, /* new RSTP in userspace */
} stp_enabled;
+ u32 stp_mode;
struct net_bridge_mcast multicast_ctx;
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index cc4b27ff1b088..fa2271c5d84fe 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -149,7 +149,9 @@ static void br_stp_start(struct net_bridge *br)
{
int err = -ENOENT;
- if (net_eq(dev_net(br->dev), &init_net))
+ /* AUTO mode: try bridge-stp helper in init_net only */
+ if (br->stp_mode == BR_STP_MODE_AUTO &&
+ net_eq(dev_net(br->dev), &init_net))
err = br_stp_call_user(br, "start");
if (err && err != -ENOENT)
@@ -162,7 +164,7 @@ static void br_stp_start(struct net_bridge *br)
else if (br->bridge_forward_delay > BR_MAX_FORWARD_DELAY)
__br_set_forward_delay(br, BR_MAX_FORWARD_DELAY);
- if (!err) {
+ if (br->stp_mode == BR_STP_MODE_USER || !err) {
br->stp_enabled = BR_USER_STP;
br_debug(br, "userspace STP started\n");
} else {
@@ -180,12 +182,13 @@ static void br_stp_start(struct net_bridge *br)
static void br_stp_stop(struct net_bridge *br)
{
- int err;
-
if (br->stp_enabled == BR_USER_STP) {
- err = br_stp_call_user(br, "stop");
- if (err)
- br_err(br, "failed to stop userspace STP (%d)\n", err);
+ if (br->stp_mode == BR_STP_MODE_AUTO) {
+ int err = br_stp_call_user(br, "stop");
+
+ if (err)
+ br_err(br, "failed to stop userspace STP (%d)\n", err);
+ }
/* To start timers on any ports left in blocking */
spin_lock_bh(&br->lock);
--
2.43.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox