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] Move iommu code to arch-generic locations

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Move iommu code to arch-generic locations, and also clean up some VT-d code.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 20 Mar 2008 05:40:09 -0700
Delivery-date: Thu, 20 Mar 2008 05:40:47 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
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/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/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 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Move iommu code to arch-generic locations, and also clean up some VT-d code., Xen patchbot-unstable <=