[PATCH 06/13] PCI: Account for ACS egress control in isolation checks
Leon Romanovsky <[email protected]> Sun, 2 Aug 2026 18:09:44 +0300
| Newsgroups | org.kernel.vger.linux-pci,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Leon Romanovsky <[email protected]> pci_acs_enabled() treats P2P Request Redirect as effective whenever its control bit is set. PCIe r7.0, sec 6.12.3, table 6-11 lets an enabled Egress Control Vector override it: a clear vector bit routes the request directly. IOMMU grouping uses this check to prove peer requests cannot bypass the IOMMU, but cannot know every applicable vector bit, so Request Redirect gives no such guarantee while Egress Control is enabled. Report Request Redirect as ineffective there, merging the devices into one IOMMU group, and report no isolation when the register cannot be read. Apply the same rule to the Intel SPT PCH quirk. Signed-off-by: Leon Romanovsky <[email protected]> --- drivers/pci/pci.c | 12 +++++++++++- drivers/pci/quirks.c | 10 ++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 154eb08036ad..bc1c3b68c131 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3620,7 +3620,8 @@ static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) */ acs_flags &= (pdev->acs_capabilities | PCI_ACS_EC); - pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl); + if (pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl)) + return false; /* * Direct Translated P2P routes a Translated Request to the peer @@ -3630,6 +3631,15 @@ static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) if (request_redirect && (ctrl & PCI_ACS_DT) && !(ctrl & PCI_ACS_TB)) return false; + /* + * Egress Control can override Request Redirect for peer requests. + * This target-independent check cannot prove that every applicable + * Egress Control Vector bit is set, so RR does not guarantee isolation + * while EC is enabled. + */ + if (request_redirect && (ctrl & PCI_ACS_EC)) + return false; + return (ctrl & acs_flags) == acs_flags; } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index bb4c09cbbd10..ebfe902b0118 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4990,15 +4990,21 @@ static int pci_quirk_intel_spt_pch_acs(struct pci_dev *dev, u16 acs_flags) return -ENOTTY; /* see pci_acs_flags_enabled() */ - pci_read_config_dword(dev, pos + PCI_ACS_CAP, &cap); + if (pci_read_config_dword(dev, pos + PCI_ACS_CAP, &cap)) + return 0; acs_flags &= (cap | PCI_ACS_EC); - pci_read_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, &ctrl); + if (pci_read_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, &ctrl)) + return 0; /* Direct Translated P2P may bypass Request Redirect. */ if (request_redirect && (ctrl & PCI_ACS_DT) && !(ctrl & PCI_ACS_TB)) return 0; + /* Egress Control may override Request Redirect for peer requests. */ + if (request_redirect && (ctrl & PCI_ACS_EC)) + return 0; + return pci_acs_ctrl_enabled(acs_flags, ctrl); } -- 2.55.0