From 4575e9aac5336d1365138c0284773bf8da4b1fa3 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 15 Jun 2026 13:12:29 -0600 Subject: vfio/pci: Latch disable_idle_d3 per device When disable_idle_d3 was introduced in vfio-pci, it directly manipulated the device power state with pci_set_power_state(). There were no refcounts to maintain or balanced operations, we could unconditionally bring the device to D0 and conditionally move it to D3hot. Therefore the module parameter was made writable. Later, in commit c61302aa48f7 ("vfio/pci: Move module parameters to vfio_pci.c"), as part of the vfio-pci-core split, the writable aspect of the module parameter was nullified. The parameter value could still be changed through sysfs, but the vfio-pci driver latched the values into vfio-pci-core globals at module init. Loading the vfio-pci module, or unloading and reloading, with non-default or different values could change the globals relative to existing devices bound to vfio-pci variant drivers. Runtime PM was introduced in commit 7ab5e10eda02 ("vfio/pci: Move the unused device into low power state with runtime PM"), which marks the point where power states became refcounted. PM get and put operations need to be balanced, but the same module operations noted above can change the global variables relative to those devices already bound to vfio-pci variant drivers. This introduces a window where PM operations can now become unbalanced. To resolve this with a narrow footprint for stable backports, the disable_idle_d3 flag is latched into the vfio_pci_core_device at the time of initialization, such that the device always operates with a consistent value. NB. vfio_pci_dev_set_try_reset() now unconditionally raises the runtime PM usage count around bus reset to account for disable_idle_d3 becoming a per-device rather than global flag. When this flag is set, the additional get/put pair is harmless and allows continued use of the shared vfio_pci_dev_set_pm_runtime_get() helper. Fixes: 7ab5e10eda02 ("vfio/pci: Move the unused device into low power state with runtime PM") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Alex Williamson Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20260615191241.688297-2-alex.williamson@nvidia.com Signed-off-by: Alex Williamson --- drivers/vfio/pci/vfio_pci_core.c | 19 ++++++++++--------- include/linux/vfio_pci_core.h | 1 + 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index a28f1e99362c..f8d1755de2ce 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -538,7 +538,7 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev) u16 cmd; u8 msix_pos; - if (!disable_idle_d3) { + if (!vdev->disable_idle_d3) { ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) return ret; @@ -617,7 +617,7 @@ out_free_state: out_disable_device: pci_disable_device(pdev); out_power: - if (!disable_idle_d3) + if (!vdev->disable_idle_d3) pm_runtime_put(&pdev->dev); return ret; } @@ -753,7 +753,7 @@ out: vfio_pci_dev_set_try_reset(vdev->vdev.dev_set); /* Put the pm-runtime usage counter acquired during enable */ - if (!disable_idle_d3) + if (!vdev->disable_idle_d3) pm_runtime_put(&pdev->dev); } EXPORT_SYMBOL_GPL(vfio_pci_core_disable); @@ -2144,6 +2144,8 @@ int vfio_pci_core_init_dev(struct vfio_device *core_vdev) init_rwsem(&vdev->memory_lock); xa_init(&vdev->ctx); + vdev->disable_idle_d3 = disable_idle_d3; + return 0; } EXPORT_SYMBOL_GPL(vfio_pci_core_init_dev); @@ -2239,7 +2241,7 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev) dev->driver->pm = &vfio_pci_core_pm_ops; pm_runtime_allow(dev); - if (!disable_idle_d3) + if (!vdev->disable_idle_d3) pm_runtime_put(dev); ret = vfio_register_group_dev(&vdev->vdev); @@ -2248,7 +2250,7 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev) return 0; out_power: - if (!disable_idle_d3) + if (!vdev->disable_idle_d3) pm_runtime_get_noresume(dev); pm_runtime_forbid(dev); @@ -2267,7 +2269,7 @@ void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev) vfio_pci_vf_uninit(vdev); vfio_pci_vga_uninit(vdev); - if (!disable_idle_d3) + if (!vdev->disable_idle_d3) pm_runtime_get_noresume(&vdev->pdev->dev); pm_runtime_forbid(&vdev->pdev->dev); @@ -2599,7 +2601,7 @@ static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set) * state. Increment the usage count for all the devices in the dev_set * before reset and decrement the same after reset. */ - if (!disable_idle_d3 && vfio_pci_dev_set_pm_runtime_get(dev_set)) + if (vfio_pci_dev_set_pm_runtime_get(dev_set)) return; if (!pci_reset_bus(pdev)) @@ -2609,8 +2611,7 @@ static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set) if (reset_done) cur->needs_reset = false; - if (!disable_idle_d3) - pm_runtime_put(&cur->pdev->dev); + pm_runtime_put(&cur->pdev->dev); } } diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h index 5fc6ce4dd786..27aab3fdbb91 100644 --- a/include/linux/vfio_pci_core.h +++ b/include/linux/vfio_pci_core.h @@ -127,6 +127,7 @@ struct vfio_pci_core_device { bool needs_pm_restore:1; bool pm_intx_masked:1; bool pm_runtime_engaged:1; + bool disable_idle_d3:1; bool sriov_active; struct pci_saved_state *pci_saved_state; struct pci_saved_state *pm_save; -- cgit v1.2.3 From daedde7f024ecf88bc8e832ed40cf2c795f0796a Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 15 Jun 2026 13:12:30 -0600 Subject: vfio/pci: Release the VGA arbiter client on register_device() failure The re-order in the Fixes commit below displaced vfio_pci_vga_init() as the last failure point of what is now vfio_pci_core_register_device() without introducing an unwind for the VGA arbiter registration. In current kernels this is mostly benign because vfio_pci_set_decode() only uses pci_dev state, but the original failure path could leave a callback with a freed vdev cookie. The stale registration also becomes unsafe again once the callback follows drvdata to the vfio device. Add the required VGA unwind callout. Fixes: 4aeec3984ddc ("vfio/pci: Re-order vfio_pci_probe()") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Alex Williamson Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20260615191241.688297-3-alex.williamson@nvidia.com Signed-off-by: Alex Williamson --- drivers/vfio/pci/vfio_pci_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index f8d1755de2ce..dab82c078580 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -2254,6 +2254,7 @@ out_power: pm_runtime_get_noresume(dev); pm_runtime_forbid(dev); + vfio_pci_vga_uninit(vdev); out_vf: vfio_pci_vf_uninit(vdev); return ret; -- cgit v1.2.3 From e73638e55f861758d49f14d7bb5dba3035981cd7 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 15 Jun 2026 13:12:31 -0600 Subject: vfio/pci: Fix racy bitfields and tighten struct layout Bitfield operations are not atomic, they use a read-modify-write pattern, therefore we should be careful not to pack bitfields that can be concurrently updated into the same storage unit. This split takes a binary approach: flags that are only modified pre/post open/close remain bitfields, flags modified from user action, including actions that reach across to another device (ex. reset) use dedicated storage units. Note that the virq_disabled and bardirty flags are relocated to fill an existing hole in the structure. Bitfield justifications: has_dyn_msix: written only in vfio_pci_core_enable() pci_2_3: written only in vfio_pci_core_enable() reset_works: written only in vfio_pci_core_enable() extended_caps: written only in vfio_cap_len() under vfio_config_init() has_vga: written only in vfio_pci_core_enable() nointx: written only in vfio_pci_core_enable() needs_pm_restore: written only in vfio_pci_probe_power_state() disable_idle_d3: written only at .init in vfio_pci_core_init_dev() Dedicated storage units: virq_disabled: written by guest INTx command writes in vfio_basic_config_write() while the device is open bardirty: written by guest BAR writes in vfio_basic_config_write() while the device is open pm_intx_masked: written in the runtime-PM suspend path. pm_runtime_engaged: written by low-power feature entry/exit paths needs_reset: set in vfio_pci_core_disable() and cleared for devices in the set by vfio_pci_dev_set_try_reset() sriov_active: written by vfio_pci_core_sriov_configure() via sysfs sriov_numvfs while bound. Fixes: 9cd0f6d5cbb6 ("vfio/pci: Use bitfield for struct vfio_pci_core_device flags") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Alex Williamson Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20260615191241.688297-4-alex.williamson@nvidia.com Signed-off-by: Alex Williamson --- include/linux/vfio_pci_core.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h index 27aab3fdbb91..985b8af5a04b 100644 --- a/include/linux/vfio_pci_core.h +++ b/include/linux/vfio_pci_core.h @@ -101,6 +101,9 @@ struct vfio_pci_core_device { const struct vfio_pci_device_ops *pci_ops; void __iomem *barmap[PCI_STD_NUM_BARS]; bool bar_mmap_supported[PCI_STD_NUM_BARS]; + /* Flags modified at runtime - dedicated storage unit */ + bool virq_disabled; + bool bardirty; u8 *pci_config_map; u8 *vconfig; struct perm_bits *msi_perm; @@ -115,19 +118,19 @@ struct vfio_pci_core_device { u16 msix_size; u32 msix_offset; u32 rbar[7]; + /* Flags only modified on setup/release - bitfield ok */ bool has_dyn_msix:1; bool pci_2_3:1; - bool virq_disabled:1; bool reset_works:1; bool extended_caps:1; - bool bardirty:1; bool has_vga:1; - bool needs_reset:1; bool nointx:1; bool needs_pm_restore:1; - bool pm_intx_masked:1; - bool pm_runtime_engaged:1; bool disable_idle_d3:1; + /* Flags modified at runtime - dedicated storage unit */ + bool needs_reset; + bool pm_intx_masked; + bool pm_runtime_engaged; bool sriov_active; struct pci_saved_state *pci_saved_state; struct pci_saved_state *pm_save; -- cgit v1.2.3 From f2365a63b02ddea32e7db78b742c2503ec7b81f1 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 15 Jun 2026 13:12:32 -0600 Subject: vfio/mlx5: Fix racy bitfields and tighten struct layout Bitfield operations are not atomic, they use a read-modify-write pattern, therefore we should be careful not to pack bitfields that can be concurrently updated into the same storage unit. This split takes a binary approach: flags that are only modified pre/post open/close remain bitfields, flags modified from user action, including actions that reach across to another device (ex. reset) use dedicated storage units. Note mlx5_vhca_page_tracker.status is relocated to fill the alignment hole this split exposes. Bitfield justifications: migrate_cap: written only in mlx5vf_cmd_set_migratable() at probe chunk_mode: written only in mlx5vf_cmd_set_migratable() at probe mig_state_cap: written only in mlx5vf_cmd_set_migratable() at probe Dedicated storage units: mdev_detach: written in the VF attach/detach event notifier mlx5fv_vf_event() at runtime log_active: written in mlx5vf_start_page_tracker()/ mlx5vf_stop_page_tracker() during runtime dirty tracking deferred_reset: written in mlx5vf_state_mutex_unlock()/ mlx5vf_pci_aer_reset_done() during runtime reset handling is_err: set by tracker error handling and dirty-log polling at runtime object_changed: set by tracker event handling and cleared by dirty-log polling at runtime Fixes: 61a2f1460fd0 ("vfio/mlx5: Manage the VF attach/detach callback from the PF") Fixes: 79c3cf279926 ("vfio/mlx5: Init QP based resources for dirty tracking") Fixes: f886473071d6 ("vfio/mlx5: Add support for tracker object change event") Cc: Yishai Hadas Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Alex Williamson Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20260615191241.688297-5-alex.williamson@nvidia.com Signed-off-by: Alex Williamson --- drivers/vfio/pci/mlx5/cmd.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/vfio/pci/mlx5/cmd.h b/drivers/vfio/pci/mlx5/cmd.h index deed0f132f39..c86d8b243a52 100644 --- a/drivers/vfio/pci/mlx5/cmd.h +++ b/drivers/vfio/pci/mlx5/cmd.h @@ -158,26 +158,29 @@ struct mlx5_vhca_qp { struct mlx5_vhca_page_tracker { u32 id; u32 pdn; - u8 is_err:1; - u8 object_changed:1; + /* Flags modified at runtime - dedicated storage unit */ + u8 is_err; + u8 object_changed; + int status; struct mlx5_uars_page *uar; struct mlx5_vhca_cq cq; struct mlx5_vhca_qp *host_qp; struct mlx5_vhca_qp *fw_qp; struct mlx5_nb nb; - int status; }; struct mlx5vf_pci_core_device { struct vfio_pci_core_device core_device; int vf_id; u16 vhca_id; + /* Flags only modified on setup/release - bitfield ok */ u8 migrate_cap:1; - u8 deferred_reset:1; - u8 mdev_detach:1; - u8 log_active:1; u8 chunk_mode:1; u8 mig_state_cap:1; + /* Flags modified at runtime - dedicated storage unit */ + u8 mdev_detach; + u8 log_active; + u8 deferred_reset; struct completion tracker_comp; /* protect migration state */ struct mutex state_mutex; -- cgit v1.2.3 From 3788cd493e444742bc2ba252eb5c09ffc8b345dc Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 15 Jun 2026 13:12:33 -0600 Subject: vfio/pci: Latch all module parameters per device The vfio-pci module parameters of disable_idle_d3, nointxmask, and disable_vga latch vfio-pci policy into vfio-pci-core globals each time the vfio-pci module is initialized. The disable_idle_d3 parameter has already migrated to a per-device flag in order to provide consistency for refcounted PM operations for the lifetime of the device registration. Pull the remaining vfio-pci module-parameter policy out of vfio-pci-core into per-device flags set at device initialization. This also restores the mutable aspect of the disable_idle_d3 and nointxmask module parameters for vfio-pci, with the caveat that the parameters are latched into the device at probe. A notable change for variant drivers is that their devices are no longer affected by vfio-pci module parameters and those drivers may need to adopt similar module parameters if any devices have a hidden dependency on vfio-pci setting non-default policy. Assisted-by: Claude:claude-opus-4-8 Acked-by: Chengwen Feng Signed-off-by: Alex Williamson Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20260615191241.688297-6-alex.williamson@nvidia.com Signed-off-by: Alex Williamson --- drivers/vfio/pci/vfio_pci.c | 30 ++++++++++++++++++++++-------- drivers/vfio/pci/vfio_pci_core.c | 26 ++++++-------------------- include/linux/vfio_pci_core.h | 4 ++-- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 0c771064c0b8..830369ff878d 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -125,9 +125,30 @@ static int vfio_pci_open_device(struct vfio_device *core_vdev) return 0; } +static int vfio_pci_init_dev(struct vfio_device *core_vdev) +{ + struct vfio_pci_core_device *vdev = + container_of(core_vdev, struct vfio_pci_core_device, vdev); + + /* + * These behaviors originated in vfio-pci and moved into + * vfio-pci-core when the driver was split; vfio-pci remains the + * only driver that toggles them. Latch our module parameters per + * device at init time so that later parameter changes do not + * affect already-initialized devices. + */ + vdev->nointxmask = nointxmask; + vdev->disable_idle_d3 = disable_idle_d3; +#ifdef CONFIG_VFIO_PCI_VGA + vdev->disable_vga = disable_vga; +#endif + + return vfio_pci_core_init_dev(core_vdev); +} + static const struct vfio_device_ops vfio_pci_ops = { .name = "vfio-pci", - .init = vfio_pci_core_init_dev, + .init = vfio_pci_init_dev, .release = vfio_pci_core_release_dev, .open_device = vfio_pci_open_device, .close_device = vfio_pci_core_close_device, @@ -256,13 +277,6 @@ static void __init vfio_pci_fill_ids(void) static int __init vfio_pci_init(void) { int ret; - bool is_disable_vga = true; - -#ifdef CONFIG_VFIO_PCI_VGA - is_disable_vga = disable_vga; -#endif - - vfio_pci_core_set_params(nointxmask, is_disable_vga, disable_idle_d3); /* Register and scan for devices */ ret = pci_register_driver(&vfio_pci_driver); diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index dab82c078580..db36d903dcd4 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -38,10 +38,6 @@ #define DRIVER_AUTHOR "Alex Williamson " #define DRIVER_DESC "core driver for VFIO based PCI devices" -static bool nointxmask; -static bool disable_vga; -static bool disable_idle_d3; - static void vfio_pci_eventfd_rcu_free(struct rcu_head *rcu) { struct vfio_pci_eventfd *eventfd = @@ -92,10 +88,10 @@ struct vfio_pci_vf_token { int users; }; -static inline bool vfio_vga_disabled(void) +static inline bool vfio_vga_disabled(struct vfio_pci_core_device *vdev) { #ifdef CONFIG_VFIO_PCI_VGA - return disable_vga; + return vdev->disable_vga; #else return true; #endif @@ -111,11 +107,12 @@ static inline bool vfio_vga_disabled(void) */ static unsigned int vfio_pci_set_decode(struct pci_dev *pdev, bool single_vga) { + struct vfio_pci_core_device *vdev = dev_get_drvdata(&pdev->dev); struct pci_dev *tmp = NULL; unsigned char max_busnr; unsigned int decodes; - if (single_vga || !vfio_vga_disabled() || pci_is_root_bus(pdev->bus)) + if (single_vga || !vfio_vga_disabled(vdev) || pci_is_root_bus(pdev->bus)) return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM | VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM; @@ -562,7 +559,7 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev) if (!vdev->pci_saved_state) pci_dbg(pdev, "%s: Couldn't store saved state\n", __func__); - if (likely(!nointxmask)) { + if (likely(!vdev->nointxmask)) { if (vfio_pci_nointx(pdev)) { pci_info(pdev, "Masking broken INTx support\n"); vdev->nointx = true; @@ -602,7 +599,7 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev) vdev->has_dyn_msix = false; } - if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev)) + if (!vfio_vga_disabled(vdev) && vfio_pci_is_vga(pdev)) vdev->has_vga = true; vfio_pci_core_map_bars(vdev); @@ -2144,8 +2141,6 @@ int vfio_pci_core_init_dev(struct vfio_device *core_vdev) init_rwsem(&vdev->memory_lock); xa_init(&vdev->ctx); - vdev->disable_idle_d3 = disable_idle_d3; - return 0; } EXPORT_SYMBOL_GPL(vfio_pci_core_init_dev); @@ -2616,15 +2611,6 @@ static void vfio_pci_dev_set_try_reset(struct vfio_device_set *dev_set) } } -void vfio_pci_core_set_params(bool is_nointxmask, bool is_disable_vga, - bool is_disable_idle_d3) -{ - nointxmask = is_nointxmask; - disable_vga = is_disable_vga; - disable_idle_d3 = is_disable_idle_d3; -} -EXPORT_SYMBOL_GPL(vfio_pci_core_set_params); - static void vfio_pci_core_cleanup(void) { vfio_pci_uninit_perm_bits(); diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h index 985b8af5a04b..9a1674c152aa 100644 --- a/include/linux/vfio_pci_core.h +++ b/include/linux/vfio_pci_core.h @@ -127,6 +127,8 @@ struct vfio_pci_core_device { bool nointx:1; bool needs_pm_restore:1; bool disable_idle_d3:1; + bool nointxmask:1; + bool disable_vga:1; /* Flags modified at runtime - dedicated storage unit */ bool needs_reset; bool pm_intx_masked; @@ -161,8 +163,6 @@ int vfio_pci_core_register_dev_region(struct vfio_pci_core_device *vdev, unsigned int type, unsigned int subtype, const struct vfio_pci_regops *ops, size_t size, u32 flags, void *data); -void vfio_pci_core_set_params(bool nointxmask, bool is_disable_vga, - bool is_disable_idle_d3); void vfio_pci_core_close_device(struct vfio_device *core_vdev); int vfio_pci_core_init_dev(struct vfio_device *core_vdev); void vfio_pci_core_release_dev(struct vfio_device *core_vdev); -- cgit v1.2.3 From dc7fe87de492ea7f33a72b78d26650b75bf37f4f Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 15 Jun 2026 14:47:00 -0600 Subject: vfio: Remove device debugfs before releasing devres VFIO device debugfs files created with debugfs_create_devm_seqfile() store a devres allocated debugfs_devm_entry as inode private data. vfio_unregister_group_dev() currently calls vfio_device_del() before vfio_device_debugfs_exit(), but device_del() releases devres. This can leave debugfs entries visible with stale inode private data while unregister waits for userspace references to drain. Remove the per-device debugfs tree before vfio_device_del(). The debugfs view is diagnostic only, so losing it at the start of unregister is preferable to preserving entries whose backing storage may already have been released. Complete the teardown by clearing the per-device debugfs root after removal. This matches the global debugfs root cleanup and prevents future users from mistaking a removed dentry for a live debugfs tree during the remainder of unregister. Fixes: 2202844e4468 ("vfio/migration: Add debugfs to live migration driver") Reported-by: Sashiko AI Review Link: https://lore.kernel.org/r/20260615192725.6A2221F000E9@smtp.kernel.org Cc: stable@vger.kernel.org Cc: Longfang Liu Assisted-by: OpenAI Codex:gpt-5 Signed-off-by: Alex Williamson Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20260615204717.735302-1-alex.williamson@nvidia.com Signed-off-by: Alex Williamson --- drivers/vfio/debugfs.c | 1 + drivers/vfio/vfio_main.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/vfio/debugfs.c b/drivers/vfio/debugfs.c index 8b0ca7a09064..8a2f1b0cce3f 100644 --- a/drivers/vfio/debugfs.c +++ b/drivers/vfio/debugfs.c @@ -97,6 +97,7 @@ void vfio_device_debugfs_init(struct vfio_device *vdev) void vfio_device_debugfs_exit(struct vfio_device *vdev) { debugfs_remove_recursive(vdev->debug_root); + vdev->debug_root = NULL; } void vfio_debugfs_create_root(void) diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c index 5e0422014523..ed538aebb0b8 100644 --- a/drivers/vfio/vfio_main.c +++ b/drivers/vfio/vfio_main.c @@ -406,6 +406,13 @@ void vfio_unregister_group_dev(struct vfio_device *device) */ vfio_device_group_unregister(device); + /* + * Remove debugfs before device_del(), which releases devres. Some + * debugfs entries are created with debugfs_create_devm_seqfile() and + * therefore rely on devres-managed inode private data. + */ + vfio_device_debugfs_exit(device); + /* * Balances vfio_device_add() in register path, also prevents * new device opened by userspace in the cdev path. @@ -435,7 +442,6 @@ void vfio_unregister_group_dev(struct vfio_device *device) } } - vfio_device_debugfs_exit(device); /* Balances vfio_device_set_group in register path */ vfio_device_remove_group(device); } -- cgit v1.2.3 From 586a989d8b0db75d6f97c80a4f588d46e1df6881 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 15 Jun 2026 13:12:34 -0600 Subject: vfio/pci: Expose latched module parameter policy in debugfs The nointxmask and disable_idle_d3 module parameters remain writable, but vfio-pci now latches their values into each device at init. Once a device is registered, changing the module parameter only affects future devices, leaving no direct way to confirm the effective policy for an existing device. Add a pci debugfs directory under the VFIO device debugfs root and report the per-device nointxmask and disable_idle_d3 values. These are read-only debugfs views and use the same Y/N bool output convention as the module parameters. Read-only vfio-pci parameters, such as disable_vga, are not exposed here because they cannot drift from the latched device value, therefore the existing module parameter exposure via sysfs is sufficient. Note that while only vfio-pci currently provides these options, the implementation is in vfio-pci-core and therefore properly reflects the device policy in the core, regardless of driver. Assisted-by: OpenAI Codex:gpt-5 Cc: Guixin Liu Signed-off-by: Alex Williamson Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20260615191241.688297-7-alex.williamson@nvidia.com Signed-off-by: Alex Williamson --- Documentation/ABI/testing/debugfs-vfio | 26 +++++++++++++++ drivers/vfio/pci/vfio_pci_core.c | 59 ++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/Documentation/ABI/testing/debugfs-vfio b/Documentation/ABI/testing/debugfs-vfio index 70ec2d454686..ed2f29c3a9b4 100644 --- a/Documentation/ABI/testing/debugfs-vfio +++ b/Documentation/ABI/testing/debugfs-vfio @@ -29,3 +29,29 @@ Date: Oct 2025 KernelVersion: 6.18 Contact: Cédric Le Goater Description: Read the migration features of the vfio device. + +What: /sys/kernel/debug/vfio//pci +Date: June 2026 +KernelVersion: 7.2 +Contact: Alex Williamson +Description: This debugfs file directory is used for debugging + VFIO PCI devices. + +What: /sys/kernel/debug/vfio//pci/nointxmask +Date: June 2026 +KernelVersion: 7.2 +Contact: Alex Williamson +Description: Read the nointxmask policy latched for this device. This + policy governs whether the device may use PCI 2.3 style + INTx masking when supported, reporting a value of "N", or + requires APIC level INTx masking, reporting a value of "Y". + +What: /sys/kernel/debug/vfio//pci/disable_idle_d3 +Date: June 2026 +KernelVersion: 7.2 +Contact: Alex Williamson +Description: Read the disable_idle_d3 policy latched for this device. This + policy governs whether the device PM runtime usage count is + kept elevated while the device is bound to the driver and + unused, reporting a value of "Y", or decremented to allow the + device to enter a low power state, reporting a value of "N". diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index db36d903dcd4..3f11a9624b9c 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -11,6 +11,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #if IS_ENABLED(CONFIG_EEH) #include #endif @@ -97,6 +99,60 @@ static inline bool vfio_vga_disabled(struct vfio_pci_core_device *vdev) #endif } +#ifdef CONFIG_VFIO_DEBUGFS +static struct vfio_pci_core_device * +vfio_pci_core_debugfs_private(struct seq_file *seq) +{ + struct device *dev = seq->private; + struct vfio_device *core_vdev = container_of(dev, struct vfio_device, + device); + + return container_of(core_vdev, struct vfio_pci_core_device, vdev); +} + +static int vfio_pci_core_debugfs_nointxmask(struct seq_file *seq, void *data) +{ + struct vfio_pci_core_device *vdev = vfio_pci_core_debugfs_private(seq); + + seq_puts(seq, vdev->nointxmask ? "Y\n" : "N\n"); + return 0; +} + +static int vfio_pci_core_debugfs_disable_idle_d3(struct seq_file *seq, + void *data) +{ + struct vfio_pci_core_device *vdev = vfio_pci_core_debugfs_private(seq); + + seq_puts(seq, vdev->disable_idle_d3 ? "Y\n" : "N\n"); + return 0; +} + +/* + * disable_idle_d3 and nointxmask are writable module parameters latched + * per device at init, so a device's effective value can differ from the + * current parameter setting. Expose the per-device (read-only) values + * here for visibility; read-only parameters can't drift and are omitted. + */ +static void vfio_pci_core_debugfs_init(struct vfio_pci_core_device *vdev) +{ + struct device *dev = &vdev->vdev.device; + struct dentry *pci_dir; + + if (IS_ERR_OR_NULL(vdev->vdev.debug_root)) + return; + + pci_dir = debugfs_create_dir("pci", vdev->vdev.debug_root); + debugfs_create_devm_seqfile(dev, "nointxmask", pci_dir, + vfio_pci_core_debugfs_nointxmask); + debugfs_create_devm_seqfile(dev, "disable_idle_d3", pci_dir, + vfio_pci_core_debugfs_disable_idle_d3); +} +#else +static inline void vfio_pci_core_debugfs_init(struct vfio_pci_core_device *vdev) +{ +} +#endif /* CONFIG_VFIO_DEBUGFS */ + /* * Our VGA arbiter participation is limited since we don't know anything * about the device itself. However, if the device is the only VGA device @@ -2242,6 +2298,9 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev) ret = vfio_register_group_dev(&vdev->vdev); if (ret) goto out_power; + + vfio_pci_core_debugfs_init(vdev); + return 0; out_power: -- cgit v1.2.3 From e242e974e812e7a47e3088860c80d9492fac314f Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 30 Jun 2026 14:28:05 -0700 Subject: vfio: selftests: Add luuid to libvfio.mk's list of libraries, not to the Makefile Link to the uuid library as part of libvfio.mk instead of as only linking it via VFIO selftests' Makefile, as the whole point of providing libvfio.mk is to allow linking the VFIO library functionality into KVM selftests, without KVM selftests having to know the gory details or duplicate code. Cc: Raghavendra Rao Ananta Cc: David Matlack Cc: Vipin Sharma Cc: Alex Williamson Fixes: e65f1bf8a2db ("vfio: selftests: Extend container/iommufd setup for passing vf_token") Signed-off-by: Sean Christopherson Reviewed-by: David Matlack Link: https://lore.kernel.org/r/20260630212805.474418-1-seanjc@google.com Signed-off-by: Alex Williamson --- tools/testing/selftests/vfio/Makefile | 2 -- tools/testing/selftests/vfio/lib/libvfio.mk | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/vfio/Makefile b/tools/testing/selftests/vfio/Makefile index e6e8cb52ab03..2c32c48db509 100644 --- a/tools/testing/selftests/vfio/Makefile +++ b/tools/testing/selftests/vfio/Makefile @@ -29,8 +29,6 @@ CFLAGS += $(EXTRA_CFLAGS) LDFLAGS += -pthread -LDLIBS += -luuid - $(TEST_GEN_PROGS): $(OUTPUT)/%: $(OUTPUT)/%.o $(LIBVFIO_O) $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $< $(LIBVFIO_O) $(LDLIBS) -o $@ diff --git a/tools/testing/selftests/vfio/lib/libvfio.mk b/tools/testing/selftests/vfio/lib/libvfio.mk index 2b8d73b7d329..67942b085068 100644 --- a/tools/testing/selftests/vfio/lib/libvfio.mk +++ b/tools/testing/selftests/vfio/lib/libvfio.mk @@ -26,6 +26,8 @@ $(LIBVFIO_O_DIRS): CFLAGS += -I$(LIBVFIO_SRCDIR)/include +LDLIBS += -luuid + $(LIBVFIO_O): $(LIBVFIO_OUTPUT)/%.o : $(LIBVFIO_SRCDIR)/%.c | $(LIBVFIO_O_DIRS) $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ -- cgit v1.2.3