[prev in list] [next in list] [prev in thread] [next in thread] 

List:       xen-devel
Subject:    [Xen-devel] [PATCH 3/5] AMD IOMMU: bug fix and code cleanup
From:       Wei Wang2 <wei.wang2 () amd ! com>
Date:       2008-07-31 12:28:41
Message-ID: 1217507321.27350.124.camel () osrc57 ! amd ! com
[Download RAW message or body]

detect.patch: Remove pci scanning, parse acpi structures to detect iommu
hardware.

-Wei

Signed-off-by: Wei Wang <wei.wang2@amd.com>
-- 
AMD Saxony, Dresden, Germany
Operating System Research Center

Legal Information:
AMD Saxony Limited Liability Company & Co. KG
Sitz (Geschäftsanschrift):
   Wilschdorfer Landstr. 101, 01109 Dresden, Deutschland
Registergericht Dresden: HRA 4896
vertretungsberechtigter Komplementär:
   AMD Saxony LLC (Sitz Wilmington, Delaware, USA)
Geschäftsführer der AMD Saxony LLC:
   Dr. Hans-R. Deppe, Thomas McCoy

["detect.patch" (detect.patch)]

diff -r 9ee2e41a68a1 xen/drivers/passthrough/amd/iommu_detect.c
--- a/xen/drivers/passthrough/amd/iommu_detect.c	Wed Jul 30 15:25:09 2008 +0100
+++ b/xen/drivers/passthrough/amd/iommu_detect.c	Wed Jul 30 17:16:25 2008 +0200
@@ -25,65 +25,10 @@
 #include <xen/pci_regs.h>
 #include <asm/amd-iommu.h>
 #include <asm/hvm/svm/amd-iommu-proto.h>
+#include <asm/hvm/svm/amd-iommu-acpi.h>
 
-static int __init valid_bridge_bus_config(
-    int bus, int dev, int func, int *sec_bus, int *sub_bus)
-{
-    int pri_bus;
-
-    pri_bus = pci_conf_read8(bus, dev, func, PCI_PRIMARY_BUS);
-    *sec_bus = pci_conf_read8(bus, dev, func, PCI_SECONDARY_BUS);
-    *sub_bus = pci_conf_read8(bus, dev, func, PCI_SUBORDINATE_BUS);
-
-    return ((pri_bus == bus) && (*sec_bus > bus) && (*sub_bus >= *sec_bus));
-}
-
-int __init get_iommu_last_downstream_bus(struct amd_iommu *iommu)
-{
-    int bus, dev, func;
-    int devfn, hdr_type;
-    int sec_bus, sub_bus;
-    int multi_func;
-
-    bus = iommu->last_downstream_bus = iommu->root_bus;
-    iommu->downstream_bus_present[bus] = 1;
-    dev = PCI_SLOT(iommu->first_devfn);
-    multi_func = PCI_FUNC(iommu->first_devfn) > 0;
-    for ( devfn = iommu->first_devfn; devfn <= iommu->last_devfn; devfn++ )
-    {
-        /* skipping to next device#? */
-        if ( dev != PCI_SLOT(devfn) )
-        {
-            dev = PCI_SLOT(devfn);
-            multi_func = 0;
-        }
-        func = PCI_FUNC(devfn);
- 
-        if ( !VALID_PCI_VENDOR_ID(pci_conf_read16(bus, dev, func,
-                                                  PCI_VENDOR_ID)) )
-            continue;
-
-        hdr_type = pci_conf_read8(bus, dev, func, PCI_HEADER_TYPE);
-        if ( func == 0 )
-            multi_func = IS_PCI_MULTI_FUNCTION(hdr_type);
-
-        if ( (func == 0 || multi_func) &&
-             IS_PCI_TYPE1_HEADER(hdr_type) )
-        {
-            if ( !valid_bridge_bus_config(bus, dev, func,
-                                          &sec_bus, &sub_bus) )
-                return -ENODEV;
-
-            if ( sub_bus > iommu->last_downstream_bus )
-                iommu->last_downstream_bus = sub_bus;
-            do {
-                iommu->downstream_bus_present[sec_bus] = 1;
-            } while ( sec_bus++ < sub_bus );
-        }
-    }
-
-    return 0;
-}
+extern struct list_head amd_iommu_head;
+unsigned short last_bdf = 0;
 
 static int __init get_iommu_msi_capabilities(u8 bus, u8 dev, u8 func,
             struct amd_iommu *iommu)
@@ -128,30 +73,10 @@ int __init get_iommu_capabilities(u8 bus
                                   struct amd_iommu *iommu)
 {
     u32 cap_header, cap_range, misc_info;
-    u64 mmio_bar;
-
-    mmio_bar = (u64)pci_conf_read32(
-        bus, dev, func, cap_ptr + PCI_CAP_MMIO_BAR_HIGH_OFFSET) << 32;
-    mmio_bar |= pci_conf_read32(bus, dev, func,
-                                cap_ptr + PCI_CAP_MMIO_BAR_LOW_OFFSET);
-    iommu->mmio_base_phys = mmio_bar & (u64)~0x3FFF;
-
-    if ( ((mmio_bar & 0x1) == 0) || (iommu->mmio_base_phys == 0) )
-    {
-        amd_iov_error("Invalid MMIO_BAR = 0x%"PRIx64"\n", mmio_bar);
-        return -ENODEV;
-    }
-
-    iommu->bdf = (bus << 8) | PCI_DEVFN(dev, func);
-    iommu->cap_offset = cap_ptr;
 
     cap_header = pci_conf_read32(bus, dev, func, cap_ptr);
     iommu->revision = get_field_from_reg_u32(
         cap_header, PCI_CAP_REV_MASK, PCI_CAP_REV_SHIFT);
-    iommu->iotlb_support = get_field_from_reg_u32(
-        cap_header, PCI_CAP_IOTLB_MASK, PCI_CAP_IOTLB_SHIFT);
-    iommu->ht_tunnel_support = get_field_from_reg_u32(
-        cap_header, PCI_CAP_HT_TUNNEL_MASK, PCI_CAP_HT_TUNNEL_SHIFT);
     iommu->pte_not_present_cached = get_field_from_reg_u32(
         cap_header, PCI_CAP_NP_CACHE_MASK, PCI_CAP_NP_CACHE_SHIFT);
 
@@ -159,96 +84,76 @@ int __init get_iommu_capabilities(u8 bus
                                 cap_ptr + PCI_CAP_RANGE_OFFSET);
     iommu->unit_id = get_field_from_reg_u32(
         cap_range, PCI_CAP_UNIT_ID_MASK, PCI_CAP_UNIT_ID_SHIFT);
-    iommu->root_bus = get_field_from_reg_u32(
-        cap_range, PCI_CAP_BUS_NUMBER_MASK, PCI_CAP_BUS_NUMBER_SHIFT);
-    iommu->first_devfn = get_field_from_reg_u32(
-        cap_range, PCI_CAP_FIRST_DEVICE_MASK, PCI_CAP_FIRST_DEVICE_SHIFT);
-    iommu->last_devfn = get_field_from_reg_u32(
-        cap_range, PCI_CAP_LAST_DEVICE_MASK, PCI_CAP_LAST_DEVICE_SHIFT);
 
     misc_info = pci_conf_read32(bus, dev, func,
                                 cap_ptr + PCI_MISC_INFO_OFFSET);
     iommu->msi_number = get_field_from_reg_u32(
         misc_info, PCI_CAP_MSI_NUMBER_MASK, PCI_CAP_MSI_NUMBER_SHIFT);
 
+    return 0;
+}
+
+int __init amd_iommu_detect_one_acpi(void *ivhd)
+{
+    struct amd_iommu *iommu;
+    u8 bus, dev, func;
+    struct acpi_ivhd_block_header *ivhd_block;
+
+    ivhd_block = (struct acpi_ivhd_block_header *)ivhd;
+
+    if ( ivhd_block->header.length < sizeof(struct acpi_ivhd_block_header) )
+    {
+        amd_iov_error("Invalid IVHD Block Length!\n");
+        return -ENODEV;
+    }
+
+    if ( !ivhd_block->header.dev_id ||
+        !ivhd_block->cap_offset || !ivhd_block->mmio_base)
+    {
+        amd_iov_error("Invalid IVHD Block!\n");
+        return -ENODEV;
+    }
+
+    iommu = (struct amd_iommu *) xmalloc(struct amd_iommu);
+    if ( !iommu )
+    {
+        amd_iov_error("Error allocating amd_iommu\n");
+        return -ENOMEM;
+    }
+    memset(iommu, 0, sizeof(struct amd_iommu));
+
+    spin_lock_init(&iommu->lock);
+
+    iommu->bdf = ivhd_block->header.dev_id;
+    iommu->cap_offset = ivhd_block->cap_offset;
+    iommu->mmio_base_phys = ivhd_block->mmio_base;
+
+    /* override IOMMU support flags */
+    iommu->coherent = get_field_from_byte(ivhd_block->header.flags,
+                        AMD_IOMMU_ACPI_COHERENT_MASK,
+                        AMD_IOMMU_ACPI_COHERENT_SHIFT);
+    iommu->iotlb_support = get_field_from_byte(ivhd_block->header.flags,
+                        AMD_IOMMU_ACPI_IOTLB_SUP_MASK,
+                        AMD_IOMMU_ACPI_IOTLB_SUP_SHIFT);
+    iommu->isochronous = get_field_from_byte(ivhd_block->header.flags,
+                        AMD_IOMMU_ACPI_ISOC_MASK,
+                        AMD_IOMMU_ACPI_ISOC_SHIFT);
+    iommu->res_pass_pw = get_field_from_byte(ivhd_block->header.flags,
+                        AMD_IOMMU_ACPI_RES_PASS_PW_MASK,
+                        AMD_IOMMU_ACPI_RES_PASS_PW_SHIFT);
+    iommu->pass_pw = get_field_from_byte(ivhd_block->header.flags,
+                        AMD_IOMMU_ACPI_PASS_PW_MASK,
+                        AMD_IOMMU_ACPI_PASS_PW_SHIFT);
+    iommu->ht_tunnel_enable = get_field_from_byte(ivhd_block->header.flags,
+                        AMD_IOMMU_ACPI_HT_TUN_ENB_MASK,
+                        AMD_IOMMU_ACPI_HT_TUN_ENB_SHIFT);
+    bus = iommu->bdf >> 8;
+    dev = PCI_SLOT(iommu->bdf & 0xFF);
+    func = PCI_FUNC(iommu->bdf & 0xFF);
+    get_iommu_capabilities(bus, dev, func, iommu->cap_offset, iommu);
     get_iommu_msi_capabilities(bus, dev, func, iommu);
+
+    list_add_tail(&iommu->list, &amd_iommu_head);
 
     return 0;
 }
-
-static int __init scan_caps_for_iommu(
-    int bus, int dev, int func,
-    iommu_detect_callback_ptr_t iommu_detect_callback)
-{
-    int cap_ptr, cap_id, cap_type;
-    u32 cap_header;
-    int count, error = 0;
-
-    count = 0;
-    cap_ptr = pci_conf_read8(bus, dev, func, PCI_CAPABILITY_LIST);
-    while ( (cap_ptr >= PCI_MIN_CAP_OFFSET) &&
-            (count < PCI_MAX_CAP_BLOCKS) &&
-            !error )
-    {
-        cap_ptr &= PCI_CAP_PTR_MASK;
-        cap_header = pci_conf_read32(bus, dev, func, cap_ptr);
-        cap_id = get_field_from_reg_u32(
-            cap_header, PCI_CAP_ID_MASK, PCI_CAP_ID_SHIFT);
-
-        if ( cap_id == PCI_CAP_ID_SECURE_DEVICE )
-        {
-            cap_type = get_field_from_reg_u32(
-                cap_header, PCI_CAP_TYPE_MASK, PCI_CAP_TYPE_SHIFT);
-            if ( cap_type == PCI_CAP_TYPE_IOMMU )
-                error = iommu_detect_callback(
-                    bus, dev, func, cap_ptr);
-        }
-
-        cap_ptr = get_field_from_reg_u32(
-            cap_header, PCI_CAP_NEXT_PTR_MASK, PCI_CAP_NEXT_PTR_SHIFT);
-        count++;
-    }
-
-    return error;
-}
-
-static int __init scan_functions_for_iommu(
-    int bus, int dev, iommu_detect_callback_ptr_t iommu_detect_callback)
-{
-    int func, hdr_type;
-    int count = 1, error = 0;
-
-    for ( func = 0;
-          (func < count) && !error &&
-              VALID_PCI_VENDOR_ID(pci_conf_read16(bus, dev, func,
-                                                  PCI_VENDOR_ID));
-          func++ )
-
-    {
-        hdr_type = pci_conf_read8(bus, dev, func, PCI_HEADER_TYPE);
-
-        if ( (func == 0) && IS_PCI_MULTI_FUNCTION(hdr_type) )
-            count = PCI_MAX_FUNC_COUNT;
-
-        if ( IS_PCI_TYPE0_HEADER(hdr_type) ||
-             IS_PCI_TYPE1_HEADER(hdr_type) )
-            error = scan_caps_for_iommu(bus, dev, func,
-                                        iommu_detect_callback);
-    }
-
-    return error;
-}
-
-
-int __init scan_for_iommu(iommu_detect_callback_ptr_t iommu_detect_callback)
-{
-    int bus, dev, error = 0;
-
-    for ( bus = 0; bus < PCI_MAX_BUS_COUNT && !error; ++bus )
-        for ( dev = 0; dev < PCI_MAX_DEV_COUNT && !error; ++dev )
-            error = scan_functions_for_iommu(bus, dev,
-                                             iommu_detect_callback);
-
-    return error;
-}
-


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic