WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Enable pci mmcfg and ATS for x86_64
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 02 Jun 2009 10:45:24 -0700
Delivery-date: Tue, 02 Jun 2009 10:47:02 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Enable pci mmcfg and ATS for x86_64, Xen patchbot-unstable <=