[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/1] x86/AMD: Fix setup ssss:bb:dd:f for d0 failed



From: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>

The host bridge device (i.e. 0x18 for AMD) does not
require IOMMU, and therefore is not included in the IVRS.
The current logic tries to map all PCI devices to an IOMMU. 
In this case, "xl dmesg" shows the following message on AMD sytem.

(XEN) setup 0000:00:18.0 for d0 failed (-19)
(XEN) setup 0000:00:18.1 for d0 failed (-19)
(XEN) setup 0000:00:18.2 for d0 failed (-19)
(XEN) setup 0000:00:18.3 for d0 failed (-19)
(XEN) setup 0000:00:18.4 for d0 failed (-19)
(XEN) setup 0000:00:18.5 for d0 failed (-19)

This patch add new device type (i.e. DEV_TYPE_PCI_HOST_BRIDGE) which
is corresponded to PCI class code 0x06 and sub-class 0x00. Then, it
use this new type to filter when trying to map device to IOMMU.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>
---
 xen/drivers/passthrough/amd/pci_amd_iommu.c |   20 +++++++++++++----
 xen/drivers/passthrough/pci.c               |   31 ++++++++++++++++-----------
 xen/drivers/passthrough/vtd/iommu.c         |    2 ++
 xen/include/xen/pci.h                       |    1 +
 4 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c 
b/xen/drivers/passthrough/amd/pci_amd_iommu.c
index 9684ae8..0bb954a 100644
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c
@@ -175,10 +175,22 @@ static int __init amd_iommu_setup_dom0_device(u8 devfn, 
struct pci_dev *pdev)
 
     if ( unlikely(!iommu) )
     {
-        AMD_IOMMU_DEBUG("No iommu for device %04x:%02x:%02x.%u\n",
-                        pdev->seg, pdev->bus,
-                        PCI_SLOT(devfn), PCI_FUNC(devfn));
-        return -ENODEV;
+        /* Filter the bridge devices */
+        if ( (pdev->type == DEV_TYPE_PCIe_BRIDGE)
+        ||   (pdev->type == DEV_TYPE_PCIe2PCI_BRIDGE)
+        ||   (pdev->type == DEV_TYPE_LEGACY_PCI_BRIDGE)
+        ||   (pdev->type == DEV_TYPE_PCI_HOST_BRIDGE) )
+        {
+            AMD_IOMMU_DEBUG("Skipping device %04x:%02x:%02x.%u (type %x)\n",
+                        pdev->seg, PCI_BUS(bdf), PCI_SLOT(bdf), PCI_FUNC(bdf),
+                        pdev->type);
+            return 0;
+        } else {
+            AMD_IOMMU_DEBUG("No iommu for device %04x:%02x:%02x.%u\n",
+                    pdev->seg, pdev->bus,
+                    PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+            return -ENODEV;
+        }
     }
 
     amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev);
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index f2756c9..0b94fc4 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -189,9 +189,6 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 
bus, u8 devfn)
         u16 cap;
         u8 sec_bus, sub_bus;
 
-        case DEV_TYPE_PCIe_BRIDGE:
-            break;
-
         case DEV_TYPE_PCIe2PCI_BRIDGE:
         case DEV_TYPE_LEGACY_PCI_BRIDGE:
             sec_bus = pci_conf_read8(pseg->nr, bus, PCI_SLOT(devfn),
@@ -239,6 +236,8 @@ static struct pci_dev *alloc_pdev(struct pci_seg *pseg, u8 
bus, u8 devfn)
             break;
 
         case DEV_TYPE_PCI:
+        case DEV_TYPE_PCI_HOST_BRIDGE:
+        case DEV_TYPE_PCIe_BRIDGE:
             break;
 
         default:
@@ -691,35 +690,43 @@ void pci_release_devices(struct domain *d)
     spin_unlock(&pcidevs_lock);
 }
 
-#define PCI_CLASS_BRIDGE_PCI     0x0604
+#define PCI_CLASS_HOST_PCI_BRIDGE    0x0600
+#define PCI_CLASS_PCI_PCI_BRIDGE     0x0604
 
 enum pdev_type pdev_type(u16 seg, u8 bus, u8 devfn)
 {
-    u16 class_device, creg;
+    u16 creg;
     u8 d = PCI_SLOT(devfn), f = PCI_FUNC(devfn);
-    int pos = pci_find_cap_offset(seg, bus, d, f, PCI_CAP_ID_EXP);
+    u16 class_device = pci_conf_read16(seg, bus, d, f, PCI_CLASS_DEVICE);
+    int cap_offset = pci_find_cap_offset(seg, bus, d, f, PCI_CAP_ID_EXP);
 
-    class_device = pci_conf_read16(seg, bus, d, f, PCI_CLASS_DEVICE);
     switch ( class_device )
     {
-    case PCI_CLASS_BRIDGE_PCI:
-        if ( !pos )
+    case PCI_CLASS_PCI_PCI_BRIDGE:
+        if ( !cap_offset )
             return DEV_TYPE_LEGACY_PCI_BRIDGE;
-        creg = pci_conf_read16(seg, bus, d, f, pos + PCI_EXP_FLAGS);
+
+        creg = pci_conf_read16(seg, bus, d, f, cap_offset + PCI_EXP_FLAGS);
+
         switch ( (creg & PCI_EXP_FLAGS_TYPE) >> 4 )
         {
         case PCI_EXP_TYPE_PCI_BRIDGE:
             return DEV_TYPE_PCIe2PCI_BRIDGE;
         case PCI_EXP_TYPE_PCIE_BRIDGE:
             return DEV_TYPE_PCI2PCIe_BRIDGE;
+        default: 
+            return DEV_TYPE_PCIe_BRIDGE;
         }
-        return DEV_TYPE_PCIe_BRIDGE;
+        break;
+
+    case PCI_CLASS_HOST_PCI_BRIDGE:
+        return DEV_TYPE_PCI_HOST_BRIDGE;
 
     case 0x0000: case 0xffff:
         return DEV_TYPE_PCI_UNKNOWN;
     }
 
-    return pos ? DEV_TYPE_PCIe_ENDPOINT : DEV_TYPE_PCI;
+    return cap_offset ? DEV_TYPE_PCIe_ENDPOINT : DEV_TYPE_PCI;
 }
 
 /*
diff --git a/xen/drivers/passthrough/vtd/iommu.c 
b/xen/drivers/passthrough/vtd/iommu.c
index 76f7b8e..046262c 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -1448,6 +1448,7 @@ static int domain_context_mapping(
         break;
 
     case DEV_TYPE_PCI:
+    case DEV_TYPE_PCI_HOST_BRIDGE:
         if ( iommu_verbose )
             dprintk(VTDPREFIX, "d%d:PCI: map %04x:%02x:%02x.%u\n",
                     domain->domain_id, seg, bus,
@@ -1577,6 +1578,7 @@ static int domain_context_unmap(
         break;
 
     case DEV_TYPE_PCI:
+    case DEV_TYPE_PCI_HOST_BRIDGE:
         if ( iommu_verbose )
             dprintk(VTDPREFIX, "d%d:PCI: unmap %04x:%02x:%02x.%u\n",
                     domain->domain_id, seg, bus, PCI_SLOT(devfn), 
PCI_FUNC(devfn));
diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
index ca72a99..2530491 100644
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -73,6 +73,7 @@ struct pci_dev {
         DEV_TYPE_PCIe2PCI_BRIDGE,   // PCIe-to-PCI/PCIx bridge
         DEV_TYPE_PCI2PCIe_BRIDGE,   // PCI/PCIx-to-PCIe bridge
         DEV_TYPE_LEGACY_PCI_BRIDGE, // Legacy PCI bridge
+        DEV_TYPE_PCI_HOST_BRIDGE,   // PCI Host bridge
         DEV_TYPE_PCI,
     } type;
 
-- 
1.7.10.4



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.