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

[Xen-changelog] [xen-unstable] Enable pci mmcfg and ATS for x86_64



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1243939774 -3600
# Node ID 42fe00c6f8b4e7f5c7c13ab8928d8dae24f19a72
# Parent  4294a04b24bc55ffc18215d85a9eda517935b816
Enable pci mmcfg and ATS for x86_64

This patch enables PCI MMCONFIG in xen and turns on hooks for ATS.

Signed-off-by: Allen Kay <allen.m.kay@xxxxxxxxx>
---
 xen/arch/x86/acpi/boot.c               |    2 
 xen/arch/x86/e820.c                    |   34 ++
 xen/arch/x86/pci.c                     |   49 ----
 xen/arch/x86/traps.c                   |    2 
 xen/arch/x86/x86_32/Makefile           |    1 
 xen/arch/x86/x86_32/pci.c              |   70 ++++++
 xen/arch/x86/x86_64/Makefile           |    4 
 xen/arch/x86/x86_64/acpi_mmcfg.c       |   98 ++++++++
 xen/arch/x86/x86_64/mmconfig-shared.c  |  382 +++++++++++++++++++++++++++++++++
 xen/arch/x86/x86_64/mmconfig.h         |   85 +++++++
 xen/arch/x86/x86_64/mmconfig_64.c      |  180 +++++++++++++++
 xen/arch/x86/x86_64/pci.c              |  109 +++++++++
 xen/drivers/passthrough/vtd/extern.h   |    6 
 xen/drivers/passthrough/vtd/ia64/ats.c |    8 
 xen/drivers/passthrough/vtd/iommu.c    |    2 
 xen/drivers/passthrough/vtd/qinval.c   |    2 
 xen/drivers/passthrough/vtd/x86/ats.c  |    8 
 xen/include/asm-x86/acpi.h             |    3 
 xen/include/asm-x86/config.h           |    8 
 xen/include/asm-x86/e820.h             |    1 
 xen/include/asm-x86/msr-index.h        |    2 
 xen/include/xen/pci.h                  |    5 
 22 files changed, 988 insertions(+), 73 deletions(-)

diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/acpi/boot.c
--- a/xen/arch/x86/acpi/boot.c  Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/arch/x86/acpi/boot.c  Tue Jun 02 11:49:34 2009 +0100
@@ -937,6 +937,8 @@ int __init acpi_boot_init(void)
 
        acpi_dmar_init();
 
+       acpi_mmcfg_init();
+
        return 0;
 }
 
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/e820.c
--- a/xen/arch/x86/e820.c       Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/arch/x86/e820.c       Tue Jun 02 11:49:34 2009 +0100
@@ -24,6 +24,40 @@ boolean_param("e820-verbose", e820_verbo
 boolean_param("e820-verbose", e820_verbose);
 
 struct e820map e820;
+
+/*
+ * This function checks if the entire range <start,end> is mapped with type.
+ *
+ * Note: this function only works correct if the e820 table is sorted and
+ * not-overlapping, which is the case
+ */
+int __init e820_all_mapped(u64 start, u64 end, unsigned type)
+{
+       int i;
+
+       for (i = 0; i < e820.nr_map; i++) {
+               struct e820entry *ei = &e820.map[i];
+
+               if (type && ei->type != type)
+                       continue;
+               /* is the region (part) in overlap with the current region ?*/
+               if (ei->addr >= end || ei->addr + ei->size <= start)
+                       continue;
+
+               /* if the region is at the beginning of <start,end> we move
+                * start to the end of the region since it's ok until there
+                */
+               if (ei->addr <= start)
+                       start = ei->addr + ei->size;
+               /*
+                * if start is now at or beyond end, we're done, full
+                * coverage
+                */
+               if (start >= end)
+                       return 1;
+       }
+       return 0;
+}
 
 static void __init add_memory_region(unsigned long long start,
                                      unsigned long long size, int type)
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/pci.c
--- a/xen/arch/x86/pci.c        Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/arch/x86/pci.c        Tue Jun 02 11:49:34 2009 +0100
@@ -6,9 +6,6 @@
 
 #include <xen/spinlock.h>
 #include <asm/io.h>
-
-#define PCI_CONF_ADDRESS(bus, dev, func, reg) \
-    (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3))
 
 static DEFINE_SPINLOCK(pci_config_lock);
 
@@ -69,49 +66,3 @@ void pci_conf_write(uint32_t cf8, uint8_
 
     spin_unlock_irqrestore(&pci_config_lock, flags);
 }
-
-uint8_t pci_conf_read8(
-    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
-{
-    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
-    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1);
-}
-
-uint16_t pci_conf_read16(
-    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
-{
-    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
-    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2);
-}
-
-uint32_t pci_conf_read32(
-    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
-{
-    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
-    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4);
-}
-
-void pci_conf_write8(
-    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
-    uint8_t data)
-{
-    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
-    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1, data);
-}
-
-void pci_conf_write16(
-    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
-    uint16_t data)
-{
-    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
-    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2, data);
-}
-
-void pci_conf_write32(
-    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
-    uint32_t data)
-{
-    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
-    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4, data);
-}
-
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/arch/x86/traps.c      Tue Jun 02 11:49:34 2009 +0100
@@ -2186,7 +2186,7 @@ static int emulate_privileged_op(struct 
                 break;
             if ( (rdmsr_safe(MSR_FAM10H_MMIO_CONF_BASE, l, h) != 0) ||
                  (((((u64)h << 32) | l) ^ res) &
-                  ~((1 << FAM10H_MMIO_CONF_ENABLE_BIT) |
+                  ~( FAM10H_MMIO_CONF_ENABLE |
                     (FAM10H_MMIO_CONF_BUSRANGE_MASK <<
                      FAM10H_MMIO_CONF_BUSRANGE_SHIFT) |
                     ((u64)FAM10H_MMIO_CONF_BASE_MASK <<
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_32/Makefile
--- a/xen/arch/x86/x86_32/Makefile      Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/arch/x86/x86_32/Makefile      Tue Jun 02 11:49:34 2009 +0100
@@ -5,6 +5,7 @@ obj-y += seg_fixup.o
 obj-y += seg_fixup.o
 obj-y += traps.o
 obj-y += machine_kexec.o
+obj-y += pci.o
 
 obj-$(crash_debug) += gdbstub.o
 
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_32/pci.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/x86_32/pci.c Tue Jun 02 11:49:34 2009 +0100
@@ -0,0 +1,70 @@
+/******************************************************************************
+ * pci.c
+ * 
+ * Architecture-dependent PCI access functions.
+ */
+
+#include <xen/spinlock.h>
+#include <xen/pci.h>
+#include <asm/io.h>
+
+#define PCI_CONF_ADDRESS(bus, dev, func, reg) \
+    (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3))
+
+uint32_t pci_conf_read(uint32_t cf8, uint8_t offset, uint8_t bytes);
+void pci_conf_write(uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t 
data);
+
+uint8_t pci_conf_read8(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
+{
+    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
+    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1);
+}
+
+uint16_t pci_conf_read16(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
+{
+    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
+    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2);
+}
+
+uint32_t pci_conf_read32(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
+{
+    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
+    return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4);
+}
+
+void pci_conf_write8(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
+    uint8_t data)
+{
+    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
+    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1, data);
+}
+
+void pci_conf_write16(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
+    uint16_t data)
+{
+    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
+    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2, data);
+}
+
+void pci_conf_write32(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
+    uint32_t data)
+{
+    BUG_ON((bus > 255) || (dev > 31) || (func > 7) || (reg > 255));
+    pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4, data);
+}
+
+int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
+{
+    return 0;
+}
+
+void acpi_mmcfg_init(void)
+{
+    return;
+}
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/Makefile
--- a/xen/arch/x86/x86_64/Makefile      Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/arch/x86/x86_64/Makefile      Tue Jun 02 11:49:34 2009 +0100
@@ -5,6 +5,10 @@ obj-y += mm.o
 obj-y += mm.o
 obj-y += traps.o
 obj-y += machine_kexec.o
+obj-y += pci.o
+obj-y += acpi_mmcfg.o
+obj-y += mmconfig_64.o
+obj-y += mmconfig-shared.o
 
 obj-$(crash_debug)   += gdbstub.o
 obj-$(CONFIG_COMPAT) += compat.o
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/acpi_mmcfg.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/x86_64/acpi_mmcfg.c  Tue Jun 02 11:49:34 2009 +0100
@@ -0,0 +1,98 @@
+/*
+ *  acpi_mmconfig.c - Architecture-Specific Low-Level ACPI Boot Support
+ *
+ *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@xxxxxxxxx>
+ *  Copyright (C) 2001 Jun Nakajima <jun.nakajima@xxxxxxxxx>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * copied from Linux
+ */
+
+#include <xen/config.h>
+#include <xen/errno.h>
+#include <xen/init.h>
+#include <xen/acpi.h>
+#include <xen/irq.h>
+#include <xen/dmi.h>
+#include <asm/fixmap.h>
+#include <asm/page.h>
+#include <asm/apic.h>
+#include <asm/io_apic.h>
+#include <asm/apic.h>
+#include <asm/io.h>
+#include <asm/mpspec.h>
+#include <asm/processor.h>
+#include <mach_apic.h>
+#include <mach_mpparse.h>
+
+#include "mmconfig.h"
+
+/* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
+struct acpi_mcfg_allocation *pci_mmcfg_config;
+int pci_mmcfg_config_num;
+
+static int acpi_mcfg_64bit_base_addr __initdata = FALSE;
+
+int acpi_parse_mcfg(struct acpi_table_header *header)
+{
+    struct acpi_table_mcfg *mcfg;
+    unsigned long i;
+    int config_size;
+
+    if (!header)
+        return -EINVAL;
+
+    mcfg = (struct acpi_table_mcfg *)header;
+
+    /* how many config structures do we have */
+    pci_mmcfg_config_num = 0;
+    i = header->length - sizeof(struct acpi_table_mcfg);
+    while (i >= sizeof(struct acpi_mcfg_allocation)) {
+        ++pci_mmcfg_config_num;
+        i -= sizeof(struct acpi_mcfg_allocation);
+    };
+    if (pci_mmcfg_config_num == 0) {
+        printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
+        return -ENODEV;
+    }
+
+    config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config);
+    pci_mmcfg_config = xmalloc_bytes(config_size);
+    if (!pci_mmcfg_config) {
+        printk(KERN_WARNING PREFIX
+               "No memory for MCFG config tables\n");
+        return -ENOMEM;
+    }
+
+    memcpy(pci_mmcfg_config, &mcfg[1], config_size);
+
+    for (i = 0; i < pci_mmcfg_config_num; ++i) {
+        if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) &&
+            !acpi_mcfg_64bit_base_addr) {
+            printk(KERN_ERR PREFIX
+                   "MMCONFIG not in low 4GB of memory\n");
+            xfree(pci_mmcfg_config);
+            pci_mmcfg_config_num = 0;
+            return -ENODEV;
+        }
+    }
+
+    return 0;
+}
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/mmconfig-shared.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/x86_64/mmconfig-shared.c     Tue Jun 02 11:49:34 2009 +0100
@@ -0,0 +1,382 @@
+/*
+ * mmconfig-shared.c - Low-level direct PCI config space access via
+ *                     MMCONFIG - common code between i386 and x86-64.
+ *
+ * This code does:
+ * - known chipset handling
+ * - ACPI decoding and validation
+ *
+ * Per-architecture code takes care of the mappings and accesses
+ * themselves.
+ *
+ * Author: Allen Kay <allen.m.kay@xxxxxxxxx> -  adapted to xen from Linux
+ */
+
+#include <xen/mm.h>
+#include <xen/acpi.h>
+#include <xen/xmalloc.h>
+#include <xen/pci.h>
+#include <xen/pci_regs.h>
+#include <asm/e820.h>
+#include <asm/msr.h>
+#include <asm/msr-index.h>
+
+#include "mmconfig.h"
+
+static int __initdata known_bridge;
+unsigned int pci_probe = PCI_PROBE_CONF1 | PCI_PROBE_MMCONF;
+
+static const char __init *pci_mmcfg_e7520(void)
+{
+    u32 win;
+    win = pci_conf_read16(0, 0, 0, 0xce);
+
+    win = win & 0xf000;
+    if(win == 0x0000 || win == 0xf000)
+        pci_mmcfg_config_num = 0;
+    else {
+        pci_mmcfg_config_num = 1;
+        pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0]));
+        if (!pci_mmcfg_config)
+            return NULL;
+        memset(pci_mmcfg_config, 0, sizeof(pci_mmcfg_config[0]));
+        pci_mmcfg_config[0].address = win << 16;
+        pci_mmcfg_config[0].pci_segment = 0;
+        pci_mmcfg_config[0].start_bus_number = 0;
+        pci_mmcfg_config[0].end_bus_number = 255;
+    }
+
+    return "Intel Corporation E7520 Memory Controller Hub";
+}
+
+static const char __init *pci_mmcfg_intel_945(void)
+{
+    u32 pciexbar, mask = 0, len = 0;
+
+    pci_mmcfg_config_num = 1;
+
+        pciexbar = pci_conf_read32(0, 0, 0, 0x48);
+
+    /* Enable bit */
+    if (!(pciexbar & 1))
+        pci_mmcfg_config_num = 0;
+
+    /* Size bits */
+    switch ((pciexbar >> 1) & 3) {
+    case 0:
+        mask = 0xf0000000U;
+        len  = 0x10000000U;
+        break;
+    case 1:
+        mask = 0xf8000000U;
+        len  = 0x08000000U;
+        break;
+    case 2:
+        mask = 0xfc000000U;
+        len  = 0x04000000U;
+        break;
+    default:
+        pci_mmcfg_config_num = 0;
+    }
+
+    /* Errata #2, things break when not aligned on a 256Mb boundary */
+    /* Can only happen in 64M/128M mode */
+
+    if ((pciexbar & mask) & 0x0fffffffU)
+        pci_mmcfg_config_num = 0;
+
+    /* Don't hit the APIC registers and their friends */
+    if ((pciexbar & mask) >= 0xf0000000U)
+        pci_mmcfg_config_num = 0;
+
+    if (pci_mmcfg_config_num) {
+        pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0]));
+        if (!pci_mmcfg_config)
+            return NULL;
+        memset(pci_mmcfg_config, 0, sizeof(pci_mmcfg_config[0]));
+        pci_mmcfg_config[0].address = pciexbar & mask;
+        pci_mmcfg_config[0].pci_segment = 0;
+        pci_mmcfg_config[0].start_bus_number = 0;
+        pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1;
+    }
+
+    return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub";
+}
+
+static const char __init *pci_mmcfg_amd_fam10h(void)
+{
+    u32 low, high, address;
+    u64 base, msr;
+    int i;
+    unsigned segnbits = 0, busnbits;
+
+    if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF))
+        return NULL;
+
+    address = MSR_FAM10H_MMIO_CONF_BASE;
+    if (rdmsr_safe(address, low, high))
+        return NULL;
+
+    msr = high;
+    msr <<= 32;
+    msr |= low;
+
+    /* mmconfig is not enable */
+    if (!(msr & FAM10H_MMIO_CONF_ENABLE))
+        return NULL;
+
+    base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
+
+    busnbits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
+                FAM10H_MMIO_CONF_BUSRANGE_MASK;
+
+    /*
+     * only handle bus 0 ?
+     * need to skip it
+     */
+    if (!busnbits)
+        return NULL;
+
+    if (busnbits > 8) {
+        segnbits = busnbits - 8;
+        busnbits = 8;
+    }
+
+    pci_mmcfg_config_num = (1 << segnbits);
+    pci_mmcfg_config = xmalloc_bytes(sizeof(pci_mmcfg_config[0]) *
+                                     pci_mmcfg_config_num);
+    if (!pci_mmcfg_config)
+        return NULL;
+
+    for (i = 0; i < (1 << segnbits); i++) {
+        pci_mmcfg_config[i].address = base + (1<<28) * i;
+        pci_mmcfg_config[i].pci_segment = i;
+        pci_mmcfg_config[i].start_bus_number = 0;
+        pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1;
+    }
+
+    return "AMD Family 10h NB";
+}
+
+struct pci_mmcfg_hostbridge_probe {
+    u32 bus;
+    u32 devfn;
+    u32 vendor;
+    u32 device;
+    const char *(*probe)(void);
+};
+
+static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = {
+    { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
+      PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 },
+    { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL,
+      PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 },
+    { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD,
+      0x1200, pci_mmcfg_amd_fam10h },
+    { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD,
+      0x1200, pci_mmcfg_amd_fam10h },
+};
+
+static int __init pci_mmcfg_check_hostbridge(void)
+{
+    u32 l;
+    u32 bus, devfn;
+    u16 vendor, device;
+    int i;
+    const char *name;
+
+    pci_mmcfg_config_num = 0;
+    pci_mmcfg_config = NULL;
+    name = NULL;
+
+    for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) {
+        bus =  pci_mmcfg_probes[i].bus;
+        devfn = pci_mmcfg_probes[i].devfn;
+        l = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), 0);
+        vendor = l & 0xffff;
+        device = (l >> 16) & 0xffff;
+
+        if (pci_mmcfg_probes[i].vendor == vendor &&
+            pci_mmcfg_probes[i].device == device)
+            name = pci_mmcfg_probes[i].probe();
+    }
+
+    if (name) {
+        printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n",
+            name, pci_mmcfg_config_num ? "with" : "without");
+    }
+
+    return name != NULL;
+}
+
+typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type);
+
+static int __init is_mmconf_reserved(
+    check_reserved_t is_reserved,
+    u64 addr, u64 size, int i,
+    typeof(pci_mmcfg_config[0]) *cfg, int with_e820)
+{
+    u64 old_size = size;
+    int valid = 0;
+
+    while (!is_reserved(addr, addr + size - 1, E820_RESERVED)) {
+        size >>= 1;
+        if (size < (16UL<<20))
+            break;
+    }
+
+    if (size >= (16UL<<20) || size == old_size) {
+        printk(KERN_NOTICE
+               "PCI: MCFG area at %lx reserved in %s\n",
+                addr, with_e820?"E820":"ACPI motherboard resources");
+        valid = 1;
+
+        if (old_size != size) {
+            /* update end_bus_number */
+            cfg->end_bus_number = cfg->start_bus_number + ((size>>20) - 1);
+            printk(KERN_NOTICE "PCI: updated MCFG configuration %d: base %lx "
+                   "segment %hu buses %u - %u\n",
+                   i, (unsigned long)cfg->address, cfg->pci_segment,
+                   (unsigned int)cfg->start_bus_number,
+                   (unsigned int)cfg->end_bus_number);
+        }
+    }
+
+    return valid;
+}
+
+static void __init pci_mmcfg_reject_broken(int early)
+{
+    typeof(pci_mmcfg_config[0]) *cfg;
+    int i;
+
+    if ((pci_mmcfg_config_num == 0) ||
+        (pci_mmcfg_config == NULL) ||
+        (pci_mmcfg_config[0].address == 0))
+        return;
+
+    cfg = &pci_mmcfg_config[0];
+
+    for (i = 0; i < pci_mmcfg_config_num; i++) {
+        int valid = 0;
+        u64 addr, size;
+
+        cfg = &pci_mmcfg_config[i];
+        addr = cfg->start_bus_number;
+        addr <<= 20;
+        addr += cfg->address;
+        size = cfg->end_bus_number + 1 - cfg->start_bus_number;
+        size <<= 20;
+        printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx "
+               "segment %hu buses %u - %u\n",
+               i, (unsigned long)cfg->address, cfg->pci_segment,
+               (unsigned int)cfg->start_bus_number,
+               (unsigned int)cfg->end_bus_number);
+
+        if (valid)
+            continue;
+
+        if (!early)
+            printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %lx is not"
+                   " reserved in ACPI motherboard resources\n",
+                   cfg->address);
+
+        valid = is_mmconf_reserved(e820_all_mapped, addr, size, i, cfg, 1);
+
+        if (!valid)
+            goto reject;
+    }
+
+    return;
+
+reject:
+    printk(KERN_INFO "PCI: Not using MMCONFIG.\n");
+    pci_mmcfg_arch_free();
+    xfree(pci_mmcfg_config);
+    pci_mmcfg_config = NULL;
+    pci_mmcfg_config_num = 0;
+}
+
+void __init __pci_mmcfg_init(int early)
+{
+    /* MMCONFIG disabled */
+    if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+        return;
+
+    /* MMCONFIG already enabled */
+    if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
+        return;
+
+    /* for late to exit */
+    if (known_bridge)
+        return;
+
+    if (early) {
+        if (pci_mmcfg_check_hostbridge())
+            known_bridge = 1;
+    }
+
+    if (!known_bridge) {
+        acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
+        pci_mmcfg_reject_broken(early);
+    }
+
+    if ((pci_mmcfg_config_num == 0) ||
+        (pci_mmcfg_config == NULL) ||
+        (pci_mmcfg_config[0].address == 0))
+        return;
+
+    if (pci_mmcfg_arch_init()) {
+        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
+    }
+}
+
+void acpi_mmcfg_init(void)
+{
+    __pci_mmcfg_init(1);
+}
+
+/**
+ * pci_find_ext_capability - Find an extended capability
+ * @dev: PCI device to query
+ * @cap: capability code
+ *
+ * Returns the address of the requested extended capability structure
+ * within the device's PCI configuration space or 0 if the device does
+ * not support it.  Possible values for @cap:
+ *
+ *  %PCI_EXT_CAP_ID_ERR         Advanced Error Reporting
+ *  %PCI_EXT_CAP_ID_VC          Virtual Channel
+ *  %PCI_EXT_CAP_ID_DSN         Device Serial Number
+ *  %PCI_EXT_CAP_ID_PWR         Power Budgeting
+ */
+int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
+{
+    u32 header;
+    int ttl = 480; /* 3840 bytes, minimum 8 bytes per capability */
+    int pos = 0x100;
+
+    header = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
+
+    /*
+     * If we have no capabilities, this is indicated by cap ID,
+     * cap version and next pointer all being 0.
+     */
+    if ( (header == 0) || (header == -1) )
+    {
+        dprintk(XENLOG_INFO VTDPREFIX,
+                "next cap:%x:%x.%x:  no extended config\n",
+                bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+        return 0;
+    }
+
+    while ( ttl-- > 0 ) {
+        if ( PCI_EXT_CAP_ID(header) == cap )
+            return pos;
+        pos = PCI_EXT_CAP_NEXT(header);
+        if ( pos < 0x100 )
+            break;
+        header = pci_conf_read32(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
+    }
+    return 0;
+}
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/mmconfig.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/x86_64/mmconfig.h    Tue Jun 02 11:49:34 2009 +0100
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Author: Allen Kay <allen.m.kay@xxxxxxxxx> - adapted from linux
+ */
+
+#define PCI_VENDOR_ID_INTEL        0x8086
+#define PCI_DEVICE_ID_INTEL_E7520_MCH    0x3590
+#define PCI_DEVICE_ID_INTEL_82945G_HB    0x2770
+
+/* ioport ends */
+#define PCI_PROBE_BIOS        0x0001
+#define PCI_PROBE_CONF1        0x0002
+#define PCI_PROBE_CONF2        0x0004
+#define PCI_PROBE_MMCONF    0x0008
+#define PCI_PROBE_MASK        0x000f
+#define PCI_PROBE_NOEARLY    0x0010
+
+#define PCI_VENDOR_ID_AMD             0x1022
+#define PCI_CHECK_ENABLE_AMD_MMCONF     0x20000
+
+/*
+ * AMD Fam10h CPUs are buggy, and cannot access MMIO config space
+ * on their northbrige except through the * %eax register. As such, you MUST
+ * NOT use normal IOMEM accesses, you need to only use the magic mmio-config
+ * accessor functions.
+ * In fact just use pci_config_*, nothing else please.
+ */
+static inline unsigned char mmio_config_readb(void __iomem *pos)
+{
+    u8 val;
+    asm volatile("movb (%1),%%al" : "=a" (val) : "r" (pos));
+    return val;
+}
+
+static inline unsigned short mmio_config_readw(void __iomem *pos)
+{
+    u16 val;
+    asm volatile("movw (%1),%%ax" : "=a" (val) : "r" (pos));
+    return val;
+}
+
+static inline unsigned int mmio_config_readl(void __iomem *pos)
+{
+    u32 val;
+    asm volatile("movl (%1),%%eax" : "=a" (val) : "r" (pos));
+    return val;
+}
+
+static inline void mmio_config_writeb(void __iomem *pos, u8 val)
+{
+    asm volatile("movb %%al,(%1)" :: "a" (val), "r" (pos) : "memory");
+}
+
+static inline void mmio_config_writew(void __iomem *pos, u16 val)
+{
+    asm volatile("movw %%ax,(%1)" :: "a" (val), "r" (pos) : "memory");
+}
+
+static inline void mmio_config_writel(void __iomem *pos, u32 val)
+{
+    asm volatile("movl %%eax,(%1)" :: "a" (val), "r" (pos) : "memory");
+}
+
+/* external variable defines */
+extern int pci_mmcfg_config_num;
+extern struct acpi_mcfg_allocation *pci_mmcfg_config;
+
+/* fucntion prototypes */
+int __init acpi_parse_mcfg(struct acpi_table_header *header);
+int __init pci_mmcfg_arch_init(void);
+void __init pci_mmcfg_arch_free(void);
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/mmconfig_64.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/x86_64/mmconfig_64.c Tue Jun 02 11:49:34 2009 +0100
@@ -0,0 +1,180 @@
+/*
+ * mmconfig.c - Low-level direct PCI config space access via MMCONFIG
+ *
+ * This is an 64bit optimized version that always keeps the full mmconfig
+ * space mapped. This allows lockless config space operation.
+ *
+ * copied from Linux
+ */
+
+#include <xen/mm.h>
+#include <xen/acpi.h>
+#include <xen/xmalloc.h>
+#include <xen/pci.h>
+#include <xen/pci_regs.h>
+
+#include "mmconfig.h"
+
+/* Static virtual mapping of the MMCONFIG aperture */
+struct mmcfg_virt {
+    struct acpi_mcfg_allocation *cfg;
+    char __iomem *virt;
+};
+static struct mmcfg_virt *pci_mmcfg_virt;
+
+static char __iomem *get_virt(unsigned int seg, unsigned bus)
+{
+    struct acpi_mcfg_allocation *cfg;
+    int cfg_num;
+
+    for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
+        cfg = pci_mmcfg_virt[cfg_num].cfg;
+        if (cfg->pci_segment == seg &&
+            (cfg->start_bus_number <= bus) &&
+            (cfg->end_bus_number >= bus))
+            return pci_mmcfg_virt[cfg_num].virt;
+    }
+
+    /* Fall back to type 0 */
+    return NULL;
+}
+
+static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned 
int devfn)
+{
+    char __iomem *addr;
+
+    addr = get_virt(seg, bus);
+    if (!addr)
+        return NULL;
+     return addr + ((bus << 20) | (devfn << 12));
+}
+
+int pci_mmcfg_read(unsigned int seg, unsigned int bus,
+              unsigned int devfn, int reg, int len, u32 *value)
+{
+    char __iomem *addr;
+
+    /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
+    if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
+err:        *value = -1;
+        return -EINVAL;
+    }
+
+    addr = pci_dev_base(seg, bus, devfn);
+    if (!addr)
+        goto err;
+
+    switch (len) {
+    case 1:
+        *value = mmio_config_readb(addr + reg);
+        break;
+    case 2:
+        *value = mmio_config_readw(addr + reg);
+        break;
+    case 4:
+        *value = mmio_config_readl(addr + reg);
+        break;
+    }
+
+    return 0;
+}
+
+int pci_mmcfg_write(unsigned int seg, unsigned int bus,
+               unsigned int devfn, int reg, int len, u32 value)
+{
+    char __iomem *addr;
+
+    /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
+    if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
+        return -EINVAL;
+
+    addr = pci_dev_base(seg, bus, devfn);
+    if (!addr)
+        return -EINVAL;
+
+    switch (len) {
+    case 1:
+        mmio_config_writeb(addr + reg, value);
+        break;
+    case 2:
+        mmio_config_writew(addr + reg, value);
+        break;
+    case 4:
+        mmio_config_writel(addr + reg, value);
+        break;
+    }
+
+    return 0;
+}
+
+static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg)
+{
+    void __iomem *addr;
+    unsigned long virt;
+    unsigned long mfn;
+    unsigned long size, nr_mfn;
+
+    printk("amk_mcfg_ioremap: PCI_MCFG_VIRT_START %lx\n", 
(u64)PCI_MCFG_VIRT_START); 
+    printk("amk_mcfg_ioremap: start_bus %x end_bus %x\n",
+               cfg->start_bus_number, cfg->end_bus_number);
+
+    virt = PCI_MCFG_VIRT_START + (cfg->pci_segment * (1 << 22)) +
+               (cfg->start_bus_number * (1 << 20));
+    mfn = cfg->address >> PAGE_SHIFT;
+        size = (cfg->end_bus_number - cfg->start_bus_number) << 20;
+        nr_mfn = size >> PAGE_SHIFT;
+
+    printk("amk_mcfg_ioremap: virt %lx mfn = %lx size %lx\n", virt, mfn, size);
+
+    map_pages_to_xen(virt, mfn, nr_mfn, PAGE_HYPERVISOR_NOCACHE);
+    addr = (void __iomem *) virt;
+
+    printk("amk_mcfg_ioremap: PCI_MCFG_VIRT_START %lx\n",
+        (u64)PCI_MCFG_VIRT_START); 
+    printk("amk_mcfg_ioremap: virt  %lx size %lx\n", virt, size);
+
+    return addr;
+}
+
+int __init pci_mmcfg_arch_init(void)
+{
+    int i;
+    pci_mmcfg_virt = xmalloc_bytes(sizeof(*pci_mmcfg_virt) * 
pci_mmcfg_config_num);
+    if (pci_mmcfg_virt == NULL) {
+        printk(KERN_ERR "PCI: Can not allocate memory for mmconfig 
structures\n");
+        return 0;
+    }
+    memset(pci_mmcfg_virt, 0, sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num);
+
+    for (i = 0; i < pci_mmcfg_config_num; ++i) {
+        pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
+        pci_mmcfg_virt[i].virt = mcfg_ioremap(&pci_mmcfg_config[i]);
+        if (!pci_mmcfg_virt[i].virt) {
+            printk(KERN_ERR "PCI: Cannot map mmconfig aperture for "
+                    "segment %d\n",
+                pci_mmcfg_config[i].pci_segment);
+            pci_mmcfg_arch_free();
+            return 0;
+        }
+    }
+    return 1;
+}
+
+void __init pci_mmcfg_arch_free(void)
+{
+    int i;
+
+    if (pci_mmcfg_virt == NULL)
+        return;
+
+    for (i = 0; i < pci_mmcfg_config_num; ++i) {
+        if (pci_mmcfg_virt[i].virt) {
+            iounmap(pci_mmcfg_virt[i].virt);
+            pci_mmcfg_virt[i].virt = NULL;
+            pci_mmcfg_virt[i].cfg = NULL;
+        }
+    }
+
+    xfree(pci_mmcfg_virt);
+    pci_mmcfg_virt = NULL;
+}
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/arch/x86/x86_64/pci.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/x86_64/pci.c Tue Jun 02 11:49:34 2009 +0100
@@ -0,0 +1,109 @@
+/******************************************************************************
+ * pci.c
+ * 
+ * Architecture-dependent PCI access functions.
+ */
+
+#include <xen/spinlock.h>
+#include <xen/pci.h>
+#include <asm/io.h>
+
+#define PCI_CONF_ADDRESS(bus, dev, func, reg) \
+    (0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg & ~3))
+
+int pci_mmcfg_read(unsigned int seg, unsigned int bus,
+                   unsigned int devfn, int reg, int len, u32 *value);
+int pci_mmcfg_write(unsigned int seg, unsigned int bus,
+                    unsigned int devfn, int reg, int len, u32 value);
+uint32_t pci_conf_read(uint32_t cf8, uint8_t offset, uint8_t bytes);
+void pci_conf_write(uint32_t cf8, uint8_t offset, uint8_t bytes, uint32_t 
data);
+
+uint8_t pci_conf_read8(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
+{
+    u32 value;
+
+    if ( reg > 255 )
+    {
+        pci_mmcfg_read(0, bus, PCI_DEVFN(dev, func), reg, 1, &value);
+        return value;
+    }
+    else
+    {
+        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
+        return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 
1);
+    }
+}
+
+uint16_t pci_conf_read16(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
+{
+    u32 value;
+
+    if ( reg > 255 )
+    {
+        pci_mmcfg_read(0, bus, PCI_DEVFN(dev, func), reg, 2, &value);
+        return value;
+    }
+    else
+    {
+        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
+        return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 
2);
+    }
+}
+
+uint32_t pci_conf_read32(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg)
+{
+    u32 value;
+
+    if ( reg > 255 )
+    {
+        pci_mmcfg_read(0, bus, PCI_DEVFN(dev, func), reg, 4, &value);
+        return value;
+    }
+    else
+    {
+        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
+        return pci_conf_read(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4);
+    }
+}
+
+void pci_conf_write8(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
+    uint8_t data)
+{
+    if ( reg > 255 )
+        pci_mmcfg_write(0, bus, PCI_DEVFN(dev, func), reg, 1, data);
+    else
+    {
+        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
+        pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 3, 1, 
data);
+    }
+}
+
+void pci_conf_write16(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
+    uint16_t data)
+{
+    if ( reg > 255 )
+        pci_mmcfg_write(0, bus, PCI_DEVFN(dev, func), reg, 2, data);
+    else
+    {
+        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
+        pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), reg & 2, 2, 
data);
+    }
+}
+
+void pci_conf_write32(
+    unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
+    uint32_t data)
+{
+    if ( reg > 255 )
+        pci_mmcfg_write(0, bus, PCI_DEVFN(dev, func), reg, 4, data);
+    else
+    {
+        BUG_ON((bus > 255) || (dev > 31) || (func > 7));
+        pci_conf_write(PCI_CONF_ADDRESS(bus, dev, func, reg), 0, 4, data);
+    }
+}
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/drivers/passthrough/vtd/extern.h
--- a/xen/drivers/passthrough/vtd/extern.h      Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/drivers/passthrough/vtd/extern.h      Tue Jun 02 11:49:34 2009 +0100
@@ -48,8 +48,14 @@ struct iommu * ioapic_to_iommu(unsigned 
 struct iommu * ioapic_to_iommu(unsigned int apic_id);
 struct acpi_drhd_unit * ioapic_to_drhd(unsigned int apic_id);
 void clear_fault_bits(struct iommu *iommu);
+int ats_device(int seg, int bus, int devfn);
+int enable_ats_device(int seg, int bus, int devfn);
+int disable_ats_device(int seg, int bus, int devfn);
+int invalidate_ats_tcs(struct iommu *iommu);
 int qinval_device_iotlb(struct iommu *iommu,
                         u32 max_invs_pend, u16 sid, u16 size, u64 addr);
+int dev_invalidate_iotlb(struct iommu *iommu, u16 did,
+                         u64 addr, unsigned int size_order, u64 type);
 struct acpi_drhd_unit * find_ats_dev_drhd(struct iommu *iommu);
 
 #endif // _VTD_EXTERN_H_
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/drivers/passthrough/vtd/ia64/ats.c
--- a/xen/drivers/passthrough/vtd/ia64/ats.c    Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/drivers/passthrough/vtd/ia64/ats.c    Tue Jun 02 11:49:34 2009 +0100
@@ -35,14 +35,6 @@ struct acpi_drhd_unit * find_ats_dev_drh
     return NULL;
 }
 
-/*
- * BUGBUG: return 0 until pcimmcfg is checked in.
- */
-int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
-{
-    return 0;
-}
-
 int ats_device(int seg, int bus, int devfn)
 {
     return 0;
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c       Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c       Tue Jun 02 11:49:34 2009 +0100
@@ -1663,10 +1663,8 @@ static void setup_dom0_devices(struct do
                 pdev->domain = d;
                 list_add(&pdev->domain_list, &d->arch.pdev_list);
                 domain_context_mapping(d, pdev->bus, pdev->devfn);
-#if defined(NOT_YET)
                 if ( ats_device(0, pdev->bus, pdev->devfn) )
                     enable_ats_device(0, pdev->bus, pdev->devfn);
-#endif
             }
         }
     }
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/drivers/passthrough/vtd/qinval.c
--- a/xen/drivers/passthrough/vtd/qinval.c      Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/drivers/passthrough/vtd/qinval.c      Tue Jun 02 11:49:34 2009 +0100
@@ -409,10 +409,8 @@ static int flush_iotlb_qi(
         ret = queue_invalidate_iotlb(iommu,
                   (type >> DMA_TLB_FLUSH_GRANU_OFFSET), dr,
                   dw, did, (u8)size_order, 0, addr);
-#if defined(NOT_YET)
         if ( flush_dev_iotlb )
             ret |= dev_invalidate_iotlb(iommu, did, addr, size_order, type);
-#endif
         ret |= invalidate_sync(iommu);
     }
     return ret;
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/drivers/passthrough/vtd/x86/ats.c
--- a/xen/drivers/passthrough/vtd/x86/ats.c     Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/drivers/passthrough/vtd/x86/ats.c     Tue Jun 02 11:49:34 2009 +0100
@@ -79,14 +79,6 @@ struct acpi_drhd_unit * find_ats_dev_drh
             return drhd;
     }
     return NULL;
-}
-
-/*
- * BUGBUG: return 0 until pcimmcfg is checked in.
- */
-int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
-{
-    return 0;
 }
 
 int ats_device(int seg, int bus, int devfn)
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/include/asm-x86/acpi.h
--- a/xen/include/asm-x86/acpi.h        Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/include/asm-x86/acpi.h        Tue Jun 02 11:49:34 2009 +0100
@@ -164,7 +164,8 @@ extern u8 x86_acpiid_to_apicid[];
 extern u8 x86_acpiid_to_apicid[];
 #define MAX_LOCAL_APIC 256
 
-extern int acpi_dmar_init(void);
+int acpi_dmar_init(void);
+void acpi_mmcfg_init(void);
 
 /* Incremented whenever we transition through S3. Value is 1 during boot. */
 extern uint32_t system_reset_counter;
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/include/asm-x86/config.h
--- a/xen/include/asm-x86/config.h      Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/include/asm-x86/config.h      Tue Jun 02 11:49:34 2009 +0100
@@ -135,7 +135,7 @@ extern unsigned int video_mode, video_fl
  *  0xffff804000000000 - 0xffff807fffffffff [256GB, 2^38 bytes, PML4:256]
  *    Reserved for future shared info with the guest OS (GUEST ACCESSIBLE).
  *  0xffff808000000000 - 0xffff80ffffffffff [512GB, 2^39 bytes, PML4:257]
- *    Reserved for future use.
+ *    ioremap for PCI mmconfig space
  *  0xffff810000000000 - 0xffff817fffffffff [512GB, 2^39 bytes, PML4:258]
  *    Guest linear page table.
  *  0xffff818000000000 - 0xffff81ffffffffff [512GB, 2^39 bytes, PML4:259]
@@ -188,6 +188,12 @@ extern unsigned int video_mode, video_fl
 /* Slot 256: read-only guest-accessible machine-to-phys translation table. */
 #define RO_MPT_VIRT_START       (PML4_ADDR(256))
 #define RO_MPT_VIRT_END         (RO_MPT_VIRT_START + PML4_ENTRY_BYTES/2)
+/* Slot 257: ioremap for PCI mmconfig space for 2048 segments (512GB)
+ *     - full 16-bit segment support needs 44 bits
+ *     - since PML4 slot has 39 bits, we limit segments to 2048 (11-bits)
+ */
+#define PCI_MCFG_VIRT_START     (PML4_ADDR(257))
+#define PCI_MCFG_VIRT_END       (RDWR_MPT_VIRT_START + PML4_ENTRY_BYTES)
 /* Slot 258: linear page table (guest table). */
 #define LINEAR_PT_VIRT_START    (PML4_ADDR(258))
 #define LINEAR_PT_VIRT_END      (LINEAR_PT_VIRT_START + PML4_ENTRY_BYTES)
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/include/asm-x86/e820.h
--- a/xen/include/asm-x86/e820.h        Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/include/asm-x86/e820.h        Tue Jun 02 11:49:34 2009 +0100
@@ -23,6 +23,7 @@ struct e820map {
     struct e820entry map[E820MAX];
 };
 
+extern int e820_all_mapped(u64 start, u64 end, unsigned type);
 extern int reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e);
 extern int e820_change_range_type(
     struct e820map *e820, uint64_t s, uint64_t e,
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/include/asm-x86/msr-index.h
--- a/xen/include/asm-x86/msr-index.h   Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/include/asm-x86/msr-index.h   Tue Jun 02 11:49:34 2009 +0100
@@ -231,7 +231,7 @@
 
 /* Other AMD Fam10h MSRs */
 #define MSR_FAM10H_MMIO_CONF_BASE      0xc0010058
-#define FAM10H_MMIO_CONF_ENABLE_BIT    0
+#define FAM10H_MMIO_CONF_ENABLE         (1<<0)
 #define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf
 #define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
 #define FAM10H_MMIO_CONF_BASE_MASK     0xfffffff
diff -r 4294a04b24bc -r 42fe00c6f8b4 xen/include/xen/pci.h
--- a/xen/include/xen/pci.h     Mon Jun 01 18:37:27 2009 +0100
+++ b/xen/include/xen/pci.h     Tue Jun 02 11:49:34 2009 +0100
@@ -93,8 +93,13 @@ void pci_conf_write32(
 void pci_conf_write32(
     unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg,
     uint32_t data);
+int pci_mmcfg_read(unsigned int seg, unsigned int bus,
+                   unsigned int devfn, int reg, int len, u32 *value);
+int pci_mmcfg_write(unsigned int seg, unsigned int bus,
+                    unsigned int devfn, int reg, int len, u32 value);
 int pci_find_cap_offset(u8 bus, u8 dev, u8 func, u8 cap);
 int pci_find_next_cap(u8 bus, unsigned int devfn, u8 pos, int cap);
+int pci_find_ext_capability(int seg, int bus, int devfn, int cap);
 
 int msixtbl_pt_register(struct domain *d, int pirq, uint64_t gtable);
 void msixtbl_pt_unregister(struct domain *d, int pirq);

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


 


Rackspace

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