On Sun, Apr 29, 2018 at 09:16:48PM +0300, Gil Kupfer wrote: > This patch adds noats option to the pci boot parameter. > When noats is selected, all ATS related functions fail immediately and > the IOMMU is configured to not use device-iotlb. > > Any function that checks for ATS capabilities directly against the > devices should also check this flag. (Currently, such functions exist > only in IOMMU drivers, and they are covered by this patch.) > > The motivation behind this patch is the existence of malicious devices. > Lots of research has been done about how to utilitize the IOMMU as a > protection from such devices. When ATS is supported, any I/O device can > access any physical access by faking device-IOTLB entries. > Adding the ability to ignore these entries lets sysadmins enhance system > security. > > Signed-off-by: Gil Kupfer <gilkup@xxxxxxxxxxxxxxxxx> Applied with Joerg's ack to pci/virtualization for v4.18, thanks! > --- > This patch is intended to add the ability to disable ATS at boot time. > > My IOMMU has the ATS ecap but I don't have any PCI device that supports > ATS so I can't fully test it. However, I did ran it (with and without the > new boot flag) on QEMU with virtualized IOMMU with the device-iotlb flag > and it seems that at least the machine does not crush. > > QEMU version: > master branch from Jul 11 2017 > commit aa916e409c04 ("Merge 29741be b876804") > --- > Documentation/admin-guide/kernel-parameters.txt | 2 ++ > drivers/iommu/amd_iommu.c | 11 ++++++++--- > drivers/iommu/intel-iommu.c | 3 ++- > drivers/pci/ats.c | 3 +++ > drivers/pci/pci.c | 7 +++++++ > include/linux/pci.h | 2 ++ > 6 files changed, 24 insertions(+), 4 deletions(-) > > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt > index 7737ab5..f443362 100644 > --- a/Documentation/admin-guide/kernel-parameters.txt > +++ b/Documentation/admin-guide/kernel-parameters.txt > @@ -3000,6 +3000,8 @@ > pcie_scan_all Scan all possible PCIe devices. Otherwise we > only look for one device below a PCIe downstream > port. > + noats [PCIE, Intel-IOMMU, AMD-IOMMU] > + do not use PCIe ATS (and IOMMU device-iotlb). > > pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power > Management. > diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c > index 0f1219f..2aa757e 100644 > --- a/drivers/iommu/amd_iommu.c > +++ b/drivers/iommu/amd_iommu.c > @@ -388,6 +388,9 @@ static bool pci_iommuv2_capable(struct pci_dev *pdev) > }; > int i, pos; > > + if (is_pcie_ats_disabled()) > + return false; > + > for (i = 0; i < 3; ++i) { > pos = pci_find_ext_capability(pdev, caps[i]); > if (pos == 0) > @@ -3602,9 +3605,11 @@ int amd_iommu_device_info(struct pci_dev *pdev, > > memset(info, 0, sizeof(*info)); > > - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS); > - if (pos) > - info->flags |= AMD_IOMMU_DEVICE_FLAG_ATS_SUP; > + if (!is_pcie_ats_disabled()) { > + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS); > + if (pos) > + info->flags |= AMD_IOMMU_DEVICE_FLAG_ATS_SUP; > + } > > pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); > if (pos) > diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c > index fc2765c..7ac4adc 100644 > --- a/drivers/iommu/intel-iommu.c > +++ b/drivers/iommu/intel-iommu.c > @@ -2434,7 +2434,8 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, > if (dev && dev_is_pci(dev)) { > struct pci_dev *pdev = to_pci_dev(info->dev); > > - if (ecap_dev_iotlb_support(iommu->ecap) && > + if (!is_pcie_ats_disabled() && > + ecap_dev_iotlb_support(iommu->ecap) && > pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) && > dmar_find_matched_atsr_unit(pdev)) > info->ats_supported = 1; > diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c > index eeb9fb2..619024d 100644 > --- a/drivers/pci/ats.c > +++ b/drivers/pci/ats.c > @@ -21,6 +21,9 @@ void pci_ats_init(struct pci_dev *dev) > { > int pos; > > + if (is_pcie_ats_disabled()) > + return; > + > pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS); > if (!pos) > return; > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > index 563901c..eb77590 100644 > --- a/drivers/pci/pci.c > +++ b/drivers/pci/pci.c > @@ -109,6 +109,10 @@ unsigned int pcibios_max_latency = 255; > /* If set, the PCIe ARI capability will not be used. */ > static bool pcie_ari_disabled; > > +/* If set, the PCIe ATS capability will not be used. */ > +static bool pcie_ats_disabled; > +bool is_pcie_ats_disabled(void) { return pcie_ats_disabled; } > + > /* Disable bridge_d3 for all PCIe ports */ > static bool pci_bridge_d3_disable; > /* Force bridge_d3 for all PCIe ports */ > @@ -5430,6 +5434,9 @@ static int __init pci_setup(char *str) > if (*str && (str = pcibios_setup(str)) && *str) { > if (!strcmp(str, "nomsi")) { > pci_no_msi(); > + } else if (!strncmp(str, "noats", 5)) { > + pr_info("PCIe: ATS is disabled\n"); > + pcie_ats_disabled = true; > } else if (!strcmp(str, "noaer")) { > pci_no_aer(); > } else if (!strncmp(str, "realloc=", 8)) { > diff --git a/include/linux/pci.h b/include/linux/pci.h > index 8039f9f..58fe5fb 100644 > --- a/include/linux/pci.h > +++ b/include/linux/pci.h > @@ -1420,6 +1420,8 @@ int ht_create_irq(struct pci_dev *dev, int idx); > void ht_destroy_irq(unsigned int irq); > #endif /* CONFIG_HT_IRQ */ > > +bool is_pcie_ats_disabled(void); > + > #ifdef CONFIG_PCI_ATS > /* Address Translation Service */ > void pci_ats_init(struct pci_dev *dev); > -- > 2.7.4 >