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

[Xen-changelog] [xen-unstable] Move iommu code to arch-generic locations, and also clean up some VT-d code.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1205750724 0
# Node ID bf8a3fc79093daa3107952dd9b070299851862fe
# Parent  af33f2054f47b3cdc9de37e567b11986ca22a7f1
Move iommu code to arch-generic locations, and also clean up some VT-d code.
Signed-off-by: Weidong Han <weidong.han@xxxxxxxxx>
---
 xen/arch/x86/hvm/iommu.c                   |  145 ---------
 xen/drivers/passthrough/vtd/io.c           |  296 ------------------
 xen/include/asm-x86/hvm/iommu.h            |   56 ---
 xen/include/asm-x86/hvm/vmx/intel-iommu.h  |  460 -----------------------------
 xen/include/asm-x86/iommu.h                |  109 ------
 xen/arch/x86/domain.c                      |    2 
 xen/arch/x86/domctl.c                      |    2 
 xen/arch/x86/hvm/Makefile                  |    1 
 xen/arch/x86/hvm/intercept.c               |    2 
 xen/arch/x86/irq.c                         |    2 
 xen/arch/x86/mm/p2m.c                      |    2 
 xen/drivers/passthrough/Makefile           |    3 
 xen/drivers/passthrough/amd/iommu_detect.c |    2 
 xen/drivers/passthrough/amd/iommu_map.c    |    2 
 xen/drivers/passthrough/io.c               |  272 +++++++++++++++++
 xen/drivers/passthrough/iommu.c            |  136 ++++++++
 xen/drivers/passthrough/vtd/Makefile       |    1 
 xen/drivers/passthrough/vtd/dmar.h         |    2 
 xen/drivers/passthrough/vtd/extern.h       |    2 
 xen/drivers/passthrough/vtd/intremap.c     |   26 -
 xen/drivers/passthrough/vtd/iommu.c        |  132 ++++++--
 xen/drivers/passthrough/vtd/iommu.h        |  454 ++++++++++++++++++++++++++++
 xen/drivers/passthrough/vtd/qinval.c       |   10 
 xen/drivers/passthrough/vtd/utils.c        |   11 
 xen/drivers/passthrough/vtd/vtd.h          |   11 
 xen/include/asm-x86/fixmap.h               |    2 
 xen/include/asm-x86/hvm/domain.h           |    4 
 xen/include/asm-x86/io_apic.h              |    2 
 xen/include/xen/hvm/iommu.h                |   56 +++
 xen/include/xen/iommu.h                    |  115 +++++++
 30 files changed, 1158 insertions(+), 1162 deletions(-)

diff -r af33f2054f47 -r bf8a3fc79093 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/arch/x86/domain.c     Mon Mar 17 10:45:24 2008 +0000
@@ -46,7 +46,7 @@
 #include <asm/debugreg.h>
 #include <asm/msr.h>
 #include <asm/nmi.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
 #ifdef CONFIG_COMPAT
 #include <compat/vcpu.h>
 #endif
diff -r af33f2054f47 -r bf8a3fc79093 xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/arch/x86/domctl.c     Mon Mar 17 10:45:24 2008 +0000
@@ -26,7 +26,7 @@
 #include <asm/hvm/cacheattr.h>
 #include <asm/processor.h>
 #include <xsm/xsm.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
 
 long arch_do_domctl(
     struct xen_domctl *domctl,
diff -r af33f2054f47 -r bf8a3fc79093 xen/arch/x86/hvm/Makefile
--- a/xen/arch/x86/hvm/Makefile Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/arch/x86/hvm/Makefile Mon Mar 17 10:45:24 2008 +0000
@@ -6,7 +6,6 @@ obj-y += i8254.o
 obj-y += i8254.o
 obj-y += intercept.o
 obj-y += io.o
-obj-y += iommu.o
 obj-y += irq.o
 obj-y += mtrr.o
 obj-y += pmtimer.o
diff -r af33f2054f47 -r bf8a3fc79093 xen/arch/x86/hvm/intercept.c
--- a/xen/arch/x86/hvm/intercept.c      Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/arch/x86/hvm/intercept.c      Mon Mar 17 10:45:24 2008 +0000
@@ -30,7 +30,7 @@
 #include <asm/current.h>
 #include <io_ports.h>
 #include <xen/event.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
 
 extern struct hvm_mmio_handler hpet_mmio_handler;
 extern struct hvm_mmio_handler vlapic_mmio_handler;
diff -r af33f2054f47 -r bf8a3fc79093 xen/arch/x86/hvm/iommu.c
--- a/xen/arch/x86/hvm/iommu.c  Sun Mar 16 14:11:34 2008 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
- * 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.
- */
-
-#include <xen/init.h>
-#include <xen/irq.h>
-#include <xen/spinlock.h>
-#include <xen/sched.h>
-#include <xen/xmalloc.h>
-#include <xen/domain_page.h>
-#include <asm/delay.h>
-#include <asm/string.h>
-#include <asm/mm.h>
-#include <asm/iommu.h>
-#include <asm/hvm/vmx/intel-iommu.h>
-
-extern struct iommu_ops intel_iommu_ops;
-extern struct iommu_ops amd_iommu_ops;
-
-int iommu_domain_init(struct domain *domain)
-{
-    struct hvm_iommu *hd = domain_hvm_iommu(domain);
-
-    spin_lock_init(&hd->mapping_lock);
-    spin_lock_init(&hd->iommu_list_lock);
-    INIT_LIST_HEAD(&hd->pdev_list);
-    INIT_LIST_HEAD(&hd->g2m_ioport_list);
-
-    if ( !iommu_enabled )
-        return 0;
-
-    switch ( boot_cpu_data.x86_vendor )
-    {
-    case X86_VENDOR_INTEL:
-        hd->platform_ops = &intel_iommu_ops;
-        break;
-    case X86_VENDOR_AMD:
-        hd->platform_ops = &amd_iommu_ops;
-        break;
-    default:
-        BUG();
-    }
-
-    return hd->platform_ops->init(domain);
-}
-
-int assign_device(struct domain *d, u8 bus, u8 devfn)
-{
-    struct hvm_iommu *hd = domain_hvm_iommu(d);
-
-    if ( !iommu_enabled || !hd->platform_ops)
-        return 0;
-
-    return hd->platform_ops->assign_device(d, bus, devfn);
-}
-
-void iommu_domain_destroy(struct domain *d)
-{
-    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
-    uint32_t i;
-    struct hvm_iommu *hd  = domain_hvm_iommu(d);
-    struct list_head *ioport_list, *digl_list, *tmp;
-    struct g2m_ioport *ioport;
-    struct dev_intx_gsi_link *digl;
-
-    if ( !iommu_enabled || !hd->platform_ops)
-        return;
-
-    if ( hvm_irq_dpci != NULL )
-    {
-        for ( i = 0; i < NR_IRQS; i++ )
-        {
-            if ( !hvm_irq_dpci->mirq[i].valid )
-                continue;
-
-            pirq_guest_unbind(d, i);
-            kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(i)]);
-
-            list_for_each_safe ( digl_list, tmp,
-                                 &hvm_irq_dpci->mirq[i].digl_list )
-            {
-                digl = list_entry(digl_list,
-                                  struct dev_intx_gsi_link, list);
-                list_del(&digl->list);
-                xfree(digl);
-            }
-        }
-
-        d->arch.hvm_domain.irq.dpci = NULL;
-        xfree(hvm_irq_dpci);
-    }
-
-    if ( hd )
-    {
-        list_for_each_safe ( ioport_list, tmp, &hd->g2m_ioport_list )
-        {
-            ioport = list_entry(ioport_list, struct g2m_ioport, list);
-            list_del(&ioport->list);
-            xfree(ioport);
-        }
-    }
-
-    return hd->platform_ops->teardown(d);
-}
-
-int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn)
-{
-    struct hvm_iommu *hd = domain_hvm_iommu(d);
-
-    if ( !iommu_enabled || !hd->platform_ops)
-        return 0;
-
-    return hd->platform_ops->map_page(d, gfn, mfn);
-}
-
-int iommu_unmap_page(struct domain *d, unsigned long gfn)
-{
-    struct hvm_iommu *hd = domain_hvm_iommu(d);
-
-    if ( !iommu_enabled || !hd->platform_ops)
-        return 0;
-
-    return hd->platform_ops->unmap_page(d, gfn);
-}
-
-void deassign_device(struct domain *d, u8 bus, u8 devfn)
-{
-    struct hvm_iommu *hd = domain_hvm_iommu(d);
-
-    if ( !iommu_enabled || !hd->platform_ops)
-        return;
-
-    return hd->platform_ops->reassign_device(d, dom0, bus, devfn);
-}
diff -r af33f2054f47 -r bf8a3fc79093 xen/arch/x86/irq.c
--- a/xen/arch/x86/irq.c        Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/arch/x86/irq.c        Mon Mar 17 10:45:24 2008 +0000
@@ -15,7 +15,7 @@
 #include <xen/keyhandler.h>
 #include <xen/compat.h>
 #include <asm/current.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
 
 /* opt_noirqbalance: If true, software IRQ balancing/affinity is disabled. */
 int opt_noirqbalance = 0;
diff -r af33f2054f47 -r bf8a3fc79093 xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c     Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/arch/x86/mm/p2m.c     Mon Mar 17 10:45:24 2008 +0000
@@ -27,7 +27,7 @@
 #include <asm/page.h>
 #include <asm/paging.h>
 #include <asm/p2m.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
 
 /* Debugging and auditing of the P2M code? */
 #define P2M_AUDIT     0
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/Makefile
--- a/xen/drivers/passthrough/Makefile  Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/drivers/passthrough/Makefile  Mon Mar 17 10:45:24 2008 +0000
@@ -1,2 +1,5 @@ subdir-$(x86) += vtd
 subdir-$(x86) += vtd
 subdir-$(x86) += amd
+
+obj-y += iommu.o
+obj-y += io.o
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/amd/iommu_detect.c
--- a/xen/drivers/passthrough/amd/iommu_detect.c        Sun Mar 16 14:11:34 
2008 +0000
+++ b/xen/drivers/passthrough/amd/iommu_detect.c        Mon Mar 17 10:45:24 
2008 +0000
@@ -20,7 +20,7 @@
 
 #include <xen/config.h>
 #include <xen/errno.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
 #include <asm/amd-iommu.h>
 #include <asm/hvm/svm/amd-iommu-proto.h>
 #include "../pci-direct.h"
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/amd/iommu_map.c
--- a/xen/drivers/passthrough/amd/iommu_map.c   Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/drivers/passthrough/amd/iommu_map.c   Mon Mar 17 10:45:24 2008 +0000
@@ -19,7 +19,7 @@
  */
 
 #include <xen/sched.h>
-#include <asm/hvm/iommu.h>
+#include <xen/hvm/iommu.h>
 #include <asm/amd-iommu.h>
 #include <asm/hvm/svm/amd-iommu-proto.h>
 
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/io.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/drivers/passthrough/io.c      Mon Mar 17 10:45:24 2008 +0000
@@ -0,0 +1,272 @@
+/*
+ * 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.
+ *
+ * Copyright (C) Allen Kay <allen.m.kay@xxxxxxxxx>
+ * Copyright (C) Xiaohui Xin <xiaohui.xin@xxxxxxxxx>
+ */
+
+#include <xen/event.h>
+#include <xen/iommu.h>
+
+static void pt_irq_time_out(void *data)
+{
+    struct hvm_mirq_dpci_mapping *irq_map = data;
+    unsigned int guest_gsi, machine_gsi = 0;
+    struct hvm_irq_dpci *dpci = irq_map->dom->arch.hvm_domain.irq.dpci;
+    struct dev_intx_gsi_link *digl;
+    uint32_t device, intx;
+
+    list_for_each_entry ( digl, &irq_map->digl_list, list )
+    {
+        guest_gsi = digl->gsi;
+        machine_gsi = dpci->girq[guest_gsi].machine_gsi;
+        device = digl->device;
+        intx = digl->intx;
+        hvm_pci_intx_deassert(irq_map->dom, device, intx);
+    }
+
+    clear_bit(machine_gsi, dpci->dirq_mask);
+    stop_timer(&dpci->hvm_timer[irq_to_vector(machine_gsi)]);
+    spin_lock(&dpci->dirq_lock);
+    dpci->mirq[machine_gsi].pending = 0;
+    spin_unlock(&dpci->dirq_lock);
+    pirq_guest_eoi(irq_map->dom, machine_gsi);
+}
+
+int pt_irq_create_bind_vtd(
+    struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
+{
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+    uint32_t machine_gsi, guest_gsi;
+    uint32_t device, intx, link;
+    struct dev_intx_gsi_link *digl;
+
+    if ( hvm_irq_dpci == NULL )
+    {
+        hvm_irq_dpci = xmalloc(struct hvm_irq_dpci);
+        if ( hvm_irq_dpci == NULL )
+            return -ENOMEM;
+
+        memset(hvm_irq_dpci, 0, sizeof(*hvm_irq_dpci));
+        spin_lock_init(&hvm_irq_dpci->dirq_lock);
+        for ( int i = 0; i < NR_IRQS; i++ )
+            INIT_LIST_HEAD(&hvm_irq_dpci->mirq[i].digl_list);
+
+        if ( cmpxchg((unsigned long *)&d->arch.hvm_domain.irq.dpci,
+                     0, (unsigned long)hvm_irq_dpci) != 0 )
+            xfree(hvm_irq_dpci);
+
+        hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+    }
+
+    machine_gsi = pt_irq_bind->machine_irq;
+    device = pt_irq_bind->u.pci.device;
+    intx = pt_irq_bind->u.pci.intx;
+    guest_gsi = hvm_pci_intx_gsi(device, intx);
+    link = hvm_pci_intx_link(device, intx);
+    hvm_irq_dpci->link_cnt[link]++;
+
+    digl = xmalloc(struct dev_intx_gsi_link);
+    if ( !digl )
+        return -ENOMEM;
+
+    digl->device = device;
+    digl->intx = intx;
+    digl->gsi = guest_gsi;
+    digl->link = link;
+    list_add_tail(&digl->list,
+                  &hvm_irq_dpci->mirq[machine_gsi].digl_list);
+
+    hvm_irq_dpci->girq[guest_gsi].valid = 1;
+    hvm_irq_dpci->girq[guest_gsi].device = device;
+    hvm_irq_dpci->girq[guest_gsi].intx = intx;
+    hvm_irq_dpci->girq[guest_gsi].machine_gsi = machine_gsi;
+
+    /* Bind the same mirq once in the same domain */
+    if ( !hvm_irq_dpci->mirq[machine_gsi].valid )
+    {
+        hvm_irq_dpci->mirq[machine_gsi].valid = 1;
+        hvm_irq_dpci->mirq[machine_gsi].dom = d;
+
+        init_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)],
+                   pt_irq_time_out, &hvm_irq_dpci->mirq[machine_gsi], 0);
+        /* Deal with gsi for legacy devices */
+        pirq_guest_bind(d->vcpu[0], machine_gsi, BIND_PIRQ__WILL_SHARE);
+    }
+
+    gdprintk(XENLOG_INFO VTDPREFIX,
+             "VT-d irq bind: m_irq = %x device = %x intx = %x\n",
+             machine_gsi, device, intx);
+    return 0;
+}
+
+int pt_irq_destroy_bind_vtd(
+    struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
+{
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+    uint32_t machine_gsi, guest_gsi;
+    uint32_t device, intx, link;
+    struct list_head *digl_list, *tmp;
+    struct dev_intx_gsi_link *digl;
+
+    if ( hvm_irq_dpci == NULL )
+        return 0;
+
+    machine_gsi = pt_irq_bind->machine_irq;
+    device = pt_irq_bind->u.pci.device;
+    intx = pt_irq_bind->u.pci.intx;
+    guest_gsi = hvm_pci_intx_gsi(device, intx);
+    link = hvm_pci_intx_link(device, intx);
+    hvm_irq_dpci->link_cnt[link]--;
+
+    gdprintk(XENLOG_INFO,
+            "pt_irq_destroy_bind_vtd: machine_gsi=%d, guest_gsi=%d, device=%d, 
intx=%d.\n",
+            machine_gsi, guest_gsi, device, intx);
+    memset(&hvm_irq_dpci->girq[guest_gsi], 0, sizeof(struct 
hvm_girq_dpci_mapping));
+
+    /* clear the mirq info */
+    if ( hvm_irq_dpci->mirq[machine_gsi].valid )
+    {
+
+        list_for_each_safe ( digl_list, tmp,
+                &hvm_irq_dpci->mirq[machine_gsi].digl_list )
+        {
+            digl = list_entry(digl_list,
+                    struct dev_intx_gsi_link, list);
+            if ( digl->device == device &&
+                 digl->intx   == intx &&
+                 digl->link   == link &&
+                 digl->gsi    == guest_gsi )
+            {
+                list_del(&digl->list);
+                xfree(digl);
+            }
+        }
+
+        if ( list_empty(&hvm_irq_dpci->mirq[machine_gsi].digl_list) )
+        {
+            pirq_guest_unbind(d, machine_gsi);
+            kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)]);
+            hvm_irq_dpci->mirq[machine_gsi].dom   = NULL;
+            hvm_irq_dpci->mirq[machine_gsi].valid = 0;
+        }
+    }
+
+    gdprintk(XENLOG_INFO,
+             "XEN_DOMCTL_irq_unmapping: m_irq = %x device = %x intx = %x\n",
+             machine_gsi, device, intx);
+
+    return 0;
+}
+
+int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+
+    if ( !iommu_enabled || (d == dom0) || (hvm_irq->dpci == NULL) ||
+         !hvm_irq->dpci->mirq[mirq].valid )
+        return 0;
+
+    /*
+     * Set a timer here to avoid situations where the IRQ line is shared, and
+     * the device belonging to the pass-through guest is not yet active. In
+     * this case the guest may not pick up the interrupt (e.g., masked at the
+     * PIC) and we need to detect that.
+     */
+    set_bit(mirq, hvm_irq->dpci->dirq_mask);
+    set_timer(&hvm_irq->dpci->hvm_timer[irq_to_vector(mirq)],
+              NOW() + PT_IRQ_TIME_OUT);
+    vcpu_kick(d->vcpu[0]);
+
+    return 1;
+}
+
+static void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    struct hvm_irq_dpci *dpci = hvm_irq->dpci;
+    struct dev_intx_gsi_link *digl, *tmp;
+    int i;
+
+    ASSERT(isairq < NR_ISAIRQS);
+    if ( !iommu_enabled || !dpci ||
+         !test_bit(isairq, dpci->isairq_map) )
+        return;
+
+    /* Multiple mirq may be mapped to one isa irq */
+    for ( i = 0; i < NR_IRQS; i++ )
+    {
+        if ( !dpci->mirq[i].valid )
+            continue;
+
+        list_for_each_entry_safe ( digl, tmp,
+            &dpci->mirq[i].digl_list, list )
+        {
+            if ( hvm_irq->pci_link.route[digl->link] == isairq )
+            {
+                hvm_pci_intx_deassert(d, digl->device, digl->intx);
+                spin_lock(&dpci->dirq_lock);
+                if ( --dpci->mirq[i].pending == 0 )
+                {
+                    spin_unlock(&dpci->dirq_lock);
+                    gdprintk(XENLOG_INFO VTDPREFIX,
+                             "hvm_dpci_isairq_eoi:: mirq = %x\n", i);
+                    stop_timer(&dpci->hvm_timer[irq_to_vector(i)]);
+                    pirq_guest_eoi(d, i);
+                }
+                else
+                    spin_unlock(&dpci->dirq_lock);
+            }
+        }
+    }
+}
+
+void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
+                  union vioapic_redir_entry *ent)
+{
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+    uint32_t device, intx, machine_gsi;
+
+    if ( !iommu_enabled || (hvm_irq_dpci == NULL) ||
+         (guest_gsi >= NR_ISAIRQS &&
+          !hvm_irq_dpci->girq[guest_gsi].valid) )
+        return;
+
+    if ( guest_gsi < NR_ISAIRQS )
+    {
+        hvm_dpci_isairq_eoi(d, guest_gsi);
+        return;
+    }
+
+    machine_gsi = hvm_irq_dpci->girq[guest_gsi].machine_gsi;
+    device = hvm_irq_dpci->girq[guest_gsi].device;
+    intx = hvm_irq_dpci->girq[guest_gsi].intx;
+    hvm_pci_intx_deassert(d, device, intx);
+
+    spin_lock(&hvm_irq_dpci->dirq_lock);
+    if ( --hvm_irq_dpci->mirq[machine_gsi].pending == 0 )
+    {
+        spin_unlock(&hvm_irq_dpci->dirq_lock);
+
+        gdprintk(XENLOG_INFO VTDPREFIX,
+                 "hvm_dpci_eoi:: mirq = %x\n", machine_gsi);
+        stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)]);
+        if ( (ent == NULL) || !ent->fields.mask )
+            pirq_guest_eoi(d, machine_gsi);
+    }
+    else
+        spin_unlock(&hvm_irq_dpci->dirq_lock);
+}
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/iommu.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/drivers/passthrough/iommu.c   Mon Mar 17 10:45:24 2008 +0000
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+#include <xen/sched.h>
+#include <xen/iommu.h>
+
+extern struct iommu_ops intel_iommu_ops;
+extern struct iommu_ops amd_iommu_ops;
+
+int iommu_domain_init(struct domain *domain)
+{
+    struct hvm_iommu *hd = domain_hvm_iommu(domain);
+
+    spin_lock_init(&hd->mapping_lock);
+    spin_lock_init(&hd->iommu_list_lock);
+    INIT_LIST_HEAD(&hd->pdev_list);
+    INIT_LIST_HEAD(&hd->g2m_ioport_list);
+
+    if ( !iommu_enabled )
+        return 0;
+
+    switch ( boot_cpu_data.x86_vendor )
+    {
+    case X86_VENDOR_INTEL:
+        hd->platform_ops = &intel_iommu_ops;
+        break;
+    case X86_VENDOR_AMD:
+        hd->platform_ops = &amd_iommu_ops;
+        break;
+    default:
+        BUG();
+    }
+
+    return hd->platform_ops->init(domain);
+}
+
+int assign_device(struct domain *d, u8 bus, u8 devfn)
+{
+    struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+    if ( !iommu_enabled || !hd->platform_ops)
+        return 0;
+
+    return hd->platform_ops->assign_device(d, bus, devfn);
+}
+
+void iommu_domain_destroy(struct domain *d)
+{
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+    uint32_t i;
+    struct hvm_iommu *hd  = domain_hvm_iommu(d);
+    struct list_head *ioport_list, *digl_list, *tmp;
+    struct g2m_ioport *ioport;
+    struct dev_intx_gsi_link *digl;
+
+    if ( !iommu_enabled || !hd->platform_ops)
+        return;
+
+    if ( hvm_irq_dpci != NULL )
+    {
+        for ( i = 0; i < NR_IRQS; i++ )
+        {
+            if ( !hvm_irq_dpci->mirq[i].valid )
+                continue;
+
+            pirq_guest_unbind(d, i);
+            kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(i)]);
+
+            list_for_each_safe ( digl_list, tmp,
+                                 &hvm_irq_dpci->mirq[i].digl_list )
+            {
+                digl = list_entry(digl_list,
+                                  struct dev_intx_gsi_link, list);
+                list_del(&digl->list);
+                xfree(digl);
+            }
+        }
+
+        d->arch.hvm_domain.irq.dpci = NULL;
+        xfree(hvm_irq_dpci);
+    }
+
+    if ( hd )
+    {
+        list_for_each_safe ( ioport_list, tmp, &hd->g2m_ioport_list )
+        {
+            ioport = list_entry(ioport_list, struct g2m_ioport, list);
+            list_del(&ioport->list);
+            xfree(ioport);
+        }
+    }
+
+    return hd->platform_ops->teardown(d);
+}
+
+int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn)
+{
+    struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+    if ( !iommu_enabled || !hd->platform_ops)
+        return 0;
+
+    return hd->platform_ops->map_page(d, gfn, mfn);
+}
+
+int iommu_unmap_page(struct domain *d, unsigned long gfn)
+{
+    struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+    if ( !iommu_enabled || !hd->platform_ops)
+        return 0;
+
+    return hd->platform_ops->unmap_page(d, gfn);
+}
+
+void deassign_device(struct domain *d, u8 bus, u8 devfn)
+{
+    struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+    if ( !iommu_enabled || !hd->platform_ops)
+        return;
+
+    return hd->platform_ops->reassign_device(d, dom0, bus, devfn);
+}
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/vtd/Makefile
--- a/xen/drivers/passthrough/vtd/Makefile      Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/drivers/passthrough/vtd/Makefile      Mon Mar 17 10:45:24 2008 +0000
@@ -1,6 +1,5 @@ obj-y += iommu.o
 obj-y += iommu.o
 obj-y += dmar.o
 obj-y += utils.o
-obj-y += io.o
 obj-y += qinval.o
 obj-y += intremap.o
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/vtd/dmar.h
--- a/xen/drivers/passthrough/vtd/dmar.h        Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/drivers/passthrough/vtd/dmar.h        Mon Mar 17 10:45:24 2008 +0000
@@ -22,7 +22,7 @@
 #define _DMAR_H_
 
 #include <xen/list.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
 
 extern u8 dmar_host_address_width;
 
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/vtd/extern.h
--- a/xen/drivers/passthrough/vtd/extern.h      Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/drivers/passthrough/vtd/extern.h      Mon Mar 17 10:45:24 2008 +0000
@@ -42,8 +42,6 @@ int invalidate_sync(struct iommu *iommu)
 int invalidate_sync(struct iommu *iommu);
 int iommu_flush_iec_global(struct iommu *iommu);
 int iommu_flush_iec_index(struct iommu *iommu, u8 im, u16 iidx);
-void print_iommu_regs(struct acpi_drhd_unit *drhd);
-int vtd_hw_check(void);
 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);
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/vtd/intremap.c
--- a/xen/drivers/passthrough/vtd/intremap.c    Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/drivers/passthrough/vtd/intremap.c    Mon Mar 17 10:45:24 2008 +0000
@@ -18,28 +18,10 @@
  * Copyright (C) Xiaohui Xin <xiaohui.xin@xxxxxxxxx>
  */
 
-#include <xen/config.h>
-#include <xen/lib.h>
-#include <xen/init.h>
 #include <xen/irq.h>
-#include <xen/delay.h>
 #include <xen/sched.h>
-#include <xen/acpi.h>
-#include <xen/keyhandler.h>
-#include <xen/spinlock.h>
-#include <asm/io.h>
-#include <asm/mc146818rtc.h>
-#include <asm/smp.h>
-#include <asm/desc.h>
-#include <mach_apic.h>
-#include <io_ports.h>
-
-#include <xen/spinlock.h>
-#include <xen/xmalloc.h>
-#include <xen/domain_page.h>
-#include <asm/delay.h>
-#include <asm/string.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
+#include "iommu.h"
 #include "dmar.h"
 #include "vtd.h"
 #include "../pci-direct.h"
@@ -172,7 +154,7 @@ io_apic_read_remap_rte(
     struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid);
     struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);
 
-    if ( !iommu || !(ir_ctrl->iremap) )
+    if ( !iommu || !ir_ctrl || !(ir_ctrl->iremap) )
     {
         *IO_APIC_BASE(apic) = reg;
         return *(IO_APIC_BASE(apic)+4);
@@ -218,7 +200,7 @@ io_apic_write_remap_rte(
     struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid);
     struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);
 
-    if ( !iommu || !(ir_ctrl->iremap) )
+    if ( !iommu || !ir_ctrl || !(ir_ctrl->iremap) )
     {
         *IO_APIC_BASE(apic) = reg;
         *(IO_APIC_BASE(apic)+4) = value;
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/vtd/io.c
--- a/xen/drivers/passthrough/vtd/io.c  Sun Mar 16 14:11:34 2008 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) Allen Kay <allen.m.kay@xxxxxxxxx>
- * Copyright (C) Xiaohui Xin <xiaohui.xin@xxxxxxxxx>
- */
-
-#include <xen/init.h>
-#include <xen/config.h>
-#include <xen/init.h>
-#include <xen/mm.h>
-#include <xen/lib.h>
-#include <xen/errno.h>
-#include <xen/trace.h>
-#include <xen/event.h>
-#include <xen/hypercall.h>
-#include <asm/current.h>
-#include <asm/cpufeature.h>
-#include <asm/processor.h>
-#include <asm/msr.h>
-#include <asm/apic.h>
-#include <asm/paging.h>
-#include <asm/shadow.h>
-#include <asm/p2m.h>
-#include <asm/hvm/hvm.h>
-#include <asm/hvm/support.h>
-#include <asm/hvm/vpt.h>
-#include <asm/hvm/vpic.h>
-#include <asm/hvm/vlapic.h>
-#include <public/sched.h>
-#include <xen/iocap.h>
-#include <public/hvm/ioreq.h>
-#include <public/domctl.h>
-
-static void pt_irq_time_out(void *data)
-{
-    struct hvm_mirq_dpci_mapping *irq_map = data;
-    unsigned int guest_gsi, machine_gsi = 0;
-    struct hvm_irq_dpci *dpci = irq_map->dom->arch.hvm_domain.irq.dpci;
-    struct dev_intx_gsi_link *digl;
-    uint32_t device, intx;
-
-    list_for_each_entry ( digl, &irq_map->digl_list, list )
-    {
-        guest_gsi = digl->gsi;
-        machine_gsi = dpci->girq[guest_gsi].machine_gsi;
-        device = digl->device;
-        intx = digl->intx;
-        hvm_pci_intx_deassert(irq_map->dom, device, intx);
-    }
-
-    clear_bit(machine_gsi, dpci->dirq_mask);
-    stop_timer(&dpci->hvm_timer[irq_to_vector(machine_gsi)]);
-    spin_lock(&dpci->dirq_lock);
-    dpci->mirq[machine_gsi].pending = 0;
-    spin_unlock(&dpci->dirq_lock);
-    pirq_guest_eoi(irq_map->dom, machine_gsi);
-}
-
-int pt_irq_create_bind_vtd(
-    struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
-{
-    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
-    uint32_t machine_gsi, guest_gsi;
-    uint32_t device, intx, link;
-    struct dev_intx_gsi_link *digl;
-
-    if ( hvm_irq_dpci == NULL )
-    {
-        hvm_irq_dpci = xmalloc(struct hvm_irq_dpci);
-        if ( hvm_irq_dpci == NULL )
-            return -ENOMEM;
-
-        memset(hvm_irq_dpci, 0, sizeof(*hvm_irq_dpci));
-        spin_lock_init(&hvm_irq_dpci->dirq_lock);
-        for ( int i = 0; i < NR_IRQS; i++ )
-            INIT_LIST_HEAD(&hvm_irq_dpci->mirq[i].digl_list);
-
-        if ( cmpxchg((unsigned long *)&d->arch.hvm_domain.irq.dpci,
-                     0, (unsigned long)hvm_irq_dpci) != 0 )
-            xfree(hvm_irq_dpci);
-
-        hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
-    }
-
-    machine_gsi = pt_irq_bind->machine_irq;
-    device = pt_irq_bind->u.pci.device;
-    intx = pt_irq_bind->u.pci.intx;
-    guest_gsi = hvm_pci_intx_gsi(device, intx);
-    link = hvm_pci_intx_link(device, intx);
-    hvm_irq_dpci->link_cnt[link]++;
-
-    digl = xmalloc(struct dev_intx_gsi_link);
-    if ( !digl )
-        return -ENOMEM;
-
-    digl->device = device;
-    digl->intx = intx;
-    digl->gsi = guest_gsi;
-    digl->link = link;
-    list_add_tail(&digl->list,
-                  &hvm_irq_dpci->mirq[machine_gsi].digl_list);
-
-    hvm_irq_dpci->girq[guest_gsi].valid = 1;
-    hvm_irq_dpci->girq[guest_gsi].device = device;
-    hvm_irq_dpci->girq[guest_gsi].intx = intx;
-    hvm_irq_dpci->girq[guest_gsi].machine_gsi = machine_gsi;
-
-    /* Bind the same mirq once in the same domain */
-    if ( !hvm_irq_dpci->mirq[machine_gsi].valid )
-    {
-        hvm_irq_dpci->mirq[machine_gsi].valid = 1;
-        hvm_irq_dpci->mirq[machine_gsi].dom = d;
-
-        init_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)],
-                   pt_irq_time_out, &hvm_irq_dpci->mirq[machine_gsi], 0);
-        /* Deal with gsi for legacy devices */
-        pirq_guest_bind(d->vcpu[0], machine_gsi, BIND_PIRQ__WILL_SHARE);
-    }
-
-    gdprintk(XENLOG_INFO VTDPREFIX,
-             "VT-d irq bind: m_irq = %x device = %x intx = %x\n",
-             machine_gsi, device, intx);
-    return 0;
-}
-
-int pt_irq_destroy_bind_vtd(
-    struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind)
-{
-    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
-    uint32_t machine_gsi, guest_gsi;
-    uint32_t device, intx, link;
-    struct list_head *digl_list, *tmp;
-    struct dev_intx_gsi_link *digl;
-
-    if ( hvm_irq_dpci == NULL )
-        return 0;
-
-    machine_gsi = pt_irq_bind->machine_irq;
-    device = pt_irq_bind->u.pci.device;
-    intx = pt_irq_bind->u.pci.intx;
-    guest_gsi = hvm_pci_intx_gsi(device, intx);
-    link = hvm_pci_intx_link(device, intx);
-    hvm_irq_dpci->link_cnt[link]--;
-
-    gdprintk(XENLOG_INFO,
-            "pt_irq_destroy_bind_vtd: machine_gsi=%d, guest_gsi=%d, device=%d, 
intx=%d.\n",
-            machine_gsi, guest_gsi, device, intx);
-    memset(&hvm_irq_dpci->girq[guest_gsi], 0, sizeof(struct 
hvm_girq_dpci_mapping));
-
-    /* clear the mirq info */
-    if ( hvm_irq_dpci->mirq[machine_gsi].valid )
-    {
-
-        list_for_each_safe ( digl_list, tmp,
-                &hvm_irq_dpci->mirq[machine_gsi].digl_list )
-        {
-            digl = list_entry(digl_list,
-                    struct dev_intx_gsi_link, list);
-            if ( digl->device == device &&
-                 digl->intx   == intx &&
-                 digl->link   == link &&
-                 digl->gsi    == guest_gsi )
-            {
-                list_del(&digl->list);
-                xfree(digl);
-            }
-        }
-
-        if ( list_empty(&hvm_irq_dpci->mirq[machine_gsi].digl_list) )
-        {
-            pirq_guest_unbind(d, machine_gsi);
-            kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)]);
-            hvm_irq_dpci->mirq[machine_gsi].dom   = NULL;
-            hvm_irq_dpci->mirq[machine_gsi].valid = 0;
-        }
-    }
-
-    gdprintk(XENLOG_INFO,
-             "XEN_DOMCTL_irq_unmapping: m_irq = %x device = %x intx = %x\n",
-             machine_gsi, device, intx);
-
-    return 0;
-}
-
-int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq)
-{
-    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
-
-    if ( !iommu_enabled || (d == dom0) || (hvm_irq->dpci == NULL) ||
-         !hvm_irq->dpci->mirq[mirq].valid )
-        return 0;
-
-    /*
-     * Set a timer here to avoid situations where the IRQ line is shared, and
-     * the device belonging to the pass-through guest is not yet active. In
-     * this case the guest may not pick up the interrupt (e.g., masked at the
-     * PIC) and we need to detect that.
-     */
-    set_bit(mirq, hvm_irq->dpci->dirq_mask);
-    set_timer(&hvm_irq->dpci->hvm_timer[irq_to_vector(mirq)],
-              NOW() + PT_IRQ_TIME_OUT);
-    vcpu_kick(d->vcpu[0]);
-
-    return 1;
-}
-
-static void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq)
-{
-    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
-    struct hvm_irq_dpci *dpci = hvm_irq->dpci;
-    struct dev_intx_gsi_link *digl, *tmp;
-    int i;
-
-    ASSERT(isairq < NR_ISAIRQS);
-    if ( !iommu_enabled || !dpci ||
-         !test_bit(isairq, dpci->isairq_map) )
-        return;
-
-    /* Multiple mirq may be mapped to one isa irq */
-    for ( i = 0; i < NR_IRQS; i++ )
-    {
-        if ( !dpci->mirq[i].valid )
-            continue;
-
-        list_for_each_entry_safe ( digl, tmp,
-            &dpci->mirq[i].digl_list, list )
-        {
-            if ( hvm_irq->pci_link.route[digl->link] == isairq )
-            {
-                hvm_pci_intx_deassert(d, digl->device, digl->intx);
-                spin_lock(&dpci->dirq_lock);
-                if ( --dpci->mirq[i].pending == 0 )
-                {
-                    spin_unlock(&dpci->dirq_lock);
-                    gdprintk(XENLOG_INFO VTDPREFIX,
-                             "hvm_dpci_isairq_eoi:: mirq = %x\n", i);
-                    stop_timer(&dpci->hvm_timer[irq_to_vector(i)]);
-                    pirq_guest_eoi(d, i);
-                }
-                else
-                    spin_unlock(&dpci->dirq_lock);
-            }
-        }
-    }
-}
-
-void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
-                  union vioapic_redir_entry *ent)
-{
-    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
-    uint32_t device, intx, machine_gsi;
-
-    if ( !iommu_enabled || (hvm_irq_dpci == NULL) ||
-         (guest_gsi >= NR_ISAIRQS &&
-          !hvm_irq_dpci->girq[guest_gsi].valid) )
-        return;
-
-    if ( guest_gsi < NR_ISAIRQS )
-    {
-        hvm_dpci_isairq_eoi(d, guest_gsi);
-        return;
-    }
-
-    machine_gsi = hvm_irq_dpci->girq[guest_gsi].machine_gsi;
-    device = hvm_irq_dpci->girq[guest_gsi].device;
-    intx = hvm_irq_dpci->girq[guest_gsi].intx;
-    hvm_pci_intx_deassert(d, device, intx);
-
-    spin_lock(&hvm_irq_dpci->dirq_lock);
-    if ( --hvm_irq_dpci->mirq[machine_gsi].pending == 0 )
-    {
-        spin_unlock(&hvm_irq_dpci->dirq_lock);
-
-        gdprintk(XENLOG_INFO VTDPREFIX,
-                 "hvm_dpci_eoi:: mirq = %x\n", machine_gsi);
-        stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)]);
-        if ( (ent == NULL) || !ent->fields.mask )
-            pirq_guest_eoi(d, machine_gsi);
-    }
-    else
-        spin_unlock(&hvm_irq_dpci->dirq_lock);
-}
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c       Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/drivers/passthrough/vtd/iommu.c       Mon Mar 17 10:45:24 2008 +0000
@@ -19,17 +19,12 @@
  * Copyright (C) Allen Kay <allen.m.kay@xxxxxxxxx> - adapted to xen
  */
 
-#include <xen/init.h>
 #include <xen/irq.h>
-#include <xen/spinlock.h>
 #include <xen/sched.h>
 #include <xen/xmalloc.h>
 #include <xen/domain_page.h>
-#include <asm/delay.h>
-#include <asm/string.h>
-#include <asm/mm.h>
-#include <asm/iommu.h>
-#include <asm/hvm/vmx/intel-iommu.h>
+#include <xen/iommu.h>
+#include "iommu.h"
 #include "dmar.h"
 #include "../pci-direct.h"
 #include "../pci_regs.h"
@@ -72,6 +67,93 @@ static void iommu_domid_release(struct d
         d->arch.hvm_domain.hvm_iommu.iommu_domid = 0;
         clear_bit(iommu_domid, domid_bitmap);
     }
+}
+
+static struct intel_iommu *alloc_intel_iommu(void)
+{
+    struct intel_iommu *intel;
+
+    intel = xmalloc(struct intel_iommu);
+    if ( !intel )
+    {
+        gdprintk(XENLOG_ERR VTDPREFIX,
+                 "Allocate intel_iommu failed.\n");
+        return NULL;
+    }
+    memset(intel, 0, sizeof(struct intel_iommu));
+
+    spin_lock_init(&intel->qi_ctrl.qinval_lock);
+    spin_lock_init(&intel->qi_ctrl.qinval_poll_lock);
+
+    spin_lock_init(&intel->ir_ctrl.iremap_lock);
+
+    return intel;
+}
+
+static void free_intel_iommu(struct intel_iommu *intel)
+{
+    if ( intel )
+    {
+        xfree(intel);
+        intel = NULL;
+    }
+}
+
+struct qi_ctrl *iommu_qi_ctrl(struct iommu *iommu)
+{
+    if ( !iommu )
+        return NULL;
+
+    if ( !iommu->intel )
+    {
+        iommu->intel = alloc_intel_iommu();
+        if ( !iommu->intel )
+        {
+            dprintk(XENLOG_ERR VTDPREFIX,
+                    "iommu_qi_ctrl: Allocate iommu->intel failed.\n");
+            return NULL;
+        }
+    }
+
+    return &(iommu->intel->qi_ctrl);
+}
+
+struct ir_ctrl *iommu_ir_ctrl(struct iommu *iommu)
+{
+    if ( !iommu )
+        return NULL;
+
+    if ( !iommu->intel )
+    {
+        iommu->intel = alloc_intel_iommu();
+        if ( !iommu->intel )
+        {
+            dprintk(XENLOG_ERR VTDPREFIX,
+                    "iommu_ir_ctrl: Allocate iommu->intel failed.\n");
+            return NULL;
+        }
+    }
+
+    return &(iommu->intel->ir_ctrl);
+}
+
+struct iommu_flush *iommu_get_flush(struct iommu *iommu)
+{
+    if ( !iommu )
+        return NULL;
+
+    if ( !iommu->intel )
+    {
+        iommu->intel = alloc_intel_iommu();
+        if ( !iommu->intel )
+        {
+            dprintk(XENLOG_ERR VTDPREFIX,
+                    "iommu_get_flush: Allocate iommu->intel failed.\n");
+            return NULL;
+        }
+    }
+
+    return &(iommu->intel->flush);
 }
 
 unsigned int x86_clflush_size;
@@ -756,40 +838,34 @@ static int iommu_page_fault_do_one(struc
             PCI_SLOT(source_id & 0xFF), PCI_FUNC(source_id & 0xFF), addr,
             fault_reason, iommu->reg);
 
-    if (fault_reason < 0x20) 
+    if ( fault_reason < 0x20 )
         print_vtd_entries(current->domain, iommu, (source_id >> 8),
-                          (source_id & 0xff), (addr >> PAGE_SHIFT)); 
+                          (source_id & 0xff), (addr >> PAGE_SHIFT));
 
     return 0;
 }
 
 static void iommu_fault_status(u32 fault_status)
 {
-    if (fault_status & DMA_FSTS_PFO)
+    if ( fault_status & DMA_FSTS_PFO )
         dprintk(XENLOG_ERR VTDPREFIX,
             "iommu_fault_status: Fault Overflow\n");
-    else
-    if (fault_status & DMA_FSTS_PPF)
+    else if ( fault_status & DMA_FSTS_PPF )
         dprintk(XENLOG_ERR VTDPREFIX,
             "iommu_fault_status: Primary Pending Fault\n");
-    else
-    if (fault_status & DMA_FSTS_AFO)
+    else if ( fault_status & DMA_FSTS_AFO )
         dprintk(XENLOG_ERR VTDPREFIX,
             "iommu_fault_status: Advanced Fault Overflow\n");
-    else
-    if (fault_status & DMA_FSTS_APF)
+    else if ( fault_status & DMA_FSTS_APF )
         dprintk(XENLOG_ERR VTDPREFIX,
             "iommu_fault_status: Advanced Pending Fault\n");
-    else
-    if (fault_status & DMA_FSTS_IQE)
+    else if ( fault_status & DMA_FSTS_IQE )
         dprintk(XENLOG_ERR VTDPREFIX,
             "iommu_fault_status: Invalidation Queue Error\n");
-    else
-    if (fault_status & DMA_FSTS_ICE)
+    else if ( fault_status & DMA_FSTS_ICE )
         dprintk(XENLOG_ERR VTDPREFIX,
             "iommu_fault_status: Invalidation Completion Error\n");
-    else
-    if (fault_status & DMA_FSTS_ITE)
+    else if ( fault_status & DMA_FSTS_ITE )
         dprintk(XENLOG_ERR VTDPREFIX,
             "iommu_fault_status: Invalidation Time-out Error\n");
 }
@@ -976,8 +1052,6 @@ struct iommu *iommu_alloc(void *hw_data)
 {
     struct acpi_drhd_unit *drhd = (struct acpi_drhd_unit *) hw_data;
     struct iommu *iommu;
-    struct qi_ctrl *qi_ctrl;
-    struct ir_ctrl *ir_ctrl;
 
     if ( nr_iommus > MAX_IOMMUS )
     {
@@ -1014,12 +1088,7 @@ struct iommu *iommu_alloc(void *hw_data)
     spin_lock_init(&iommu->lock);
     spin_lock_init(&iommu->register_lock);
 
-    qi_ctrl = iommu_qi_ctrl(iommu);
-    spin_lock_init(&qi_ctrl->qinval_lock);
-    spin_lock_init(&qi_ctrl->qinval_poll_lock);
-
-    ir_ctrl = iommu_ir_ctrl(iommu);
-    spin_lock_init(&ir_ctrl->iremap_lock);
+    iommu->intel = alloc_intel_iommu();
 
     drhd->iommu = iommu;
     return iommu;
@@ -1036,6 +1105,7 @@ static void free_iommu(struct iommu *iom
         free_xenheap_page((void *)iommu->root_entry);
     if ( iommu->reg )
         iounmap(iommu->reg);
+    free_intel_iommu(iommu->intel);
     free_irq(iommu->vector);
     xfree(iommu);
 }
@@ -1063,7 +1133,7 @@ int intel_iommu_domain_init(struct domai
         iommu = drhd->iommu ? : iommu_alloc(drhd);
 
     /* calculate AGAW */
-    if (guest_width > cap_mgaw(iommu->cap))
+    if ( guest_width > cap_mgaw(iommu->cap) )
         guest_width = cap_mgaw(iommu->cap);
     adjust_width = guestwidth_to_adjustwidth(guest_width);
     agaw = width_to_agaw(adjust_width);
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/vtd/iommu.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/drivers/passthrough/vtd/iommu.h       Mon Mar 17 10:45:24 2008 +0000
@@ -0,0 +1,454 @@
+/*
+ * 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.
+ *
+ * Copyright (C) Ashok Raj <ashok.raj@xxxxxxxxx>
+ */
+
+#ifndef _INTEL_IOMMU_H_
+#define _INTEL_IOMMU_H_
+
+#include <xen/types.h>
+
+/*
+ * Intel IOMMU register specification per version 1.0 public spec.
+ */
+
+#define    DMAR_VER_REG    0x0    /* Arch version supported by this IOMMU */
+#define    DMAR_CAP_REG    0x8    /* Hardware supported capabilities */
+#define    DMAR_ECAP_REG    0x10    /* Extended capabilities supported */
+#define    DMAR_GCMD_REG    0x18    /* Global command register */
+#define    DMAR_GSTS_REG    0x1c    /* Global status register */
+#define    DMAR_RTADDR_REG    0x20    /* Root entry table */
+#define    DMAR_CCMD_REG    0x28    /* Context command reg */
+#define    DMAR_FSTS_REG    0x34    /* Fault Status register */
+#define    DMAR_FECTL_REG    0x38    /* Fault control register */
+#define    DMAR_FEDATA_REG    0x3c    /* Fault event interrupt data register */
+#define    DMAR_FEADDR_REG    0x40    /* Fault event interrupt addr register */
+#define    DMAR_FEUADDR_REG 0x44    /* Upper address register */
+#define    DMAR_AFLOG_REG    0x58    /* Advanced Fault control */
+#define    DMAR_PMEN_REG    0x64    /* Enable Protected Memory Region */
+#define    DMAR_PLMBASE_REG 0x68    /* PMRR Low addr */
+#define    DMAR_PLMLIMIT_REG 0x6c    /* PMRR low limit */
+#define    DMAR_PHMBASE_REG 0x70    /* pmrr high base addr */
+#define    DMAR_PHMLIMIT_REG 0x78    /* pmrr high limit */
+#define    DMAR_IQH_REG    0x80    /* invalidation queue head */
+#define    DMAR_IQT_REG    0x88    /* invalidation queue tail */
+#define    DMAR_IQA_REG    0x90    /* invalidation queue addr */
+#define    DMAR_IRTA_REG   0xB8    /* intr remap */
+
+#define OFFSET_STRIDE        (9)
+#define dmar_readl(dmar, reg) readl(dmar + reg)
+#define dmar_writel(dmar, reg, val) writel(val, dmar + reg)
+#define dmar_readq(dmar, reg) ({ \
+        u32 lo, hi; \
+        lo = dmar_readl(dmar, reg); \
+        hi = dmar_readl(dmar, reg + 4); \
+        (((u64) hi) << 32) + lo; })
+#define dmar_writeq(dmar, reg, val) do {\
+        dmar_writel(dmar, reg, (u32)val); \
+        dmar_writel(dmar, reg + 4, (u32)((u64) val >> 32)); \
+    } while (0)
+
+#define VER_MAJOR(v)        (((v) & 0xf0) >> 4)
+#define VER_MINOR(v)        ((v) & 0x0f)
+
+/*
+ * Decoding Capability Register
+ */
+#define cap_read_drain(c)    (((c) >> 55) & 1)
+#define cap_write_drain(c)    (((c) >> 54) & 1)
+#define cap_max_amask_val(c)    (((c) >> 48) & 0x3f)
+#define cap_num_fault_regs(c)    ((((c) >> 40) & 0xff) + 1)
+#define cap_pgsel_inv(c)       (((c) >> 39) & 1)
+
+#define cap_super_page_val(c)    (((c) >> 34) & 0xf)
+#define cap_super_offset(c)    (((find_first_bit(&cap_super_page_val(c), 4)) \
+                    * OFFSET_STRIDE) + 21)
+
+#define cap_fault_reg_offset(c)    ((((c) >> 24) & 0x3ff) * 16)
+
+#define cap_isoch(c)        (((c) >> 23) & 1)
+#define cap_qos(c)        (((c) >> 22) & 1)
+#define cap_mgaw(c)        ((((c) >> 16) & 0x3f) + 1)
+#define cap_sagaw(c)        (((c) >> 8) & 0x1f)
+#define cap_caching_mode(c)    (((c) >> 7) & 1)
+#define cap_phmr(c)        (((c) >> 6) & 1)
+#define cap_plmr(c)        (((c) >> 5) & 1)
+#define cap_rwbf(c)        (((c) >> 4) & 1)
+#define cap_afl(c)        (((c) >> 3) & 1)
+#define cap_ndoms(c)        (1 << (4 + 2 * ((c) & 0x7)))
+
+/*
+ * Extended Capability Register
+ */
+
+#define ecap_niotlb_iunits(e)    ((((e) >> 24) & 0xff) + 1)
+#define ecap_iotlb_offset(e)     ((((e) >> 8) & 0x3ff) * 16)
+#define ecap_coherent(e)         ((e >> 0) & 0x1)
+#define ecap_queued_inval(e)     ((e >> 1) & 0x1)
+#define ecap_dev_iotlb(e)        ((e >> 2) & 0x1)
+#define ecap_intr_remap(e)       ((e >> 3) & 0x1)
+#define ecap_ext_intr(e)         ((e >> 4) & 0x1)
+#define ecap_cache_hints(e)      ((e >> 5) & 0x1)
+#define ecap_pass_thru(e)        ((e >> 6) & 0x1)
+
+/* IOTLB_REG */
+#define DMA_TLB_FLUSH_GRANU_OFFSET  60
+#define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60)
+#define DMA_TLB_DSI_FLUSH (((u64)2) << 60)
+#define DMA_TLB_PSI_FLUSH (((u64)3) << 60)
+#define DMA_TLB_IIRG(x) (((x) >> 60) & 7) 
+#define DMA_TLB_IAIG(val) (((val) >> 57) & 7)
+#define DMA_TLB_DID(x) (((u64)(x & 0xffff)) << 32)
+
+#define DMA_TLB_READ_DRAIN (((u64)1) << 49)
+#define DMA_TLB_WRITE_DRAIN (((u64)1) << 48)
+#define DMA_TLB_IVT (((u64)1) << 63)
+
+#define DMA_TLB_IVA_ADDR(x) ((((u64)x) >> 12) << 12)
+#define DMA_TLB_IVA_HINT(x) ((((u64)x) & 1) << 6)
+
+/* GCMD_REG */
+#define DMA_GCMD_TE     (((u64)1) << 31)
+#define DMA_GCMD_SRTP   (((u64)1) << 30)
+#define DMA_GCMD_SFL    (((u64)1) << 29)
+#define DMA_GCMD_EAFL   (((u64)1) << 28)
+#define DMA_GCMD_WBF    (((u64)1) << 27)
+#define DMA_GCMD_QIE    (((u64)1) << 26)
+#define DMA_GCMD_IRE    (((u64)1) << 25)
+#define DMA_GCMD_SIRTP  (((u64)1) << 24)
+#define DMA_GCMD_CFI    (((u64)1) << 23)
+
+/* GSTS_REG */
+#define DMA_GSTS_TES    (((u64)1) << 31)
+#define DMA_GSTS_RTPS   (((u64)1) << 30)
+#define DMA_GSTS_FLS    (((u64)1) << 29)
+#define DMA_GSTS_AFLS   (((u64)1) << 28)
+#define DMA_GSTS_WBFS   (((u64)1) << 27)
+#define DMA_GSTS_QIES   (((u64)1) <<26)
+#define DMA_GSTS_IRES   (((u64)1) <<25)
+#define DMA_GSTS_SIRTPS (((u64)1) << 24)
+#define DMA_GSTS_CFIS   (((u64)1) <<23)
+
+/* PMEN_REG */
+#define DMA_PMEN_EPM    (((u32)1) << 31)
+#define DMA_PMEN_PRS    (((u32)1) << 0)
+
+/* CCMD_REG */
+#define DMA_CCMD_INVL_GRANU_OFFSET  61
+#define DMA_CCMD_ICC   (((u64)1) << 63)
+#define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
+#define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61)
+#define DMA_CCMD_DEVICE_INVL (((u64)3) << 61)
+#define DMA_CCMD_FM(m) (((u64)((m) & 0x3)) << 32)
+#define DMA_CCMD_CIRG(x) ((((u64)3) << 61) & x)
+#define DMA_CCMD_MASK_NOBIT 0
+#define DMA_CCMD_MASK_1BIT 1
+#define DMA_CCMD_MASK_2BIT 2
+#define DMA_CCMD_MASK_3BIT 3
+#define DMA_CCMD_SID(s) (((u64)((s) & 0xffff)) << 16)
+#define DMA_CCMD_DID(d) ((u64)((d) & 0xffff))
+
+#define DMA_CCMD_CAIG_MASK(x) (((u64)x) & ((u64) 0x3 << 59))
+
+/* FECTL_REG */
+#define DMA_FECTL_IM (((u64)1) << 31)
+
+/* FSTS_REG */
+#define DMA_FSTS_PFO ((u64)1 << 0)
+#define DMA_FSTS_PPF ((u64)1 << 1)
+#define DMA_FSTS_AFO ((u64)1 << 2)
+#define DMA_FSTS_APF ((u64)1 << 3)
+#define DMA_FSTS_IQE ((u64)1 << 4)
+#define DMA_FSTS_ICE ((u64)1 << 5)
+#define DMA_FSTS_ITE ((u64)1 << 6)
+#define DMA_FSTS_FAULTS    DMA_FSTS_PFO | DMA_FSTS_PPF | DMA_FSTS_AFO | 
DMA_FSTS_APF | DMA_FSTS_IQE | DMA_FSTS_ICE | DMA_FSTS_ITE
+#define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
+
+/* FRCD_REG, 32 bits access */
+#define DMA_FRCD_F (((u64)1) << 31)
+#define dma_frcd_type(d) ((d >> 30) & 1)
+#define dma_frcd_fault_reason(c) (c & 0xff)
+#define dma_frcd_source_id(c) (c & 0xffff)
+#define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */
+
+/*
+ * 0: Present
+ * 1-11: Reserved
+ * 12-63: Context Ptr (12 - (haw-1))
+ * 64-127: Reserved
+ */
+struct root_entry {
+    u64    val;
+    u64    rsvd1;
+};
+#define root_present(root)    ((root).val & 1)
+#define set_root_present(root) do {(root).val |= 1;} while(0)
+#define get_context_addr(root) ((root).val & PAGE_MASK_4K)
+#define set_root_value(root, value) \
+    do {(root).val |= ((value) & PAGE_MASK_4K);} while(0)
+
+struct context_entry {
+    u64 lo;
+    u64 hi;
+};
+#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry))
+#define context_present(c) ((c).lo & 1)
+#define context_fault_disable(c) (((c).lo >> 1) & 1)
+#define context_translation_type(c) (((c).lo >> 2) & 3)
+#define context_address_root(c) ((c).lo & PAGE_MASK_4K)
+#define context_address_width(c) ((c).hi &  7)
+#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1))
+
+#define context_set_present(c) do {(c).lo |= 1;} while(0)
+#define context_clear_present(c) do {(c).lo &= ~1;} while(0)
+#define context_set_fault_enable(c) \
+    do {(c).lo &= (((u64)-1) << 2) | 1;} while(0)
+
+#define context_set_translation_type(c, val) do { \
+        (c).lo &= (((u64)-1) << 4) | 3; \
+        (c).lo |= (val & 3) << 2; \
+    } while(0)
+#define CONTEXT_TT_MULTI_LEVEL 0
+#define CONTEXT_TT_DEV_IOTLB   1
+#define CONTEXT_TT_PASS_THRU   2
+
+#define context_set_address_root(c, val) \
+    do {(c).lo &= 0xfff; (c).lo |= (val) & PAGE_MASK_4K ;} while(0)
+#define context_set_address_width(c, val) \
+    do {(c).hi &= 0xfffffff8; (c).hi |= (val) & 7;} while(0)
+#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while(0)
+
+/* page table handling */
+#define LEVEL_STRIDE       (9)
+#define LEVEL_MASK         ((1 << LEVEL_STRIDE) - 1)
+#define agaw_to_level(val) ((val) + 2)
+#define agaw_to_width(val) (30 + val * LEVEL_STRIDE)
+#define width_to_agaw(w)   ((w - 30)/LEVEL_STRIDE)
+#define level_to_offset_bits(l) (12 + (l - 1) * LEVEL_STRIDE)
+#define address_level_offset(addr, level) \
+            ((addr >> level_to_offset_bits(level)) & LEVEL_MASK)
+#define level_mask(l) (((u64)(-1)) << level_to_offset_bits(l))
+#define level_size(l) (1 << level_to_offset_bits(l))
+#define align_to_level(addr, l) ((addr + level_size(l) - 1) & level_mask(l))
+
+/*
+ * 0: readable
+ * 1: writable
+ * 2-6: reserved
+ * 7: super page
+ * 8-11: available
+ * 12-63: Host physcial address
+ */
+struct dma_pte {
+    u64 val;
+};
+#define dma_clear_pte(p)    do {(p).val = 0;} while(0)
+#define dma_set_pte_readable(p) do {(p).val |= 1;} while(0)
+#define dma_set_pte_writable(p) do {(p).val |= 2;} while(0)
+#define dma_set_pte_superpage(p) do {(p).val |= 8;} while(0)
+#define dma_set_pte_prot(p, prot) do { (p).val = (((p).val >> 2) << 2) | 
((prot) & 3);} while (0)
+#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
+#define dma_set_pte_addr(p, addr) do {(p).val |= ((addr) >> PAGE_SHIFT_4K) << 
PAGE_SHIFT_4K;} while(0)
+#define DMA_PTE_READ (1)
+#define DMA_PTE_WRITE (2)
+#define dma_pte_present(p) (((p).val & 3) != 0)
+
+/* interrupt remap entry */
+struct iremap_entry {
+  union {
+    u64 lo_val;
+    struct {
+        u64 p       : 1,
+            fpd     : 1,
+            dm      : 1,
+            rh      : 1,
+            tm      : 1,
+            dlm     : 3,
+            avail   : 4,
+            res_1   : 4,
+            vector  : 8,
+            res_2   : 8,
+            dst     : 32;
+    }lo;
+  };
+  union {
+    u64 hi_val;
+    struct {
+        u64 sid     : 16,
+            sq      : 2,
+            svt     : 2,
+            res_1   : 44;
+    }hi;
+  };
+};
+#define IREMAP_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct iremap_entry))
+#define iremap_present(v) ((v).lo & 1)
+#define iremap_fault_disable(v) (((v).lo >> 1) & 1)
+
+#define iremap_set_present(v) do {(v).lo |= 1;} while(0)
+#define iremap_clear_present(v) do {(v).lo &= ~1;} while(0)
+
+/* queue invalidation entry */
+struct qinval_entry {
+    union {
+        struct {
+            struct {
+                u64 type    : 4,
+                    granu   : 2,
+                    res_1   : 10,
+                    did     : 16,
+                    sid     : 16,
+                    fm      : 2,
+                    res_2   : 14;
+            }lo;
+            struct {
+                u64 res;
+            }hi;
+        }cc_inv_dsc;
+        struct {
+            struct {
+                u64 type    : 4,
+                    granu   : 2,
+                    dw      : 1,
+                    dr      : 1,
+                    res_1   : 8,
+                    did     : 16,
+                    res_2   : 32;
+            }lo;
+            struct {
+                u64 am      : 6,
+                    ih      : 1,
+                    res_1   : 5,
+                    addr    : 52;
+            }hi;
+        }iotlb_inv_dsc;
+        struct {
+            struct {
+                u64 type    : 4,
+                    res_1   : 12,
+                    max_invs_pend: 5,
+                    res_2   : 11,
+                    sid     : 16,
+                    res_3   : 16;
+            }lo;
+            struct {
+                u64 size    : 1,
+                    res_1   : 11,
+                    addr    : 52;
+            }hi;
+        }dev_iotlb_inv_dsc;
+        struct {
+            struct {
+                u64 type    : 4,
+                    granu   : 1,
+                    res_1   : 22,
+                    im      : 5,
+                    iidx    : 16,
+                    res_2   : 16;
+            }lo;
+            struct {
+                u64 res;
+            }hi;
+        }iec_inv_dsc;
+        struct {
+            struct {
+                u64 type    : 4,
+                    iflag   : 1,
+                    sw      : 1,
+                    fn      : 1,
+                    res_1   : 25,
+                    sdata   : 32;
+            }lo;
+            struct {
+                u64 res_1   : 2,
+                    saddr   : 62;
+            }hi;
+        }inv_wait_dsc;
+    }q;
+};
+
+struct poll_info {
+    u64 saddr;
+    u32 udata;
+};
+
+#define QINVAL_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct qinval_entry))
+#define qinval_present(v) ((v).lo & 1)
+#define qinval_fault_disable(v) (((v).lo >> 1) & 1)
+
+#define qinval_set_present(v) do {(v).lo |= 1;} while(0)
+#define qinval_clear_present(v) do {(v).lo &= ~1;} while(0)
+
+#define RESERVED_VAL        0
+
+#define TYPE_INVAL_CONTEXT      0x1
+#define TYPE_INVAL_IOTLB        0x2
+#define TYPE_INVAL_DEVICE_IOTLB 0x3
+#define TYPE_INVAL_IEC          0x4
+#define TYPE_INVAL_WAIT         0x5
+
+#define NOTIFY_TYPE_POLL        1
+#define NOTIFY_TYPE_INTR        1
+#define INTERRUTP_FLAG          1
+#define STATUS_WRITE            1
+#define FENCE_FLAG              1
+
+#define IEC_GLOBAL_INVL         0
+#define IEC_INDEX_INVL          1
+#define IRTA_REG_EIME_SHIFT     11
+#define IRTA_REG_TABLE_SIZE     7    // 4k page = 256 * 16 byte entries
+                                     // 2^^(IRTA_REG_TABLE_SIZE + 1) = 256
+                                     // IRTA_REG_TABLE_SIZE = 7
+
+#define VTD_PAGE_TABLE_LEVEL_3  3
+#define VTD_PAGE_TABLE_LEVEL_4  4
+
+#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
+#define MAX_IOMMU_REGS 0xc0
+
+extern struct list_head acpi_drhd_units;
+extern struct list_head acpi_rmrr_units;
+extern struct list_head acpi_ioapic_units;
+
+struct qi_ctrl {
+    struct qinval_entry *qinval;         /* queue invalidation page */
+    int qinval_index;                    /* queue invalidation index */
+    spinlock_t qinval_lock;      /* lock for queue invalidation page */
+    spinlock_t qinval_poll_lock; /* lock for queue invalidation poll addr */
+    volatile u32 qinval_poll_status;     /* used by poll methord to sync */
+};
+
+struct ir_ctrl {
+    struct iremap_entry *iremap; /* interrupt remap table */
+    int iremap_index;            /* interrupt remap index */
+    spinlock_t iremap_lock;      /* lock for irq remappping table */
+};
+
+struct iommu_flush {
+    int (*context)(void *iommu, u16 did, u16 source_id,
+                   u8 function_mask, u64 type, int non_present_entry_flush);
+    int (*iotlb)(void *iommu, u16 did, u64 addr, unsigned int size_order,
+                 u64 type, int non_present_entry_flush);
+};
+
+struct intel_iommu {
+    struct qi_ctrl qi_ctrl;
+    struct ir_ctrl ir_ctrl;
+    struct iommu_flush flush;
+};
+
+#endif
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/vtd/qinval.c
--- a/xen/drivers/passthrough/vtd/qinval.c      Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/drivers/passthrough/vtd/qinval.c      Mon Mar 17 10:45:24 2008 +0000
@@ -19,15 +19,9 @@
  */
 
 
-#include <xen/init.h>
-#include <xen/irq.h>
-#include <xen/spinlock.h>
 #include <xen/sched.h>
-#include <xen/xmalloc.h>
-#include <xen/domain_page.h>
-#include <asm/delay.h>
-#include <asm/string.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
+#include "iommu.h"
 #include "dmar.h"
 #include "vtd.h"
 #include "../pci-direct.h"
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/vtd/utils.c
--- a/xen/drivers/passthrough/vtd/utils.c       Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/drivers/passthrough/vtd/utils.c       Mon Mar 17 10:45:24 2008 +0000
@@ -17,21 +17,14 @@
  * Copyright (C) Allen Kay <allen.m.kay@xxxxxxxxx>
  */
 
-#include <xen/init.h>
-#include <xen/bitmap.h>
-#include <xen/irq.h>
-#include <xen/spinlock.h>
 #include <xen/sched.h>
 #include <xen/delay.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
+#include "iommu.h"
 #include "dmar.h"
 #include "../pci-direct.h"
 #include "../pci_regs.h"
 #include "msi.h"
-
-#include <xen/mm.h>
-#include <xen/xmalloc.h>
-#include <xen/inttypes.h>
 
 #define INTEL   0x8086
 #define SEABURG 0x4000
diff -r af33f2054f47 -r bf8a3fc79093 xen/drivers/passthrough/vtd/vtd.h
--- a/xen/drivers/passthrough/vtd/vtd.h Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/drivers/passthrough/vtd/vtd.h Mon Mar 17 10:45:24 2008 +0000
@@ -21,16 +21,7 @@
 #ifndef _VTD_H_
 #define _VTD_H_
 
-#include <xen/list.h>
-#include <asm/iommu.h>
-
-#define VTDPREFIX "[VT-D]"
-
-#define DMAR_OPERATION_TIMEOUT (HZ*60) /* 1m */
-#define time_after(a,b)         \
-        (typecheck(unsigned long, a) && \
-         typecheck(unsigned long, b) && \
-         ((long)(b) - (long)(a) < 0))
+#include <xen/iommu.h>
 
 struct IO_APIC_route_remap_entry {
     union {
diff -r af33f2054f47 -r bf8a3fc79093 xen/include/asm-x86/fixmap.h
--- a/xen/include/asm-x86/fixmap.h      Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/include/asm-x86/fixmap.h      Mon Mar 17 10:45:24 2008 +0000
@@ -17,7 +17,7 @@
 #include <asm/acpi.h>
 #include <asm/page.h>
 #include <xen/kexec.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
 #include <asm/amd-iommu.h>
 
 /*
diff -r af33f2054f47 -r bf8a3fc79093 xen/include/asm-x86/hvm/domain.h
--- a/xen/include/asm-x86/hvm/domain.h  Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/include/asm-x86/hvm/domain.h  Mon Mar 17 10:45:24 2008 +0000
@@ -21,13 +21,13 @@
 #ifndef __ASM_X86_HVM_DOMAIN_H__
 #define __ASM_X86_HVM_DOMAIN_H__
 
-#include <asm/iommu.h>
+#include <xen/iommu.h>
 #include <asm/hvm/irq.h>
 #include <asm/hvm/vpt.h>
 #include <asm/hvm/vlapic.h>
 #include <asm/hvm/vioapic.h>
 #include <asm/hvm/io.h>
-#include <asm/hvm/iommu.h>
+#include <xen/hvm/iommu.h>
 #include <public/hvm/params.h>
 #include <public/hvm/save.h>
 
diff -r af33f2054f47 -r bf8a3fc79093 xen/include/asm-x86/hvm/iommu.h
--- a/xen/include/asm-x86/hvm/iommu.h   Sun Mar 16 14:11:34 2008 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) Allen Kay <allen.m.kay@xxxxxxxxx>
- */
-
-#ifndef __ASM_X86_HVM_IOMMU_H__
-#define __ASM_X86_HVM_IOMMU_H__
-
-#include <asm/iommu.h>
-#include <asm/hvm/irq.h>
-#include <asm/hvm/vpt.h>
-#include <asm/hvm/vlapic.h>
-#include <asm/hvm/io.h>
-#include <public/hvm/params.h>
-#include <public/hvm/save.h>
-
-struct g2m_ioport {
-    struct list_head list;
-    unsigned int gport;
-    unsigned int mport;
-    unsigned int np;
-};
-
-struct hvm_iommu {
-    spinlock_t iommu_list_lock;    /* protect iommu specific lists */
-    struct list_head pdev_list;    /* direct accessed pci devices */
-    struct dma_pte *pgd;           /* io page directory root */
-    spinlock_t mapping_lock;       /* io page table lock */
-    int agaw;     /* adjusted guest address width, 0 is level 2 30-bit */
-    struct list_head g2m_ioport_list;  /* guest to machine ioport mapping */
-    domid_t iommu_domid;           /* domain id stored in iommu */
-
-    /* amd iommu support */
-    int domain_id;
-    int paging_mode;
-    void *root_table;
-
-    /* iommu_ops */
-    struct iommu_ops *platform_ops;
-};
-
-#endif // __ASM_X86_HVM_IOMMU_H__
diff -r af33f2054f47 -r bf8a3fc79093 xen/include/asm-x86/hvm/vmx/intel-iommu.h
--- a/xen/include/asm-x86/hvm/vmx/intel-iommu.h Sun Mar 16 14:11:34 2008 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,460 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) Ashok Raj <ashok.raj@xxxxxxxxx>
- */
-
-#ifndef _INTEL_IOMMU_H_
-#define _INTEL_IOMMU_H_
-
-#include <xen/types.h>
-
-/*
- * Intel IOMMU register specification per version 1.0 public spec.
- */
-
-#define    DMAR_VER_REG    0x0    /* Arch version supported by this IOMMU */
-#define    DMAR_CAP_REG    0x8    /* Hardware supported capabilities */
-#define    DMAR_ECAP_REG    0x10    /* Extended capabilities supported */
-#define    DMAR_GCMD_REG    0x18    /* Global command register */
-#define    DMAR_GSTS_REG    0x1c    /* Global status register */
-#define    DMAR_RTADDR_REG    0x20    /* Root entry table */
-#define    DMAR_CCMD_REG    0x28    /* Context command reg */
-#define    DMAR_FSTS_REG    0x34    /* Fault Status register */
-#define    DMAR_FECTL_REG    0x38    /* Fault control register */
-#define    DMAR_FEDATA_REG    0x3c    /* Fault event interrupt data register */
-#define    DMAR_FEADDR_REG    0x40    /* Fault event interrupt addr register */
-#define    DMAR_FEUADDR_REG 0x44    /* Upper address register */
-#define    DMAR_AFLOG_REG    0x58    /* Advanced Fault control */
-#define    DMAR_PMEN_REG    0x64    /* Enable Protected Memory Region */
-#define    DMAR_PLMBASE_REG 0x68    /* PMRR Low addr */
-#define    DMAR_PLMLIMIT_REG 0x6c    /* PMRR low limit */
-#define    DMAR_PHMBASE_REG 0x70    /* pmrr high base addr */
-#define    DMAR_PHMLIMIT_REG 0x78    /* pmrr high limit */
-#define    DMAR_IQH_REG    0x80    /* invalidation queue head */
-#define    DMAR_IQT_REG    0x88    /* invalidation queue tail */
-#define    DMAR_IQA_REG    0x90    /* invalidation queue addr */
-#define    DMAR_IRTA_REG   0xB8    /* intr remap */
-
-#define OFFSET_STRIDE        (9)
-#define dmar_readl(dmar, reg) readl(dmar + reg)
-#define dmar_writel(dmar, reg, val) writel(val, dmar + reg)
-#define dmar_readq(dmar, reg) ({ \
-        u32 lo, hi; \
-        lo = dmar_readl(dmar, reg); \
-        hi = dmar_readl(dmar, reg + 4); \
-        (((u64) hi) << 32) + lo; })
-#define dmar_writeq(dmar, reg, val) do {\
-        dmar_writel(dmar, reg, (u32)val); \
-        dmar_writel(dmar, reg + 4, (u32)((u64) val >> 32)); \
-    } while (0)
-
-#define VER_MAJOR(v)        (((v) & 0xf0) >> 4)
-#define VER_MINOR(v)        ((v) & 0x0f)
-
-/*
- * Decoding Capability Register
- */
-#define cap_read_drain(c)    (((c) >> 55) & 1)
-#define cap_write_drain(c)    (((c) >> 54) & 1)
-#define cap_max_amask_val(c)    (((c) >> 48) & 0x3f)
-#define cap_num_fault_regs(c)    ((((c) >> 40) & 0xff) + 1)
-#define cap_pgsel_inv(c)       (((c) >> 39) & 1)
-
-#define cap_super_page_val(c)    (((c) >> 34) & 0xf)
-#define cap_super_offset(c)    (((find_first_bit(&cap_super_page_val(c), 4)) \
-                    * OFFSET_STRIDE) + 21)
-
-#define cap_fault_reg_offset(c)    ((((c) >> 24) & 0x3ff) * 16)
-
-#define cap_isoch(c)        (((c) >> 23) & 1)
-#define cap_qos(c)        (((c) >> 22) & 1)
-#define cap_mgaw(c)        ((((c) >> 16) & 0x3f) + 1)
-#define cap_sagaw(c)        (((c) >> 8) & 0x1f)
-#define cap_caching_mode(c)    (((c) >> 7) & 1)
-#define cap_phmr(c)        (((c) >> 6) & 1)
-#define cap_plmr(c)        (((c) >> 5) & 1)
-#define cap_rwbf(c)        (((c) >> 4) & 1)
-#define cap_afl(c)        (((c) >> 3) & 1)
-#define cap_ndoms(c)        (1 << (4 + 2 * ((c) & 0x7)))
-
-/*
- * Extended Capability Register
- */
-
-#define ecap_niotlb_iunits(e)    ((((e) >> 24) & 0xff) + 1)
-#define ecap_iotlb_offset(e)     ((((e) >> 8) & 0x3ff) * 16)
-#define ecap_coherent(e)         ((e >> 0) & 0x1)
-#define ecap_queued_inval(e)     ((e >> 1) & 0x1)
-#define ecap_dev_iotlb(e)        ((e >> 2) & 0x1)
-#define ecap_intr_remap(e)       ((e >> 3) & 0x1)
-#define ecap_ext_intr(e)         ((e >> 4) & 0x1)
-#define ecap_cache_hints(e)      ((e >> 5) & 0x1)
-#define ecap_pass_thru(e)        ((e >> 6) & 0x1)
-
-#define PAGE_SHIFT_4K        (12)
-#define PAGE_SIZE_4K        (1UL << PAGE_SHIFT_4K)
-#define PAGE_MASK_4K        (((u64)-1) << PAGE_SHIFT_4K)
-#define PAGE_ALIGN_4K(addr)    (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
-
-/* IOTLB_REG */
-#define DMA_TLB_FLUSH_GRANU_OFFSET  60
-#define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60)
-#define DMA_TLB_DSI_FLUSH (((u64)2) << 60)
-#define DMA_TLB_PSI_FLUSH (((u64)3) << 60)
-#define DMA_TLB_IIRG(x) (((x) >> 60) & 7) 
-#define DMA_TLB_IAIG(val) (((val) >> 57) & 7)
-#define DMA_TLB_DID(x) (((u64)(x & 0xffff)) << 32)
-
-#define DMA_TLB_READ_DRAIN (((u64)1) << 49)
-#define DMA_TLB_WRITE_DRAIN (((u64)1) << 48)
-#define DMA_TLB_IVT (((u64)1) << 63)
-
-#define DMA_TLB_IVA_ADDR(x) ((((u64)x) >> 12) << 12)
-#define DMA_TLB_IVA_HINT(x) ((((u64)x) & 1) << 6)
-
-/* GCMD_REG */
-#define DMA_GCMD_TE     (((u64)1) << 31)
-#define DMA_GCMD_SRTP   (((u64)1) << 30)
-#define DMA_GCMD_SFL    (((u64)1) << 29)
-#define DMA_GCMD_EAFL   (((u64)1) << 28)
-#define DMA_GCMD_WBF    (((u64)1) << 27)
-#define DMA_GCMD_QIE    (((u64)1) << 26)
-#define DMA_GCMD_IRE    (((u64)1) << 25)
-#define DMA_GCMD_SIRTP  (((u64)1) << 24)
-#define DMA_GCMD_CFI    (((u64)1) << 23)
-
-/* GSTS_REG */
-#define DMA_GSTS_TES    (((u64)1) << 31)
-#define DMA_GSTS_RTPS   (((u64)1) << 30)
-#define DMA_GSTS_FLS    (((u64)1) << 29)
-#define DMA_GSTS_AFLS   (((u64)1) << 28)
-#define DMA_GSTS_WBFS   (((u64)1) << 27)
-#define DMA_GSTS_QIES   (((u64)1) <<26)
-#define DMA_GSTS_IRES   (((u64)1) <<25)
-#define DMA_GSTS_SIRTPS (((u64)1) << 24)
-#define DMA_GSTS_CFIS   (((u64)1) <<23)
-
-/* PMEN_REG */
-#define DMA_PMEN_EPM    (((u32)1) << 31)
-#define DMA_PMEN_PRS    (((u32)1) << 0)
-
-/* CCMD_REG */
-#define DMA_CCMD_INVL_GRANU_OFFSET  61
-#define DMA_CCMD_ICC   (((u64)1) << 63)
-#define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
-#define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61)
-#define DMA_CCMD_DEVICE_INVL (((u64)3) << 61)
-#define DMA_CCMD_FM(m) (((u64)((m) & 0x3)) << 32)
-#define DMA_CCMD_CIRG(x) ((((u64)3) << 61) & x)
-#define DMA_CCMD_MASK_NOBIT 0
-#define DMA_CCMD_MASK_1BIT 1
-#define DMA_CCMD_MASK_2BIT 2
-#define DMA_CCMD_MASK_3BIT 3
-#define DMA_CCMD_SID(s) (((u64)((s) & 0xffff)) << 16)
-#define DMA_CCMD_DID(d) ((u64)((d) & 0xffff))
-
-#define DMA_CCMD_CAIG_MASK(x) (((u64)x) & ((u64) 0x3 << 59))
-
-/* FECTL_REG */
-#define DMA_FECTL_IM (((u64)1) << 31)
-
-/* FSTS_REG */
-#define DMA_FSTS_PFO ((u64)1 << 0)
-#define DMA_FSTS_PPF ((u64)1 << 1)
-#define DMA_FSTS_AFO ((u64)1 << 2)
-#define DMA_FSTS_APF ((u64)1 << 3)
-#define DMA_FSTS_IQE ((u64)1 << 4)
-#define DMA_FSTS_ICE ((u64)1 << 5)
-#define DMA_FSTS_ITE ((u64)1 << 6)
-#define DMA_FSTS_FAULTS    DMA_FSTS_PFO | DMA_FSTS_PPF | DMA_FSTS_AFO | 
DMA_FSTS_APF | DMA_FSTS_IQE | DMA_FSTS_ICE | DMA_FSTS_ITE
-#define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
-
-/* FRCD_REG, 32 bits access */
-#define DMA_FRCD_F (((u64)1) << 31)
-#define dma_frcd_type(d) ((d >> 30) & 1)
-#define dma_frcd_fault_reason(c) (c & 0xff)
-#define dma_frcd_source_id(c) (c & 0xffff)
-#define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */
-
-/*
- * 0: Present
- * 1-11: Reserved
- * 12-63: Context Ptr (12 - (haw-1))
- * 64-127: Reserved
- */
-struct root_entry {
-    u64    val;
-    u64    rsvd1;
-};
-#define root_present(root)    ((root).val & 1)
-#define set_root_present(root) do {(root).val |= 1;} while(0)
-#define get_context_addr(root) ((root).val & PAGE_MASK_4K)
-#define set_root_value(root, value) \
-    do {(root).val |= ((value) & PAGE_MASK_4K);} while(0)
-
-struct context_entry {
-    u64 lo;
-    u64 hi;
-};
-#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry))
-#define context_present(c) ((c).lo & 1)
-#define context_fault_disable(c) (((c).lo >> 1) & 1)
-#define context_translation_type(c) (((c).lo >> 2) & 3)
-#define context_address_root(c) ((c).lo & PAGE_MASK_4K)
-#define context_address_width(c) ((c).hi &  7)
-#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1))
-
-#define context_set_present(c) do {(c).lo |= 1;} while(0)
-#define context_clear_present(c) do {(c).lo &= ~1;} while(0)
-#define context_set_fault_enable(c) \
-    do {(c).lo &= (((u64)-1) << 2) | 1;} while(0)
-
-#define context_set_translation_type(c, val) do { \
-        (c).lo &= (((u64)-1) << 4) | 3; \
-        (c).lo |= (val & 3) << 2; \
-    } while(0)
-#define CONTEXT_TT_MULTI_LEVEL 0
-#define CONTEXT_TT_DEV_IOTLB   1
-#define CONTEXT_TT_PASS_THRU   2
-
-#define context_set_address_root(c, val) \
-    do {(c).lo &= 0xfff; (c).lo |= (val) & PAGE_MASK_4K ;} while(0)
-#define context_set_address_width(c, val) \
-    do {(c).hi &= 0xfffffff8; (c).hi |= (val) & 7;} while(0)
-#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while(0)
-
-/* page table handling */
-#define LEVEL_STRIDE       (9)
-#define LEVEL_MASK         ((1 << LEVEL_STRIDE) - 1)
-#define agaw_to_level(val) ((val) + 2)
-#define agaw_to_width(val) (30 + val * LEVEL_STRIDE)
-#define width_to_agaw(w)   ((w - 30)/LEVEL_STRIDE)
-#define level_to_offset_bits(l) (12 + (l - 1) * LEVEL_STRIDE)
-#define address_level_offset(addr, level) \
-            ((addr >> level_to_offset_bits(level)) & LEVEL_MASK)
-#define level_mask(l) (((u64)(-1)) << level_to_offset_bits(l))
-#define level_size(l) (1 << level_to_offset_bits(l))
-#define align_to_level(addr, l) ((addr + level_size(l) - 1) & level_mask(l))
-
-/*
- * 0: readable
- * 1: writable
- * 2-6: reserved
- * 7: super page
- * 8-11: available
- * 12-63: Host physcial address
- */
-struct dma_pte {
-    u64 val;
-};
-#define dma_clear_pte(p)    do {(p).val = 0;} while(0)
-#define dma_set_pte_readable(p) do {(p).val |= 1;} while(0)
-#define dma_set_pte_writable(p) do {(p).val |= 2;} while(0)
-#define dma_set_pte_superpage(p) do {(p).val |= 8;} while(0)
-#define dma_set_pte_prot(p, prot) do { (p).val = (((p).val >> 2) << 2) | 
((prot) & 3);} while (0)
-#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K)
-#define dma_set_pte_addr(p, addr) do {(p).val |= ((addr) >> PAGE_SHIFT_4K) << 
PAGE_SHIFT_4K;} while(0)
-#define DMA_PTE_READ (1)
-#define DMA_PTE_WRITE (2)
-#define dma_pte_present(p) (((p).val & 3) != 0)
-
-/* interrupt remap entry */
-struct iremap_entry {
-  union {
-    u64 lo_val;
-    struct {
-        u64 p       : 1,
-            fpd     : 1,
-            dm      : 1,
-            rh      : 1,
-            tm      : 1,
-            dlm     : 3,
-            avail   : 4,
-            res_1   : 4,
-            vector  : 8,
-            res_2   : 8,
-            dst     : 32;
-    }lo;
-  };
-  union {
-    u64 hi_val;
-    struct {
-        u64 sid     : 16,
-            sq      : 2,
-            svt     : 2,
-            res_1   : 44;
-    }hi;
-  };
-};
-#define IREMAP_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct iremap_entry))
-#define iremap_present(v) ((v).lo & 1)
-#define iremap_fault_disable(v) (((v).lo >> 1) & 1)
-
-#define iremap_set_present(v) do {(v).lo |= 1;} while(0)
-#define iremap_clear_present(v) do {(v).lo &= ~1;} while(0)
-
-/* queue invalidation entry */
-struct qinval_entry {
-    union {
-        struct {
-            struct {
-                u64 type    : 4,
-                    granu   : 2,
-                    res_1   : 10,
-                    did     : 16,
-                    sid     : 16,
-                    fm      : 2,
-                    res_2   : 14;
-            }lo;
-            struct {
-                u64 res;
-            }hi;
-        }cc_inv_dsc;
-        struct {
-            struct {
-                u64 type    : 4,
-                    granu   : 2,
-                    dw      : 1,
-                    dr      : 1,
-                    res_1   : 8,
-                    did     : 16,
-                    res_2   : 32;
-            }lo;
-            struct {
-                u64 am      : 6,
-                    ih      : 1,
-                    res_1   : 5,
-                    addr    : 52;
-            }hi;
-        }iotlb_inv_dsc;
-        struct {
-            struct {
-                u64 type    : 4,
-                    res_1   : 12,
-                    max_invs_pend: 5,
-                    res_2   : 11,
-                    sid     : 16,
-                    res_3   : 16;
-            }lo;
-            struct {
-                u64 size    : 1,
-                    res_1   : 11,
-                    addr    : 52;
-            }hi;
-        }dev_iotlb_inv_dsc;
-        struct {
-            struct {
-                u64 type    : 4,
-                    granu   : 1,
-                    res_1   : 22,
-                    im      : 5,
-                    iidx    : 16,
-                    res_2   : 16;
-            }lo;
-            struct {
-                u64 res;
-            }hi;
-        }iec_inv_dsc;
-        struct {
-            struct {
-                u64 type    : 4,
-                    iflag   : 1,
-                    sw      : 1,
-                    fn      : 1,
-                    res_1   : 25,
-                    sdata   : 32;
-            }lo;
-            struct {
-                u64 res_1   : 2,
-                    saddr   : 62;
-            }hi;
-        }inv_wait_dsc;
-    }q;
-};
-
-struct poll_info {
-    u64 saddr;
-    u32 udata;
-};
-
-#define QINVAL_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct qinval_entry))
-#define qinval_present(v) ((v).lo & 1)
-#define qinval_fault_disable(v) (((v).lo >> 1) & 1)
-
-#define qinval_set_present(v) do {(v).lo |= 1;} while(0)
-#define qinval_clear_present(v) do {(v).lo &= ~1;} while(0)
-
-#define RESERVED_VAL        0
-
-#define TYPE_INVAL_CONTEXT      0x1
-#define TYPE_INVAL_IOTLB        0x2
-#define TYPE_INVAL_DEVICE_IOTLB 0x3
-#define TYPE_INVAL_IEC          0x4
-#define TYPE_INVAL_WAIT         0x5
-
-#define NOTIFY_TYPE_POLL        1
-#define NOTIFY_TYPE_INTR        1
-#define INTERRUTP_FLAG          1
-#define STATUS_WRITE            1
-#define FENCE_FLAG              1
-
-#define IEC_GLOBAL_INVL         0
-#define IEC_INDEX_INVL          1
-#define IRTA_REG_EIME_SHIFT     11
-#define IRTA_REG_TABLE_SIZE     7    // 4k page = 256 * 16 byte entries
-                                     // 2^^(IRTA_REG_TABLE_SIZE + 1) = 256
-                                     // IRTA_REG_TABLE_SIZE = 7
-
-#define VTD_PAGE_TABLE_LEVEL_3  3
-#define VTD_PAGE_TABLE_LEVEL_4  4
-
-#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
-#define MAX_IOMMUS 32
-#define MAX_IOMMU_REGS 0xc0
-
-extern struct list_head acpi_drhd_units;
-extern struct list_head acpi_rmrr_units;
-extern struct list_head acpi_ioapic_units;
-
-struct qi_ctrl {
-    struct qinval_entry *qinval;         /* queue invalidation page */
-    int qinval_index;                    /* queue invalidation index */
-    spinlock_t qinval_lock;      /* lock for queue invalidation page */
-    spinlock_t qinval_poll_lock; /* lock for queue invalidation poll addr */
-    volatile u32 qinval_poll_status;     /* used by poll methord to sync */
-};
-
-struct ir_ctrl {
-    struct iremap_entry *iremap;         /* interrupt remap table */
-    int iremap_index;                    /* interrupt remap index */
-    spinlock_t iremap_lock;      /* lock for irq remappping table */
-};
-
-struct iommu_flush {
-    int (*context)(void *iommu, u16 did, u16 source_id,
-                   u8 function_mask, u64 type, int non_present_entry_flush);
-    int (*iotlb)(void *iommu, u16 did, u64 addr, unsigned int size_order,
-                 u64 type, int non_present_entry_flush);
-};
-
-struct intel_iommu {
-    struct qi_ctrl qi_ctrl;
-    struct ir_ctrl ir_ctrl;
-    struct iommu_flush flush; 
-};
-
-#endif
diff -r af33f2054f47 -r bf8a3fc79093 xen/include/asm-x86/io_apic.h
--- a/xen/include/asm-x86/io_apic.h     Sun Mar 16 14:11:34 2008 +0000
+++ b/xen/include/asm-x86/io_apic.h     Mon Mar 17 10:45:24 2008 +0000
@@ -6,7 +6,7 @@
 #include <asm/mpspec.h>
 #include <asm/apicdef.h>
 #include <asm/fixmap.h>
-#include <asm/iommu.h>
+#include <xen/iommu.h>
 
 /*
  * Intel IO-APIC support for SMP and UP systems.
diff -r af33f2054f47 -r bf8a3fc79093 xen/include/asm-x86/iommu.h
--- a/xen/include/asm-x86/iommu.h       Sun Mar 16 14:11:34 2008 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) Allen Kay <allen.m.kay@xxxxxxxxx>
- */
-
-#ifndef _IOMMU_H_
-#define _IOMMU_H_
-
-#include <xen/init.h>
-#include <xen/list.h>
-#include <xen/spinlock.h>
-#include <asm/hvm/vmx/intel-iommu.h>
-#include <public/hvm/ioreq.h>
-#include <public/domctl.h>
-
-extern int vtd_enabled;
-extern int amd_iommu_enabled;
-
-#define iommu_enabled ( amd_iommu_enabled || vtd_enabled )
-#define domain_hvm_iommu(d)     (&d->arch.hvm_domain.hvm_iommu)
-#define domain_vmx_iommu(d)     (&d->arch.hvm_domain.hvm_iommu.vmx_iommu)
-#define iommu_qi_ctrl(iommu)    (&(iommu->intel.qi_ctrl));
-#define iommu_ir_ctrl(iommu)    (&(iommu->intel.ir_ctrl));
-#define iommu_get_flush(iommu)  (&(iommu->intel.flush));
-
-/*
- * The PCI interface treats multi-function devices as independent
- * devices.  The slot/function address of each device is encoded
- * in a single byte as follows:
- *
- * 15:8 = bus
- *  7:3 = slot
- *  2:0 = function
- */
-#define PCI_DEVFN(slot,func)  (((slot & 0x1f) << 3) | (func & 0x07))
-#define PCI_SLOT(devfn)       (((devfn) >> 3) & 0x1f)
-#define PCI_FUNC(devfn)       ((devfn) & 0x07)
-
-struct pci_dev {
-    struct list_head list;
-    u8 bus;
-    u8 devfn;
-};
-
-struct iommu {
-    struct list_head list;
-    void __iomem *reg; /* Pointer to hardware regs, virtual addr */
-    u32        gcmd;          /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
-    u64        cap;
-    u64        ecap;
-    spinlock_t lock; /* protect context, domain ids */
-    spinlock_t register_lock; /* protect iommu register handling */
-    struct root_entry *root_entry; /* virtual address */
-    unsigned int vector;
-    struct intel_iommu intel;
-};
-
-int iommu_setup(void);
-int iommu_domain_init(struct domain *d);
-void iommu_domain_destroy(struct domain *d);
-int device_assigned(u8 bus, u8 devfn);
-int assign_device(struct domain *d, u8 bus, u8 devfn);
-void deassign_device(struct domain *d, u8 bus, u8 devfn);
-void reassign_device_ownership(struct domain *source,
-                               struct domain *target,
-                               u8 bus, u8 devfn);
-int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn);
-int iommu_unmap_page(struct domain *d, unsigned long gfn);
-void iommu_flush(struct domain *d, unsigned long gfn, u64 *p2m_entry);
-void iommu_set_pgd(struct domain *d);
-void iommu_domain_teardown(struct domain *d);
-int hvm_do_IRQ_dpci(struct domain *d, unsigned int irq);
-int dpci_ioport_intercept(ioreq_t *p);
-int pt_irq_create_bind_vtd(struct domain *d,
-                           xen_domctl_bind_pt_irq_t *pt_irq_bind);
-int pt_irq_destroy_bind_vtd(struct domain *d,
-                            xen_domctl_bind_pt_irq_t *pt_irq_bind);
-unsigned int io_apic_read_remap_rte(
-    unsigned int apic, unsigned int reg);
-void io_apic_write_remap_rte(unsigned int apic,
-    unsigned int reg, unsigned int value);
-
-#define PT_IRQ_TIME_OUT MILLISECS(8)
-#define VTDPREFIX "[VT-D]"
-
-struct iommu_ops {
-    int (*init)(struct domain *d);
-    int (*assign_device)(struct domain *d, u8 bus, u8 devfn);
-    void (*teardown)(struct domain *d);
-    int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn);
-    int (*unmap_page)(struct domain *d, unsigned long gfn);
-    void (*reassign_device)(struct domain *s, struct domain *t, u8 bus, u8 
devfn);
-};
-
-#endif /* _IOMMU_H_ */
diff -r af33f2054f47 -r bf8a3fc79093 xen/include/xen/hvm/iommu.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/xen/hvm/iommu.h       Mon Mar 17 10:45:24 2008 +0000
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ *
+ * Copyright (C) Allen Kay <allen.m.kay@xxxxxxxxx>
+ */
+
+#ifndef __ASM_X86_HVM_IOMMU_H__
+#define __ASM_X86_HVM_IOMMU_H__
+
+#include <xen/iommu.h>
+#include <asm/hvm/irq.h>
+#include <asm/hvm/vpt.h>
+#include <asm/hvm/vlapic.h>
+#include <asm/hvm/io.h>
+#include <public/hvm/params.h>
+#include <public/hvm/save.h>
+
+struct g2m_ioport {
+    struct list_head list;
+    unsigned int gport;
+    unsigned int mport;
+    unsigned int np;
+};
+
+struct hvm_iommu {
+    spinlock_t iommu_list_lock;    /* protect iommu specific lists */
+    struct list_head pdev_list;    /* direct accessed pci devices */
+    struct dma_pte *pgd;           /* io page directory root */
+    spinlock_t mapping_lock;       /* io page table lock */
+    int agaw;     /* adjusted guest address width, 0 is level 2 30-bit */
+    struct list_head g2m_ioport_list;  /* guest to machine ioport mapping */
+    domid_t iommu_domid;           /* domain id stored in iommu */
+
+    /* amd iommu support */
+    int domain_id;
+    int paging_mode;
+    void *root_table;
+
+    /* iommu_ops */
+    struct iommu_ops *platform_ops;
+};
+
+#endif // __ASM_X86_HVM_IOMMU_H__
diff -r af33f2054f47 -r bf8a3fc79093 xen/include/xen/iommu.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/xen/iommu.h   Mon Mar 17 10:45:24 2008 +0000
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ *
+ * Copyright (C) Allen Kay <allen.m.kay@xxxxxxxxx>
+ */
+
+#ifndef _IOMMU_H_
+#define _IOMMU_H_
+
+#include <xen/init.h>
+#include <xen/list.h>
+#include <xen/spinlock.h>
+#include <public/hvm/ioreq.h>
+#include <public/domctl.h>
+
+extern int vtd_enabled;
+extern int amd_iommu_enabled;
+
+#define iommu_enabled ( amd_iommu_enabled || vtd_enabled )
+#define domain_hvm_iommu(d)     (&d->arch.hvm_domain.hvm_iommu)
+#define domain_vmx_iommu(d)     (&d->arch.hvm_domain.hvm_iommu.vmx_iommu)
+
+#define MAX_IOMMUS 32
+
+#define PAGE_SHIFT_4K       (12)
+#define PAGE_SIZE_4K        (1UL << PAGE_SHIFT_4K)
+#define PAGE_MASK_4K        (((u64)-1) << PAGE_SHIFT_4K)
+#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K)
+
+/*
+ * The PCI interface treats multi-function devices as independent
+ * devices.  The slot/function address of each device is encoded
+ * in a single byte as follows:
+ *
+ * 15:8 = bus
+ *  7:3 = slot
+ *  2:0 = function
+ */
+#define PCI_DEVFN(slot,func)  (((slot & 0x1f) << 3) | (func & 0x07))
+#define PCI_SLOT(devfn)       (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn)       ((devfn) & 0x07)
+
+struct pci_dev {
+    struct list_head list;
+    u8 bus;
+    u8 devfn;
+};
+
+struct iommu {
+    struct list_head list;
+    void __iomem *reg; /* Pointer to hardware regs, virtual addr */
+    u32        gcmd;          /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
+    u64        cap;
+    u64        ecap;
+    spinlock_t lock; /* protect context, domain ids */
+    spinlock_t register_lock; /* protect iommu register handling */
+    struct root_entry *root_entry; /* virtual address */
+    unsigned int vector;
+    struct intel_iommu *intel;
+};
+
+int iommu_setup(void);
+int iommu_domain_init(struct domain *d);
+void iommu_domain_destroy(struct domain *d);
+int device_assigned(u8 bus, u8 devfn);
+int assign_device(struct domain *d, u8 bus, u8 devfn);
+void deassign_device(struct domain *d, u8 bus, u8 devfn);
+void reassign_device_ownership(struct domain *source,
+                               struct domain *target,
+                               u8 bus, u8 devfn);
+int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn);
+int iommu_unmap_page(struct domain *d, unsigned long gfn);
+void iommu_flush(struct domain *d, unsigned long gfn, u64 *p2m_entry);
+void iommu_set_pgd(struct domain *d);
+void iommu_domain_teardown(struct domain *d);
+int hvm_do_IRQ_dpci(struct domain *d, unsigned int irq);
+int dpci_ioport_intercept(ioreq_t *p);
+int pt_irq_create_bind_vtd(struct domain *d,
+                           xen_domctl_bind_pt_irq_t *pt_irq_bind);
+int pt_irq_destroy_bind_vtd(struct domain *d,
+                            xen_domctl_bind_pt_irq_t *pt_irq_bind);
+unsigned int io_apic_read_remap_rte(unsigned int apic, unsigned int reg);
+void io_apic_write_remap_rte(unsigned int apic,
+                             unsigned int reg, unsigned int value);
+struct qi_ctrl *iommu_qi_ctrl(struct iommu *iommu);
+struct ir_ctrl *iommu_ir_ctrl(struct iommu *iommu);
+struct iommu_flush *iommu_get_flush(struct iommu *iommu);
+
+#define PT_IRQ_TIME_OUT MILLISECS(8)
+#define VTDPREFIX "[VT-D]"
+
+struct iommu_ops {
+    int (*init)(struct domain *d);
+    int (*assign_device)(struct domain *d, u8 bus, u8 devfn);
+    void (*teardown)(struct domain *d);
+    int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn);
+    int (*unmap_page)(struct domain *d, unsigned long gfn);
+    void (*reassign_device)(struct domain *s, struct domain *t,
+                            u8 bus, u8 devfn);
+};
+
+#endif /* _IOMMU_H_ */

_______________________________________________
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®.