[PATCH v8 0/6] PCI: Add support for ACS Enhanced Capability

From: Wei Wang

Date: Mon May 25 2026 - 09:43:20 EST


This patchset improves the core ACS implementation and adds support for
the Access Control Services (ACS) Enhanced Capability, introduced with
PCIe Gen 5.

Improvements to the core ACS implementation include:
- Validating ACS enable flags against device-specific capabilities rather
than generic kernel masks. This ensures only supported features are
enabled while safely ignoring attempts to disable unsupported bits.

- Consolidating delimiter parsing into pci_dev_str_match() and returning
-ENODEV when no further entries can be parsed. This removes duplicated
logic in callers.

- Refactoring ACS parameter handling by splitting the intertwined
disable_acs_redir and config_acs param logic into dedicated functions.
This improves maintainability and robustness while optimizing parsing
with better validation and readability.

- Updating the config_acs kernel parameter documentation to include an
example of multi-device configuration with distinct settings and
advising users to quote the parameter to avoid bootloader parsing
issues with the semicolon separator.

Support for the ACS Enhanced Capability is built on top of this improved
implementation. This capability provides additional access control
features that improve device isolation — particularly important in
virtualization scenarios where devices are passed through to different
virtual machines (VMs). Strong isolation is critical to ensure security
between devices assigned to different VMs and the host.

In Linux, device grouping assumes that devices in separate IOMMU groups
are properly isolated. To uphold this assumption, the enhanced ACS
controls are enabled by default on hardware that supports the PCI_ACS_ECAP
capability. As with other basic ACS access controls, these new controls
can be configured via the config_acs= boot parameter.

Support for checking the enhanced ACS controls on Root and Downstream
Ports has been added to pci_acs_enabled(). On devices that support
PCI_ACS_ECAP, these controls must be properly enabled. To maintain
compatibility with legacy devices that lack PCI_ACS_ECAP support,
pci_acs_enabled() simply skips the check.

v7->v8 changes:
Patch 1:
- Validate against dev->acs_capabilities & GENMASK_U16(6, 0) rather than
the raw dev->acs_capabilities, as the latter may contain fields (like
the egress control vector size) that do not correspond to bits in the
ACS control register. (Sashiko-bot)
- Gate the new capability check on !acs_mask so it only fires for the
config_acs parameter path. This avoids breaking legacy
disable_acs_redir behavior. (Sashiko-bot)
- Validate both enable and disable bits (the full mask), not just flags.
Reverts the v7 narrowing to enable-only.
Patch 2:
- Remove the leading '-' characters in the documentation examples to
prevent copy-paste confusion for users. (Randy)
- Recommend using double quotes instead of single quotes for multiple
devices to avoid potential shell-escaping issues where single quotes
might be treated as literal characters. (Sashiko-bot)
Patch 3:
- Move the error reporting back to the callers so that caller context
is included in the dmesg output. (Krzysztof)
- In pci_dev_str_match(): enforce stricter boundary checks on successful
matches (see Patch 3 commit log for full details).
Patch 4:
- Move the pci_info logging for ACS modifications up to pci_enable_acs()
so it prints for both disable_acs_redir and config_acs modifications.
Introduction of kernel_default_ctrl so the print only fires when a
cmdline param diverges from pci_std_enable_acs()'s output (not on
every pci_std_enable_acs() modification). (Sashiko-bot)
- Drop max_shift; bound the parse loop by the u16 width (16) and rely on
the existing invalid_bits & ~valid_ctrl check to report out-of-range
bits with their bitmask, which is more informative than reporting the
parse position.
- Drop the -ENODEV "no more entries" signal. *endptr is now advanced
past the delimiter so callers terminate the loop naturally via
while (*p).
Patch 5:
- In pci_param_config_acs(): when ECAP is supported by the device add
the ECAP control bits (GENMASK_U16(12, 7)) to valid_ctrl.
- Validate DMAC/UMAC reserved encoding against the prospective ctrl
value rather than enabled_bits alone, so the case where the user
enables one bit while fw_ctrl already has the other set is also
caught.
Patch 6:
- In pci_acs_ecap_enabled(): Add a defensive NULL check for the upstream
port before dereferencing it. While standard downstream ports should
always have an upstream port, this guards against kernel panics in
malformed topologies. (Sashiko-bot)
- Remove the redundant pdev->acs_capabilities & PCI_ACS_ECAP condition
in pci_acs_flags_enabled(). The preceding bitwise operation
(acs_flags &= (pdev->acs_capabilities | PCI_ACS_EC))
already guarantees that acs_flags will only contain the PCI_ACS_ECAP
bit if the device actually supports it.
v7 Link: https://lore.kernel.org/all/SI2PR01MB439385689A32A1DDA9CEABE1DC3F2@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/

v6->v7 changes:
- Rebased onto next-20260505 (based on v7.1-rc2)
- Picked up Reviewed-by: Jason Gunthorpe <jgg@xxxxxxxxxx>
- No functional changes
v6 Link: https://lore.kernel.org/all/SEZPR01MB439931D7320F6C476D181C1EDC44A@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/

v5->v6 changes:
- Patch 3: In pci_dev_str_match(), explicitly set `ret = 0` when no
matching string is found. This resolves a smatch warning that `ret`
returned from sscanf() may be 2 or 4 even though no matching string
is found later comparison.
v5 Link: https://lore.kernel.org/all/SI2PR01MB439326AF08A79D1C5661C29BDC6CA@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/

v4->v5 changes:
- Added significant refactoring of the core ACS implementation (Patches
1-4) to improve validation, safety, and readability;
- For USP and DSP Memory Target Access Control, added masks and enum
values for the encodings and explicitly rejected the reserved encoding
(0b11);
- In pci_acs_ecap_enabled(), removed the use of 'is_dsp' variable.
v4 Link: https://lore.kernel.org/all/SI2PR01MB43932C799AE9111C7D2C319FDC65A@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/

v3->v4 changes:
- In pci_acs_ecap_enabled(): Check the pcie type for
PCI_EXP_TYPE_DOWNSTREAM explicitly.
v3 Link: https://lore.kernel.org/all/SI2PR01MB439325B4E44D5A39F34A4015DC9AA@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/

v2->v3 changes:
- Drop the warning when a device has no support for the enhanced
capability.
v2 Link: https://lore.kernel.org/all/SI2PR01MB4393B836EA4FEDD1823483BADC94A@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/

v1->v2 changes:
- Enabled all enhanced ACS controls by default, rather than just Unclaimed
Request Redirect (which addressed the primary issue we encountered);
- Added checks for enhanced ACS controls on Root and Downstream Ports in
pci_acs_enabled() to ensure proper enablement when grouping devices or
enabling features such as IOMMU PASID.
v1 Link: https://lore.kernel.org/all/SI2PR01MB43931A911357962A5E986FFEDC8CA@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/

Thanks to Jason Gunthorpe, Jonathan Cameron, Dan Carpenter,
Krzysztof Wilczyński, and Randy Dunlap for reviewing the patchset.

Patches on github: https://github.com/wei-w-wang/linux/tree/v8-acs-enhanced-cap-and-refactor

Wei Wang (6):
PCI: Validate ACS enable flags against device-specific ACS
capabilities
Documentation/kernel-parameters: Add multi-device config_acs example
PCI: Consolidate delimiter handling into pci_dev_str_match()
PCI: Refactor disable_acs_redir and config_acs param handling
PCI: Enable the enhanced ACS controls introduced by PCI_ACS_ECAP
PCI: Add the enhanced ACS controls check to pci_acs_flags_enabled()

.../admin-guide/kernel-parameters.txt | 30 +-
drivers/pci/pci.c | 306 ++++++++++++------
include/uapi/linux/pci_regs.h | 13 +
3 files changed, 250 insertions(+), 99 deletions(-)


base-commit: 550604d6c9b9efc8d068aff94dc301694a7afdee
--
2.51.0