Ask Your Question
0

ACS override patch on Fedora 22

asked 2015-08-12 06:36:05 -0600

this post is marked as community wiki

This post is a wiki. Anyone with karma >750 is welcome to improve it.

Hi everybody, first of all sorry for my english, I'm learning it.

Let's start: I'm on 4.1.3-201.fc22.x86_64 kernel and I'm trying to make a passthrough of my MSI GTX 970 to a KVM Windows virtual machine. I followed this guide and I'm having some problems with IOMMU. As you can see the processor of Alex (the author of the guide) supports ACS, so his PCI-E devices have their own IOMMU group. In my IOMMU groups I have a lot of PCI-E devices in one single group as you can see there. This is because I haven't ACS on my processor (Intel i5-4590). As the author of the guide says:

If your grouping is not reasonable, or usable, you may be able to "fix" this by using the ACS override patch, but carefully consider the implications of doing this. There is a potential for putting your data at risk. Read my IOMMU groups article again to make sure you understand the issue.

Now I found an ACS override patch there (from Alex), but the actual kernel doesn't accept the patch because the source file quirks.c had a lot of changes from when the patch was wrote (fc20 or 21 I think). Obviously I tried to apply the patch manually, but my C++ skills aren't very good and I didn't understood the patch's source code completely.

Now my question is: there is an ACS patch for fc22? I tried to google but I didn't find anything. Also, there is a way to split IOMMU groups with something to perform a VGA passthrough and without the ACS support?

Thanks for your help, here there are some useful informations about my computer:

  • CPU: Intel i5-4590
  • Motherboard: MSI Z97 GUARD PRO (with 1.8 bios)
  • lspci -vvvnn output here
  • current kernel: 4.1.3-201.fc22.x86_64

The kernel cmdlines an vfio config are the same as this guide (the same above to perform the passthroug)

If you need something else let me know.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
0

answered 2015-09-08 10:58:43 -0600

I patched my kernel on debian 4.1.3 with the following diff which seems to work (The virtual machines runs correctly). The following patch should also work in fc (I only moved the code from the previous patch at the correct position) :

diff -r b5e813034943 Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt   Mon Sep 07 19:26:43 2015 +0200
+++ b/Documentation/kernel-parameters.txt   Tue Sep 08 17:52:02 2015 +0200
@@ -2819,6 +2819,16 @@
        nomsi   Do not use MSI for native PCIe PME signaling (this makes
            all PCIe root ports use INTx for all services).

+   pcie_acs_override =
+           [PCIE] Override missing PCIe ACS support for:
+       downstream
+           All downstream ports - full ACS capabilties
+       multifunction
+           All multifunction devices - multifunction ACS subset
+       id:nnnn:nnnn
+           Specfic device - full ACS capabilities
+           Specified as vid:did (vendor/device ID) in hex
+
    pcmv=       [HW,PCMCIA] BadgePAD 4

    pd_ignore_unused
diff -r b5e813034943 drivers/pci/quirks.c
--- a/drivers/pci/quirks.c  Mon Sep 07 19:26:43 2015 +0200
+++ b/drivers/pci/quirks.c  Tue Sep 08 17:52:02 2015 +0200
@@ -3661,6 +3661,108 @@
 /* Intel 82801, https://bugzilla.kernel.org/show_bug.cgi?id=44881#c49 */
 DECLARE_PCI_FIXUP_HEADER(0x8086, 0x244e, quirk_use_pcie_bridge_dma_alias);

+static bool acs_on_downstream;
+static bool acs_on_multifunction;
+
+#define NUM_ACS_IDS 16
+struct acs_on_id {
+   unsigned short vendor;
+   unsigned short device;
+};
+static struct acs_on_id acs_on_ids[NUM_ACS_IDS];
+static u8 max_acs_id;
+
+static __init int pcie_acs_override_setup(char *p)
+{
+   if (!p)
+       return -EINVAL;
+
+   while (*p) {
+       if (!strncmp(p, "downstream", 10))
+           acs_on_downstream = true;
+       if (!strncmp(p, "multifunction", 13))
+           acs_on_multifunction = true;
+       if (!strncmp(p, "id:", 3)) {
+           char opt[5];
+           int ret;
+           long val;
+
+           if (max_acs_id >= NUM_ACS_IDS - 1) {
+               pr_warn("Out of PCIe ACS override slots (%d)\n",
+                   NUM_ACS_IDS);
+               goto next;
+           }
+
+           p += 3;
+           snprintf(opt, 5, "%s", p);
+           ret = kstrtol(opt, 16, &val);
+           if (ret) {
+               pr_warn("PCIe ACS ID parse error %d\n", ret);
+               goto next;
+           }
+           acs_on_ids[max_acs_id].vendor = val;
+
+           p += strcspn(p, ":");
+           if (*p != ':') {
+               pr_warn("PCIe ACS invalid ID\n");
+               goto next;
+           }
+
+           p++;
+           snprintf(opt, 5, "%s", p);
+           ret = kstrtol(opt, 16, &val);
+           if (ret) {
+               pr_warn("PCIe ACS ID parse error %d\n", ret);
+               goto next;
+           }
+           acs_on_ids[max_acs_id].device = val;
+           max_acs_id++;
+       }
+next:
+       p += strcspn(p, ",");
+       if (*p == ',')
+           p++;
+   }
+
+   if (acs_on_downstream || acs_on_multifunction || max_acs_id)
+       pr_warn("Warning: PCIe ACS overrides enabled; This may allow non-IOMMU protected peer-to-peer DMA\n");
+
+   return 0;
+}
+early_param("pcie_acs_override", pcie_acs_override_setup);
+
+static int pcie_acs_overrides(struct pci_dev *dev, u16 acs_flags)
+{
+   int i;
+
+   /* Never override ACS for legacy devices or devices with ACS caps */
+   if (!pci_is_pcie(dev) ||
+       pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS))
+       return -ENOTTY;
+
+   for (i = 0; i < max_acs_id; i++)
+       if (acs_on_ids[i].vendor == dev->vendor &&
+           acs_on_ids[i].device == dev->device)
+           return 1;
+
+   switch (pci_pcie_type(dev)) {
+   case PCI_EXP_TYPE_DOWNSTREAM:
+   case PCI_EXP_TYPE_ROOT_PORT:
+       if (acs_on_downstream)
+           return 1;
+       break;
+   case PCI_EXP_TYPE_ENDPOINT:
+   case PCI_EXP_TYPE_UPSTREAM:
+   case PCI_EXP_TYPE_LEG_END:
+   case PCI_EXP_TYPE_RC_END:
+       if (acs_on_multifunction && dev->multifunction)
+           return 1;
+   }
+
+   return -ENOTTY;
+}
+
+
 /*
  * AMD has indicated that the devices below do not support peer-to-peer
  * in any system where they are found in the southbridge with an AMD
@@ -3855,6 +3957,7 @@
    { PCI_VENDOR_ID_INTEL, 0x10D9, pci_quirk_mf_endpoint_acs },
    /* Intel PCH root ports */
    { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },
+    { PCI_ANY_ID, PCI_ANY_ID, pcie_acs_overrides },
    { 0x19a2, 0x710, pci_quirk_mf_endpoint_acs }, /* Emulex BE3-R */
    { 0x10df, 0x720, pci_quirk_mf_endpoint_acs ...
(more)
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2015-08-12 06:36:05 -0600

Seen: 1,827 times

Last updated: Sep 08 '15