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] x86 iommu: Define vendor-neutral interfac

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86 iommu: Define vendor-neutral interface for access to IOMMU.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 18 Feb 2008 06:00:15 -0800
Delivery-date: Mon, 18 Feb 2008 06:01:07 -0800
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 1202987657 0
# Node ID 72f52dd2dba8e0a7ac616c75520e5b168ec1eb9e
# Parent  c9d9bbf1204c66fe4a067b4a61b551d5999a9315
x86 iommu: Define vendor-neutral interface for access to IOMMU.
Signed-off-by: Wei Wang <wei.wang2@xxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/domctl.c                             |    8 
 xen/arch/x86/hvm/Makefile                         |    1 
 xen/arch/x86/hvm/iommu.c                          |  135 ++++++++
 xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c |    2 
 xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c    |  371 +++++++++++-----------
 xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c    |  346 +++++++++++++++-----
 xen/arch/x86/hvm/svm/intr.c                       |   41 ++
 xen/arch/x86/hvm/vioapic.c                        |    2 
 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c            |   38 +-
 xen/arch/x86/hvm/vmx/vtd/io.c                     |   53 ---
 xen/arch/x86/mm/p2m.c                             |   17 -
 xen/include/asm-x86/hvm/iommu.h                   |    3 
 xen/include/asm-x86/hvm/svm/amd-iommu-defs.h      |    5 
 xen/include/asm-x86/hvm/svm/amd-iommu-proto.h     |   18 -
 xen/include/asm-x86/hvm/vmx/intel-iommu.h         |    8 
 xen/include/asm-x86/iommu.h                       |   16 
 16 files changed, 725 insertions(+), 339 deletions(-)

diff -r c9d9bbf1204c -r 72f52dd2dba8 xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Thu Feb 14 10:36:47 2008 +0000
+++ b/xen/arch/x86/domctl.c     Thu Feb 14 11:14:17 2008 +0000
@@ -530,7 +530,7 @@ long arch_do_domctl(
         u8 bus, devfn;
 
         ret = -EINVAL;
-        if ( !vtd_enabled )
+        if ( !iommu_enabled )
             break;
 
         bus = (domctl->u.assign_device.machine_bdf >> 16) & 0xff;
@@ -553,7 +553,7 @@ long arch_do_domctl(
         u8 bus, devfn;
 
         ret = -EINVAL;
-        if ( !vtd_enabled )
+        if ( !iommu_enabled )
             break;
 
         if ( unlikely((d = get_domain_by_id(domctl->domain)) == NULL) )
@@ -589,9 +589,9 @@ long arch_do_domctl(
         if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
             break;
         bind = &(domctl->u.bind_pt_irq);
-        if (vtd_enabled)
+        if ( iommu_enabled )
             ret = pt_irq_create_bind_vtd(d, bind);
-        if (ret < 0)
+        if ( ret < 0 )
             gdprintk(XENLOG_ERR, "pt_irq_create_bind failed!\n");
         rcu_unlock_domain(d);
     }
diff -r c9d9bbf1204c -r 72f52dd2dba8 xen/arch/x86/hvm/Makefile
--- a/xen/arch/x86/hvm/Makefile Thu Feb 14 10:36:47 2008 +0000
+++ b/xen/arch/x86/hvm/Makefile Thu Feb 14 11:14:17 2008 +0000
@@ -6,6 +6,7 @@ obj-y += instrlen.o
 obj-y += instrlen.o
 obj-y += intercept.o
 obj-y += io.o
+obj-y += iommu.o
 obj-y += irq.o
 obj-y += mtrr.o
 obj-y += platform.o
diff -r c9d9bbf1204c -r 72f52dd2dba8 xen/arch/x86/hvm/iommu.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/hvm/iommu.c  Thu Feb 14 11:14:17 2008 +0000
@@ -0,0 +1,135 @@
+/*
+ * 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);
+}
diff -r c9d9bbf1204c -r 72f52dd2dba8 
xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c
--- a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c Thu Feb 14 10:36:47 
2008 +0000
+++ b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c Thu Feb 14 11:14:17 
2008 +0000
@@ -89,12 +89,14 @@ int __init get_iommu_capabilities(u8 bus
     u32 cap_header, cap_range;
     u64 mmio_bar;
 
+#if HACK_BIOS_SETTINGS
     /* remove it when BIOS available */
     write_pci_config(bus, dev, func,
         cap_ptr + PCI_CAP_MMIO_BAR_HIGH_OFFSET, 0x00000000);
     write_pci_config(bus, dev, func,
         cap_ptr + PCI_CAP_MMIO_BAR_LOW_OFFSET, 0x40000001);
     /* remove it when BIOS available */
+#endif
 
     mmio_bar = (u64)read_pci_config(bus, dev, func,
              cap_ptr + PCI_CAP_MMIO_BAR_HIGH_OFFSET) << 32;
diff -r c9d9bbf1204c -r 72f52dd2dba8 
xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c
--- a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c    Thu Feb 14 10:36:47 
2008 +0000
+++ b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c    Thu Feb 14 11:14:17 
2008 +0000
@@ -30,22 +30,20 @@ static int queue_iommu_command(struct am
     u32 tail, head, *cmd_buffer;
     int i;
 
-    BUG_ON( !iommu || !cmd );
-
     tail = iommu->cmd_buffer_tail;
-    if ( ++tail == iommu->cmd_buffer.entries ) {
+    if ( ++tail == iommu->cmd_buffer.entries )
         tail = 0;
-    }
     head = get_field_from_reg_u32(
-            readl(iommu->mmio_base+IOMMU_CMD_BUFFER_HEAD_OFFSET),
-            IOMMU_CMD_BUFFER_HEAD_MASK,
-            IOMMU_CMD_BUFFER_HEAD_SHIFT);
-    if ( head != tail ) {
+        readl(iommu->mmio_base+IOMMU_CMD_BUFFER_HEAD_OFFSET),
+        IOMMU_CMD_BUFFER_HEAD_MASK,
+        IOMMU_CMD_BUFFER_HEAD_SHIFT);
+    if ( head != tail )
+    {
         cmd_buffer = (u32 *)(iommu->cmd_buffer.buffer +
-            (iommu->cmd_buffer_tail * IOMMU_CMD_BUFFER_ENTRY_SIZE));
-        for ( i = 0; i < IOMMU_CMD_BUFFER_U32_PER_ENTRY; ++i ) {
+                             (iommu->cmd_buffer_tail *
+                              IOMMU_CMD_BUFFER_ENTRY_SIZE));
+        for ( i = 0; i < IOMMU_CMD_BUFFER_U32_PER_ENTRY; i++ )
             cmd_buffer[i] = cmd[i];
-        }
 
         iommu->cmd_buffer_tail = tail;
         return 1;
@@ -58,27 +56,25 @@ static void commit_iommu_command_buffer(
 {
     u32 tail;
 
-    BUG_ON( !iommu );
-
     set_field_in_reg_u32(iommu->cmd_buffer_tail, 0,
-        IOMMU_CMD_BUFFER_TAIL_MASK,
-        IOMMU_CMD_BUFFER_TAIL_SHIFT, &tail);
+                         IOMMU_CMD_BUFFER_TAIL_MASK,
+                         IOMMU_CMD_BUFFER_TAIL_SHIFT, &tail);
     writel(tail, iommu->mmio_base+IOMMU_CMD_BUFFER_TAIL_OFFSET);
 }
 
 int send_iommu_command(struct amd_iommu *iommu, u32 cmd[])
 {
-    BUG_ON( !iommu || !cmd );
-
-    if ( queue_iommu_command(iommu, cmd) ) {
+    if ( queue_iommu_command(iommu, cmd) )
+    {
         commit_iommu_command_buffer(iommu);
         return 1;
     }
+
     return 0;
 }
 
 static void invalidate_iommu_page(struct amd_iommu *iommu,
-            u64 io_addr, u16 domain_id)
+                                  u64 io_addr, u16 domain_id)
 {
     u64 addr_lo, addr_hi;
     u32 cmd[4], entry;
@@ -87,51 +83,52 @@ static void invalidate_iommu_page(struct
     addr_hi = io_addr >> 32;
 
     set_field_in_reg_u32(domain_id, 0,
-        IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_MASK,
-        IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_SHIFT, &entry);
+                         IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_MASK,
+                         IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_SHIFT, &entry);
     set_field_in_reg_u32(IOMMU_CMD_INVALIDATE_IOMMU_PAGES, entry,
-        IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT, &entry);
+                         IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT,
+                         &entry);
     cmd[1] = entry;
 
     set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, 0,
-        IOMMU_INV_IOMMU_PAGES_S_FLAG_MASK,
-        IOMMU_INV_IOMMU_PAGES_S_FLAG_SHIFT, &entry);
+                         IOMMU_INV_IOMMU_PAGES_S_FLAG_MASK,
+                         IOMMU_INV_IOMMU_PAGES_S_FLAG_SHIFT, &entry);
     set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, entry,
-        IOMMU_INV_IOMMU_PAGES_PDE_FLAG_MASK,
-        IOMMU_INV_IOMMU_PAGES_PDE_FLAG_SHIFT, &entry);
+                         IOMMU_INV_IOMMU_PAGES_PDE_FLAG_MASK,
+                         IOMMU_INV_IOMMU_PAGES_PDE_FLAG_SHIFT, &entry);
     set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, entry,
-        IOMMU_INV_IOMMU_PAGES_ADDR_LOW_MASK,
-        IOMMU_INV_IOMMU_PAGES_ADDR_LOW_SHIFT, &entry);
+                         IOMMU_INV_IOMMU_PAGES_ADDR_LOW_MASK,
+                         IOMMU_INV_IOMMU_PAGES_ADDR_LOW_SHIFT, &entry);
     cmd[2] = entry;
 
     set_field_in_reg_u32((u32)addr_hi, 0,
-        IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK,
-        IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT, &entry);
+                         IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK,
+                         IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT, &entry);
     cmd[3] = entry;
 
     cmd[0] = 0;
     send_iommu_command(iommu, cmd);
 }
 
-static void flush_command_buffer(struct amd_iommu *iommu)
+void flush_command_buffer(struct amd_iommu *iommu)
 {
     u32 cmd[4], status;
     int loop_count, comp_wait;
 
     /* clear 'ComWaitInt' in status register (WIC) */
     set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, 0,
-        IOMMU_STATUS_COMP_WAIT_INT_MASK,
-        IOMMU_STATUS_COMP_WAIT_INT_SHIFT, &status);
+                         IOMMU_STATUS_COMP_WAIT_INT_MASK,
+                         IOMMU_STATUS_COMP_WAIT_INT_SHIFT, &status);
     writel(status, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
 
     /* send an empty COMPLETION_WAIT command to flush command buffer */
     cmd[3] = cmd[2] = 0;
     set_field_in_reg_u32(IOMMU_CMD_COMPLETION_WAIT, 0,
-        IOMMU_CMD_OPCODE_MASK,
-        IOMMU_CMD_OPCODE_SHIFT, &cmd[1]);
+                         IOMMU_CMD_OPCODE_MASK,
+                         IOMMU_CMD_OPCODE_SHIFT, &cmd[1]);
     set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, 0,
-        IOMMU_COMP_WAIT_I_FLAG_MASK,
-        IOMMU_COMP_WAIT_I_FLAG_SHIFT, &cmd[0]);
+                         IOMMU_COMP_WAIT_I_FLAG_MASK,
+                         IOMMU_COMP_WAIT_I_FLAG_SHIFT, &cmd[0]);
     send_iommu_command(iommu, cmd);
 
     /* wait for 'ComWaitInt' to signal comp#endifletion? */
@@ -139,34 +136,36 @@ static void flush_command_buffer(struct 
         loop_count = amd_iommu_poll_comp_wait;
         do {
             status = readl(iommu->mmio_base +
-                    IOMMU_STATUS_MMIO_OFFSET);
-            comp_wait = get_field_from_reg_u32(status,
-                    IOMMU_STATUS_COMP_WAIT_INT_MASK,
-                    IOMMU_STATUS_COMP_WAIT_INT_SHIFT);
+                           IOMMU_STATUS_MMIO_OFFSET);
+            comp_wait = get_field_from_reg_u32(
+                status,
+                IOMMU_STATUS_COMP_WAIT_INT_MASK,
+                IOMMU_STATUS_COMP_WAIT_INT_SHIFT);
             --loop_count;
         } while ( loop_count && !comp_wait );
 
-        if ( comp_wait ) {
+        if ( comp_wait )
+        {
             /* clear 'ComWaitInt' in status register (WIC) */
             status &= IOMMU_STATUS_COMP_WAIT_INT_MASK;
             writel(status, iommu->mmio_base +
-                IOMMU_STATUS_MMIO_OFFSET);
-        } else
-            dprintk(XENLOG_WARNING, "AMD IOMMU: %s(): Warning:"
-                " ComWaitInt bit did not assert!\n",
-                 __FUNCTION__);
+                   IOMMU_STATUS_MMIO_OFFSET);
+        }
+        else
+            dprintk(XENLOG_WARNING, "AMD IOMMU: Warning:"
+                    " ComWaitInt bit did not assert!\n");
     }
 }
 
 static void clear_page_table_entry_present(u32 *pte)
 {
     set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, pte[0],
-        IOMMU_PTE_PRESENT_MASK,
-        IOMMU_PTE_PRESENT_SHIFT, &pte[0]);
+                         IOMMU_PTE_PRESENT_MASK,
+                         IOMMU_PTE_PRESENT_SHIFT, &pte[0]);
 }
 
 static void set_page_table_entry_present(u32 *pte, u64 page_addr,
-                int iw, int ir)
+                                         int iw, int ir)
 {
     u64 addr_lo, addr_hi;
     u32 entry;
@@ -175,33 +174,33 @@ static void set_page_table_entry_present
     addr_hi = page_addr >> 32;
 
     set_field_in_reg_u32((u32)addr_hi, 0,
-        IOMMU_PTE_ADDR_HIGH_MASK,
-        IOMMU_PTE_ADDR_HIGH_SHIFT, &entry);
+                         IOMMU_PTE_ADDR_HIGH_MASK,
+                         IOMMU_PTE_ADDR_HIGH_SHIFT, &entry);
     set_field_in_reg_u32(iw ? IOMMU_CONTROL_ENABLED :
-        IOMMU_CONTROL_DISABLED, entry,
-        IOMMU_PTE_IO_WRITE_PERMISSION_MASK,
-        IOMMU_PTE_IO_WRITE_PERMISSION_SHIFT, &entry);
+                         IOMMU_CONTROL_DISABLED, entry,
+                         IOMMU_PTE_IO_WRITE_PERMISSION_MASK,
+                         IOMMU_PTE_IO_WRITE_PERMISSION_SHIFT, &entry);
     set_field_in_reg_u32(ir ? IOMMU_CONTROL_ENABLED :
-        IOMMU_CONTROL_DISABLED, entry,
-        IOMMU_PTE_IO_READ_PERMISSION_MASK,
-        IOMMU_PTE_IO_READ_PERMISSION_SHIFT, &entry);
+                         IOMMU_CONTROL_DISABLED, entry,
+                         IOMMU_PTE_IO_READ_PERMISSION_MASK,
+                         IOMMU_PTE_IO_READ_PERMISSION_SHIFT, &entry);
     pte[1] = entry;
 
     set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0,
-        IOMMU_PTE_ADDR_LOW_MASK,
-        IOMMU_PTE_ADDR_LOW_SHIFT, &entry);
+                         IOMMU_PTE_ADDR_LOW_MASK,
+                         IOMMU_PTE_ADDR_LOW_SHIFT, &entry);
     set_field_in_reg_u32(IOMMU_PAGING_MODE_LEVEL_0, entry,
-        IOMMU_PTE_NEXT_LEVEL_MASK,
-        IOMMU_PTE_NEXT_LEVEL_SHIFT, &entry);
-    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
-        IOMMU_PTE_PRESENT_MASK,
-        IOMMU_PTE_PRESENT_SHIFT, &entry);
+                         IOMMU_PTE_NEXT_LEVEL_MASK,
+                         IOMMU_PTE_NEXT_LEVEL_SHIFT, &entry);
+    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
+                         IOMMU_PTE_PRESENT_MASK,
+                         IOMMU_PTE_PRESENT_SHIFT, &entry);
     pte[0] = entry;
 }
 
 
 static void amd_iommu_set_page_directory_entry(u32 *pde, 
-            u64 next_ptr, u8 next_level)
+                                               u64 next_ptr, u8 next_level)
 {
     u64 addr_lo, addr_hi;
     u32 entry;
@@ -211,29 +210,31 @@ static void amd_iommu_set_page_directory
 
     /* enable read/write permissions,which will be enforced at the PTE */
     set_field_in_reg_u32((u32)addr_hi, 0,
-        IOMMU_PDE_ADDR_HIGH_MASK, IOMMU_PDE_ADDR_HIGH_SHIFT, &entry);
-    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
-        IOMMU_PDE_IO_WRITE_PERMISSION_MASK,
-        IOMMU_PDE_IO_WRITE_PERMISSION_SHIFT, &entry);
-    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
-        IOMMU_PDE_IO_READ_PERMISSION_MASK,
-        IOMMU_PDE_IO_READ_PERMISSION_SHIFT, &entry);
+                         IOMMU_PDE_ADDR_HIGH_MASK,
+                         IOMMU_PDE_ADDR_HIGH_SHIFT, &entry);
+    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
+                         IOMMU_PDE_IO_WRITE_PERMISSION_MASK,
+                         IOMMU_PDE_IO_WRITE_PERMISSION_SHIFT, &entry);
+    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
+                         IOMMU_PDE_IO_READ_PERMISSION_MASK,
+                         IOMMU_PDE_IO_READ_PERMISSION_SHIFT, &entry);
     pde[1] = entry;
 
     /* mark next level as 'present' */
     set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0,
-        IOMMU_PDE_ADDR_LOW_MASK, IOMMU_PDE_ADDR_LOW_SHIFT, &entry);
+                         IOMMU_PDE_ADDR_LOW_MASK,
+                         IOMMU_PDE_ADDR_LOW_SHIFT, &entry);
     set_field_in_reg_u32(next_level, entry,
-        IOMMU_PDE_NEXT_LEVEL_MASK,
-        IOMMU_PDE_NEXT_LEVEL_SHIFT, &entry);
-    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
-        IOMMU_PDE_PRESENT_MASK,
-        IOMMU_PDE_PRESENT_SHIFT, &entry);
+                         IOMMU_PDE_NEXT_LEVEL_MASK,
+                         IOMMU_PDE_NEXT_LEVEL_SHIFT, &entry);
+    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
+                         IOMMU_PDE_PRESENT_MASK,
+                         IOMMU_PDE_PRESENT_SHIFT, &entry);
     pde[0] = entry;
 }
 
 void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u16 domain_id,
-                u8 paging_mode)
+                                   u8 paging_mode)
 {
     u64 addr_hi, addr_lo;
     u32 entry;
@@ -241,54 +242,56 @@ void amd_iommu_set_dev_table_entry(u32 *
     dte[6] = dte[5] = dte[4] = 0;
 
     set_field_in_reg_u32(IOMMU_DEV_TABLE_SYS_MGT_MSG_FORWARDED, 0,
-        IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_MASK,
-        IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_SHIFT, &entry);
+                         IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_MASK,
+                         IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_SHIFT, &entry);
     dte[3] = entry;
 
     set_field_in_reg_u32(domain_id, 0,
-        IOMMU_DEV_TABLE_DOMAIN_ID_MASK,
-        IOMMU_DEV_TABLE_DOMAIN_ID_SHIFT, &entry);
+                         IOMMU_DEV_TABLE_DOMAIN_ID_MASK,
+                         IOMMU_DEV_TABLE_DOMAIN_ID_SHIFT, &entry);
     dte[2] = entry;
 
     addr_lo = root_ptr & DMA_32BIT_MASK;
     addr_hi = root_ptr >> 32;
     set_field_in_reg_u32((u32)addr_hi, 0,
+                         IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_MASK,
+                         IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT, &entry);
+    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
+                         IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_MASK,
+                         IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_SHIFT, &entry);
+    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
+                         IOMMU_DEV_TABLE_IO_READ_PERMISSION_MASK,
+                         IOMMU_DEV_TABLE_IO_READ_PERMISSION_SHIFT, &entry);
+    dte[1] = entry;
+
+    set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0,
+                         IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK,
+                         IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT, &entry);
+    set_field_in_reg_u32(paging_mode, entry,
+                         IOMMU_DEV_TABLE_PAGING_MODE_MASK,
+                         IOMMU_DEV_TABLE_PAGING_MODE_SHIFT, &entry);
+    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
+                         IOMMU_DEV_TABLE_TRANSLATION_VALID_MASK,
+                         IOMMU_DEV_TABLE_TRANSLATION_VALID_SHIFT, &entry);
+    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
+                         IOMMU_DEV_TABLE_VALID_MASK,
+                         IOMMU_DEV_TABLE_VALID_SHIFT, &entry);
+    dte[0] = entry;
+}
+
+void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry)
+{
+    u64 addr_lo, addr_hi, ptr;
+
+    addr_lo = get_field_from_reg_u32(
+        entry[0],
+        IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK,
+        IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT);
+
+    addr_hi = get_field_from_reg_u32(
+        entry[1],
         IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_MASK,
-        IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT, &entry);
-    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
-        IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_MASK,
-        IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_SHIFT, &entry);
-    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
-        IOMMU_DEV_TABLE_IO_READ_PERMISSION_MASK,
-        IOMMU_DEV_TABLE_IO_READ_PERMISSION_SHIFT, &entry);
-    dte[1] = entry;
-
-    set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0,
-        IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK,
-        IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT, &entry);
-    set_field_in_reg_u32(paging_mode, entry,
-        IOMMU_DEV_TABLE_PAGING_MODE_MASK,
-        IOMMU_DEV_TABLE_PAGING_MODE_SHIFT, &entry);
-    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
-        IOMMU_DEV_TABLE_TRANSLATION_VALID_MASK,
-        IOMMU_DEV_TABLE_TRANSLATION_VALID_SHIFT, &entry);
-    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
-        IOMMU_DEV_TABLE_VALID_MASK,
-        IOMMU_DEV_TABLE_VALID_SHIFT, &entry);
-    dte[0] = entry;
-}
-
-static void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry)
-{
-    u64 addr_lo, addr_hi, ptr;
-
-    addr_lo = get_field_from_reg_u32(entry[0],
-            IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK,
-            IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT);
-
-    addr_hi = get_field_from_reg_u32(entry[1],
-            IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_MASK,
-            IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT);
+        IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT);
 
     ptr = (addr_hi << 32) | (addr_lo << PAGE_SHIFT);
     return ptr ? maddr_to_virt((unsigned long)ptr) : NULL;
@@ -297,42 +300,74 @@ static int amd_iommu_is_pte_present(u32 
 static int amd_iommu_is_pte_present(u32 *entry)
 {
     return (get_field_from_reg_u32(entry[0],
-            IOMMU_PDE_PRESENT_MASK,
-            IOMMU_PDE_PRESENT_SHIFT));
+                                   IOMMU_PDE_PRESENT_MASK,
+                                   IOMMU_PDE_PRESENT_SHIFT));
+}
+
+void invalidate_dev_table_entry(struct amd_iommu *iommu,
+                                u16 device_id)
+{
+    u32 cmd[4], entry;
+
+    cmd[3] = cmd[2] = 0;
+    set_field_in_reg_u32(device_id, 0,
+                         IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_MASK,
+                         IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_SHIFT, &entry);
+    cmd[0] = entry;
+
+    set_field_in_reg_u32(IOMMU_CMD_INVALIDATE_DEVTAB_ENTRY, 0,
+                         IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT,
+                         &entry);
+    cmd[1] = entry;
+
+    send_iommu_command(iommu, cmd);
+}
+
+int amd_iommu_is_dte_page_translation_valid(u32 *entry)
+{
+    return (get_field_from_reg_u32(entry[0],
+                                   IOMMU_DEV_TABLE_VALID_MASK,
+                                   IOMMU_DEV_TABLE_VALID_SHIFT) &&
+            get_field_from_reg_u32(entry[0],
+                                   IOMMU_DEV_TABLE_TRANSLATION_VALID_MASK,
+                                   IOMMU_DEV_TABLE_TRANSLATION_VALID_SHIFT));
 }
 
 static void *get_pte_from_page_tables(void *table, int level,
-        unsigned long io_pfn)
+                                      unsigned long io_pfn)
 {
     unsigned long offset;
-    void *pde = 0;
-
-    BUG_ON( !table );
+    void *pde = NULL;
+
+    BUG_ON(table == NULL);
 
     while ( level > 0 )
     {
-        void *next_table = 0;
-        unsigned long next_ptr;
         offset = io_pfn >> ((PTE_PER_TABLE_SHIFT *
-            (level - IOMMU_PAGING_MODE_LEVEL_1)));
+                             (level - IOMMU_PAGING_MODE_LEVEL_1)));
         offset &= ~PTE_PER_TABLE_MASK;
         pde = table + (offset * IOMMU_PAGE_TABLE_ENTRY_SIZE);
 
         if ( level == 1 )
             break;
         if ( !pde )
-           return NULL;
-        if ( !amd_iommu_is_pte_present(pde) ) {
-            next_table = alloc_xenheap_page();
+            return NULL;
+        if ( !amd_iommu_is_pte_present(pde) )
+        {
+            void *next_table = alloc_xenheap_page();
             if ( next_table == NULL )
                 return NULL;
             memset(next_table, 0, PAGE_SIZE);
-            if ( *(u64*)(pde) == 0 ) {
-                next_ptr = (u64)virt_to_maddr(next_table);
-                amd_iommu_set_page_directory_entry((u32 *)pde,
-                    next_ptr, level - 1);
-            } else
+            if ( *(u64 *)pde == 0 )
+            {
+                unsigned long next_ptr = (u64)virt_to_maddr(next_table);
+                amd_iommu_set_page_directory_entry(
+                    (u32 *)pde, next_ptr, level - 1);
+            }
+            else
+            {
                 free_xenheap_page(next_table);
+            }
         }
         table = amd_iommu_get_vptr_from_page_table_entry(pde);
         level--;
@@ -341,8 +376,7 @@ static void *get_pte_from_page_tables(vo
     return pde;
 }
 
-int amd_iommu_map_page(struct domain *d, unsigned long gfn,
-        unsigned long mfn)
+int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn)
 {
     void *pte;
     unsigned long flags;
@@ -352,7 +386,7 @@ int amd_iommu_map_page(struct domain *d,
 
     BUG_ON( !hd->root_table );
 
-    maddr = (u64)(mfn << PAGE_SHIFT);
+    maddr = (u64)mfn << PAGE_SHIFT;
 
     iw = IOMMU_IO_WRITE_ENABLED;
     ir = IOMMU_IO_READ_ENABLED;
@@ -360,18 +394,18 @@ int amd_iommu_map_page(struct domain *d,
     spin_lock_irqsave(&hd->mapping_lock, flags);
 
     pte = get_pte_from_page_tables(hd->root_table, hd->paging_mode, gfn);
-
-    if ( pte != 0 ) {
-        set_page_table_entry_present((u32 *)pte, maddr, iw, ir);
-        spin_unlock_irqrestore(&hd->mapping_lock, flags);
-        return 0;
-    } else {
+    if ( pte == 0 )
+    {
         dprintk(XENLOG_ERR,
-            "%s() AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n",
-            __FUNCTION__, gfn);
+                "AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n", gfn);
         spin_unlock_irqrestore(&hd->mapping_lock, flags);
         return -EIO;
     }
+
+    set_page_table_entry_present((u32 *)pte, maddr, iw, ir);
+
+    spin_unlock_irqrestore(&hd->mapping_lock, flags);
+    return 0;
 }
 
 int amd_iommu_unmap_page(struct domain *d, unsigned long gfn)
@@ -386,34 +420,31 @@ int amd_iommu_unmap_page(struct domain *
     BUG_ON( !hd->root_table );
 
     requestor_id = hd->domain_id;
-    io_addr = (u64)(gfn << PAGE_SHIFT);
+    io_addr = (u64)gfn << PAGE_SHIFT;
 
     spin_lock_irqsave(&hd->mapping_lock, flags);
 
     pte = get_pte_from_page_tables(hd->root_table, hd->paging_mode, gfn);
-
-    if ( pte != 0 ) {
-        /* mark PTE as 'page not present' */
-        clear_page_table_entry_present((u32 *)pte);
-        spin_unlock_irqrestore(&hd->mapping_lock, flags);
-
-        /* send INVALIDATE_IOMMU_PAGES command */
-        for_each_amd_iommu(iommu) {
-
-            spin_lock_irqsave(&iommu->lock, flags);
-
-            invalidate_iommu_page(iommu, io_addr, requestor_id);
-            flush_command_buffer(iommu);
-
-            spin_unlock_irqrestore(&iommu->lock, flags);
-        }
-
-        return 0;
-    } else {
+    if ( pte == 0 )
+    {
         dprintk(XENLOG_ERR,
-            "%s() AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n", 
-            __FUNCTION__, gfn);
+                "AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n", gfn);
         spin_unlock_irqrestore(&hd->mapping_lock, flags);
         return -EIO;
     }
-}
+
+    /* mark PTE as 'page not present' */
+    clear_page_table_entry_present((u32 *)pte);
+    spin_unlock_irqrestore(&hd->mapping_lock, flags);
+
+    /* send INVALIDATE_IOMMU_PAGES command */
+    for_each_amd_iommu(iommu)
+    {
+        spin_lock_irqsave(&iommu->lock, flags);
+        invalidate_iommu_page(iommu, io_addr, requestor_id);
+        flush_command_buffer(iommu);
+        spin_unlock_irqrestore(&iommu->lock, flags);
+    }
+
+    return 0;
+}
diff -r c9d9bbf1204c -r 72f52dd2dba8 
xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c
--- a/xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c    Thu Feb 14 10:36:47 
2008 +0000
+++ b/xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c    Thu Feb 14 11:14:17 
2008 +0000
@@ -51,19 +51,17 @@ static void __init init_cleanup(void)
 {
     struct amd_iommu *iommu;
 
-    dprintk(XENLOG_ERR, "AMD IOMMU: %s()\n", __FUNCTION__);
-
-    for_each_amd_iommu(iommu) {
+    for_each_amd_iommu ( iommu )
         unmap_iommu_mmio_region(iommu);
-    }
 }
 
 static void __init deallocate_iommu_table_struct(
-            struct table_struct *table)
-{
-    if (table->buffer) {
+    struct table_struct *table)
+{
+    if ( table->buffer )
+    {
         free_xenheap_pages(table->buffer,
-            get_order_from_bytes(table->alloc_size));
+                           get_order_from_bytes(table->alloc_size));
         table->buffer = NULL;
     }
 }
@@ -76,11 +74,10 @@ static void __init deallocate_iommu_reso
 
 static void __init detect_cleanup(void)
 {
-    struct amd_iommu *iommu;
-
-    dprintk(XENLOG_ERR, "AMD IOMMU: %s()\n", __FUNCTION__);
-
-    for_each_amd_iommu(iommu) {
+    struct amd_iommu *iommu, *next;
+
+    list_for_each_entry_safe ( iommu, next, &amd_iommu_head, list )
+    {
         list_del(&iommu->list);
         deallocate_iommu_resources(iommu);
         xfree(iommu);
@@ -91,19 +88,21 @@ static int requestor_id_from_bdf(int bdf
 {
     /* HACK - HACK */
     /* account for possible 'aliasing' by parent device */
-   return bdf;
+    return bdf;
 }
 
 static int __init allocate_iommu_table_struct(struct table_struct *table,
-            const char *name)
+                                              const char *name)
 {
     table->buffer = (void *) alloc_xenheap_pages(
         get_order_from_bytes(table->alloc_size));
 
-    if ( !table->buffer ) {
+    if ( !table->buffer )
+    {
         dprintk(XENLOG_ERR, "AMD IOMMU: Error allocating %s\n", name);
         return -ENOMEM;
     }
+
     memset(table->buffer, 0, table->alloc_size);
 
     return 0;
@@ -114,32 +113,32 @@ static int __init allocate_iommu_resourc
     /* allocate 'device table' on a 4K boundary */
     iommu->dev_table.alloc_size =
         PAGE_ALIGN(((iommu->last_downstream_bus + 1) *
-        IOMMU_DEV_TABLE_ENTRIES_PER_BUS) *
-        IOMMU_DEV_TABLE_ENTRY_SIZE);
+                    IOMMU_DEV_TABLE_ENTRIES_PER_BUS) *
+                   IOMMU_DEV_TABLE_ENTRY_SIZE);
     iommu->dev_table.entries =
         iommu->dev_table.alloc_size / IOMMU_DEV_TABLE_ENTRY_SIZE;
 
-    if (allocate_iommu_table_struct(&iommu->dev_table,
-            "Device Table") != 0)
+    if ( allocate_iommu_table_struct(&iommu->dev_table,
+                                     "Device Table") != 0 )
         goto error_out;
 
     /* allocate 'command buffer' in power of 2 increments of 4K */
     iommu->cmd_buffer_tail = 0;
     iommu->cmd_buffer.alloc_size =
         PAGE_SIZE << get_order_from_bytes(
-        PAGE_ALIGN(amd_iommu_cmd_buffer_entries *
-        IOMMU_CMD_BUFFER_ENTRY_SIZE));
-
-   iommu->cmd_buffer.entries =
+            PAGE_ALIGN(amd_iommu_cmd_buffer_entries *
+                       IOMMU_CMD_BUFFER_ENTRY_SIZE));
+
+    iommu->cmd_buffer.entries =
         iommu->cmd_buffer.alloc_size / IOMMU_CMD_BUFFER_ENTRY_SIZE;
 
     if ( allocate_iommu_table_struct(&iommu->cmd_buffer,
-            "Command Buffer") != 0 )
-        goto error_out;
-
-    return 0;
-
-error_out:
+                                     "Command Buffer") != 0 )
+        goto error_out;
+
+    return 0;
+
+ error_out:
     deallocate_iommu_resources(iommu);
     return -ENOMEM;
 }
@@ -149,7 +148,8 @@ int iommu_detect_callback(u8 bus, u8 dev
     struct amd_iommu *iommu;
 
     iommu = (struct amd_iommu *) xmalloc(struct amd_iommu);
-    if ( !iommu ) {
+    if ( !iommu )
+    {
         dprintk(XENLOG_ERR, "AMD IOMMU: Error allocating amd_iommu\n");
         return -ENOMEM;
     }
@@ -170,7 +170,7 @@ int iommu_detect_callback(u8 bus, u8 dev
 
     return 0;
 
-error_out:
+ error_out:
     xfree(iommu);
     return -ENODEV;
 }
@@ -180,11 +180,12 @@ static int __init amd_iommu_init(void)
     struct amd_iommu *iommu;
     unsigned long flags;
 
-    for_each_amd_iommu(iommu) {
+    for_each_amd_iommu ( iommu )
+    {
         spin_lock_irqsave(&iommu->lock, flags);
 
         /* register IOMMU data strucures in MMIO space */
-        if (map_iommu_mmio_region(iommu) != 0)
+        if ( map_iommu_mmio_region(iommu) != 0 )
             goto error_out;
         register_iommu_dev_table_in_mmio_space(iommu);
         register_iommu_cmd_buffer_in_mmio_space(iommu);
@@ -200,7 +201,7 @@ static int __init amd_iommu_init(void)
 
     return 0;
 
-error_out:
+ error_out:
     init_cleanup();
     return -ENODEV;
 }
@@ -209,13 +210,16 @@ struct amd_iommu *find_iommu_for_device(
 {
     struct amd_iommu *iommu;
 
-    for_each_amd_iommu(iommu) {
-        if ( bus == iommu->root_bus ) {
-            if ( devfn >= iommu->first_devfn &&
-                devfn <= iommu->last_devfn )
+    for_each_amd_iommu ( iommu )
+    {
+        if ( bus == iommu->root_bus )
+        {
+            if ( (devfn >= iommu->first_devfn) &&
+                 (devfn <= iommu->last_devfn) )
                 return iommu;
         }
-        else if ( bus <= iommu->last_downstream_bus ) {
+        else if ( bus <= iommu->last_downstream_bus )
+        {
             if ( iommu->downstream_bus_present[bus] )
                 return iommu;
         }
@@ -238,16 +242,21 @@ void amd_iommu_setup_domain_device(
     dte = iommu->dev_table.buffer +
         (requestor_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
 
-    spin_lock_irqsave(&iommu->lock, flags); 
-
-    amd_iommu_set_dev_table_entry((u32 *)dte,
-        root_ptr, hd->domain_id, hd->paging_mode);
-
-    dprintk(XENLOG_INFO, "AMD IOMMU: Set DTE req_id:%x, "
-            "root_ptr:%"PRIx64", domain_id:%d, paging_mode:%d\n",
-            requestor_id, root_ptr, hd->domain_id, hd->paging_mode);
-
-    spin_unlock_irqrestore(&iommu->lock, flags);
+    if ( !amd_iommu_is_dte_page_translation_valid((u32 *)dte) )
+    {
+        spin_lock_irqsave(&iommu->lock, flags); 
+
+        amd_iommu_set_dev_table_entry(
+            (u32 *)dte,
+            root_ptr, hd->domain_id, hd->paging_mode);
+        invalidate_dev_table_entry(iommu, requestor_id);
+        flush_command_buffer(iommu);
+        dprintk(XENLOG_INFO, "AMD IOMMU: Set DTE req_id:%x, "
+                "root_ptr:%"PRIx64", domain_id:%d, paging_mode:%d\n",
+                requestor_id, root_ptr, hd->domain_id, hd->paging_mode);
+
+        spin_unlock_irqrestore(&iommu->lock, flags);
+    }
 }
 
 void __init amd_iommu_setup_dom0_devices(void)
@@ -259,13 +268,16 @@ void __init amd_iommu_setup_dom0_devices
     u32 l;
     int req_id, bdf;
 
-    for ( bus = 0; bus < 256; bus++ ) {
-        for ( dev = 0; dev < 32; dev++ ) {
-            for ( func = 0; func < 8; func++ ) {
+    for ( bus = 0; bus < 256; bus++ )
+    {
+        for ( dev = 0; dev < 32; dev++ )
+        {
+            for ( func = 0; func < 8; func++ )
+            {
                 l = read_pci_config(bus, dev, func, PCI_VENDOR_ID);
                 /* some broken boards return 0 or ~0 if a slot is empty: */
                 if ( l == 0xffffffff || l == 0x00000000 ||
-                    l == 0x0000ffff || l == 0xffff0000 )
+                     l == 0x0000ffff || l == 0xffff0000 )
                     continue;
 
                 pdev = xmalloc(struct pci_dev);
@@ -288,29 +300,33 @@ int amd_iommu_detect(void)
 {
     unsigned long i;
 
-    if ( !enable_amd_iommu ) {
+    if ( !enable_amd_iommu )
+    {
         printk("AMD IOMMU: Disabled\n");
         return 0;
     }
 
     INIT_LIST_HEAD(&amd_iommu_head);
 
-    if ( scan_for_iommu(iommu_detect_callback) != 0 ) {
+    if ( scan_for_iommu(iommu_detect_callback) != 0 )
+    {
         dprintk(XENLOG_ERR, "AMD IOMMU: Error detection\n");
         goto error_out;
     }
 
-    if ( !iommu_found() ) {
+    if ( !iommu_found() )
+    {
         printk("AMD IOMMU: Not found!\n");
         return 0;
     }
 
-    if ( amd_iommu_init() != 0 ) {
+    if ( amd_iommu_init() != 0 )
+    {
         dprintk(XENLOG_ERR, "AMD IOMMU: Error initialization\n");
         goto error_out;
     }
 
-    if ( amd_iommu_domain_init(dom0) != 0 )
+    if ( iommu_domain_init(dom0) != 0 )
         goto error_out;
 
     /* setup 1:1 page table for dom0 */
@@ -320,21 +336,31 @@ int amd_iommu_detect(void)
     amd_iommu_setup_dom0_devices();
     return 0;
 
-error_out:
-     detect_cleanup();
-     return -ENODEV;
+ error_out:
+    detect_cleanup();
+    return -ENODEV;
 
 }
 
 static int allocate_domain_resources(struct hvm_iommu *hd)
 {
     /* allocate root table */
-    hd->root_table = (void *)alloc_xenheap_page();
+    unsigned long flags;
+
+    spin_lock_irqsave(&hd->mapping_lock, flags);
     if ( !hd->root_table )
-        return -ENOMEM;
-    memset((u8*)hd->root_table, 0, PAGE_SIZE);
-
-    return 0;
+    {
+        hd->root_table = (void *)alloc_xenheap_page();
+        if ( !hd->root_table )
+            goto error_out;
+        memset((u8*)hd->root_table, 0, PAGE_SIZE);
+    }
+    spin_unlock_irqrestore(&hd->mapping_lock, flags);
+
+    return 0;
+ error_out:
+    spin_unlock_irqrestore(&hd->mapping_lock, flags);
+    return -ENOMEM;
 }
 
 static int get_paging_mode(unsigned long entries)
@@ -346,7 +372,8 @@ static int get_paging_mode(unsigned long
     if ( entries > max_page )
         entries = max_page;
 
-    while ( entries > PTE_PER_TABLE_SIZE ) {
+    while ( entries > PTE_PER_TABLE_SIZE )
+    {
         entries = PTE_PER_TABLE_ALIGN(entries) >> PTE_PER_TABLE_SHIFT;
         ++level;
         if ( level > 6 )
@@ -362,14 +389,11 @@ int amd_iommu_domain_init(struct 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);
-
     /* allocate page directroy */
-    if ( allocate_domain_resources(hd) != 0 ) {
-        dprintk(XENLOG_ERR, "AMD IOMMU: %s()\n", __FUNCTION__);
-        goto error_out;
+    if ( allocate_domain_resources(hd) != 0 )
+    {
+        deallocate_domain_resources(hd);
+        return -ENOMEM;
     }
 
     if ( is_hvm_domain(domain) )
@@ -380,10 +404,168 @@ int amd_iommu_domain_init(struct domain 
     hd->domain_id = domain->domain_id;
 
     return 0;
-
-error_out:
-    deallocate_domain_resources(hd);
-    return -ENOMEM;
-}
-
-
+}
+
+static void amd_iommu_disable_domain_device(
+    struct domain *domain, struct amd_iommu *iommu, u16 requestor_id)
+{
+    void *dte;
+    unsigned long flags;
+
+    dte = iommu->dev_table.buffer +
+        (requestor_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
+
+    if ( amd_iommu_is_dte_page_translation_valid((u32 *)dte) )
+    {
+        spin_lock_irqsave(&iommu->lock, flags); 
+        memset (dte, 0, IOMMU_DEV_TABLE_ENTRY_SIZE);
+        invalidate_dev_table_entry(iommu, requestor_id);
+        flush_command_buffer(iommu);
+        dprintk(XENLOG_INFO , "AMD IOMMU: disable DTE 0x%x,"
+                " domain_id:%d, paging_mode:%d\n",
+                requestor_id,  domain_hvm_iommu(domain)->domain_id,
+                domain_hvm_iommu(domain)->paging_mode);
+        spin_unlock_irqrestore(&iommu->lock, flags);
+    }
+}
+
+extern void pdev_flr(u8 bus, u8 devfn);
+
+static int reassign_device( struct domain *source, struct domain *target,
+                            u8 bus, u8 devfn)
+{
+    struct hvm_iommu *source_hd = domain_hvm_iommu(source);
+    struct hvm_iommu *target_hd = domain_hvm_iommu(target);
+    struct pci_dev *pdev;
+    struct amd_iommu *iommu;
+    int req_id, bdf;
+    unsigned long flags;
+
+    for_each_pdev( source, pdev )
+    {
+        if ( (pdev->bus != bus) || (pdev->devfn != devfn) )
+            continue;
+
+        pdev->bus = bus;
+        pdev->devfn = devfn;
+
+        bdf = (bus << 8) | devfn;
+        req_id = requestor_id_from_bdf(bdf);
+        iommu = find_iommu_for_device(bus, devfn);
+
+        if ( iommu )
+        {
+            amd_iommu_disable_domain_device(source, iommu, req_id);
+            /* Move pci device from the source domain to target domain. */
+            spin_lock_irqsave(&source_hd->iommu_list_lock, flags);
+            spin_lock_irqsave(&target_hd->iommu_list_lock, flags);
+            list_move(&pdev->list, &target_hd->pdev_list);
+            spin_unlock_irqrestore(&target_hd->iommu_list_lock, flags);
+            spin_unlock_irqrestore(&source_hd->iommu_list_lock, flags);
+
+            amd_iommu_setup_domain_device(target, iommu, req_id);
+            gdprintk(XENLOG_INFO ,
+                     "AMD IOMMU: reassign %x:%x.%x domain %d -> domain %d\n",
+                     bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+                     source->domain_id, target->domain_id);
+        }
+        else
+        {
+            gdprintk(XENLOG_ERR , "AMD IOMMU: fail to find iommu."
+                     " %x:%x.%x cannot be assigned to domain %d\n", 
+                     bus, PCI_SLOT(devfn), PCI_FUNC(devfn), target->domain_id);
+            return -ENODEV;
+        }
+
+        break;
+    }
+    return 0;
+}
+
+int amd_iommu_assign_device(struct domain *d, u8 bus, u8 devfn)
+{
+    pdev_flr(bus, devfn);
+    return reassign_device(dom0, d, bus, devfn);
+}
+
+static void release_domain_devices(struct domain *d)
+{
+    struct hvm_iommu *hd  = domain_hvm_iommu(d);
+    struct pci_dev *pdev;
+
+    while ( !list_empty(&hd->pdev_list) )
+    {
+        pdev = list_entry(hd->pdev_list.next, typeof(*pdev), list);
+        pdev_flr(pdev->bus, pdev->devfn);
+        gdprintk(XENLOG_INFO ,
+                 "AMD IOMMU: release devices %x:%x.%x\n",
+                 pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+        reassign_device(d, dom0, pdev->bus, pdev->devfn);
+    }
+}
+
+static void deallocate_next_page_table(void *table, unsigned long index,
+                                       int level)
+{
+    unsigned long next_index;
+    void *next_table, *pde;
+    int next_level;
+
+    pde = table + (index * IOMMU_PAGE_TABLE_ENTRY_SIZE);
+    next_table = amd_iommu_get_vptr_from_page_table_entry((u32 *)pde);
+
+    if ( next_table )
+    {
+        next_level = level - 1;
+        if ( next_level > 1 )
+        {
+            next_index = 0;
+            do
+            {
+                deallocate_next_page_table(next_table,
+                                           next_index, next_level);
+                ++next_index;
+            } while (next_index < PTE_PER_TABLE_SIZE);
+        }
+
+        free_xenheap_page(next_table);
+    }
+}
+
+static void deallocate_iommu_page_tables(struct domain *d)
+{
+    unsigned long index;
+    struct hvm_iommu *hd  = domain_hvm_iommu(d);
+
+    if ( hd ->root_table )
+    {
+        index = 0;
+        do
+        {
+            deallocate_next_page_table(hd->root_table,
+                                       index, hd->paging_mode);
+            ++index;
+        } while ( index < PTE_PER_TABLE_SIZE );
+
+        free_xenheap_page(hd ->root_table);
+    }
+
+    hd ->root_table = NULL;
+}
+
+void amd_iommu_domain_destroy(struct domain *d)
+{
+    if ( !amd_iommu_enabled )
+        return;
+
+    deallocate_iommu_page_tables(d);
+    release_domain_devices(d);
+}
+
+struct iommu_ops amd_iommu_ops = {
+    .init = amd_iommu_domain_init,
+    .assign_device  = amd_iommu_assign_device,
+    .teardown = amd_iommu_domain_destroy,
+    .map_page = amd_iommu_map_page,
+    .unmap_page = amd_iommu_unmap_page,
+};
diff -r c9d9bbf1204c -r 72f52dd2dba8 xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c       Thu Feb 14 10:36:47 2008 +0000
+++ b/xen/arch/x86/hvm/svm/intr.c       Thu Feb 14 11:14:17 2008 +0000
@@ -94,6 +94,46 @@ static void enable_intr_window(struct vc
     vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
 }
 
+static void svm_dirq_assist(struct vcpu *v)
+{
+    unsigned int irq;
+    uint32_t device, intx;
+    struct domain *d = v->domain;
+    struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+    struct dev_intx_gsi_link *digl;
+
+    if ( !amd_iommu_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) )
+        return;
+
+    for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, NR_IRQS);
+          irq < NR_IRQS;
+          irq = find_next_bit(hvm_irq_dpci->dirq_mask, NR_IRQS, irq + 1) )
+    {
+        stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(irq)]);
+        clear_bit(irq, &hvm_irq_dpci->dirq_mask);
+
+        list_for_each_entry ( digl, &hvm_irq_dpci->mirq[irq].digl_list, list )
+        {
+            device = digl->device;
+            intx = digl->intx;
+            hvm_pci_intx_assert(d, device, intx);
+            spin_lock(&hvm_irq_dpci->dirq_lock);
+            hvm_irq_dpci->mirq[irq].pending++;
+            spin_unlock(&hvm_irq_dpci->dirq_lock);
+        }
+
+        /*
+         * Set a timer to see if the guest can finish the interrupt or not. For
+         * example, the guest OS may unmask the PIC during boot, before the
+         * guest driver is loaded. hvm_pci_intx_assert() may succeed, but the
+         * guest will never deal with the irq, then the physical interrupt line
+         * will never be deasserted.
+         */
+        set_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(irq)],
+                  NOW() + PT_IRQ_TIME_OUT);
+    }
+}
+
 asmlinkage void svm_intr_assist(void) 
 {
     struct vcpu *v = current;
@@ -102,6 +142,7 @@ asmlinkage void svm_intr_assist(void)
 
     /* Crank the handle on interrupt state. */
     pt_update_irq(v);
+    svm_dirq_assist(v);
 
     do {
         intack = hvm_vcpu_has_pending_irq(v);
diff -r c9d9bbf1204c -r 72f52dd2dba8 xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c        Thu Feb 14 10:36:47 2008 +0000
+++ b/xen/arch/x86/hvm/vioapic.c        Thu Feb 14 11:14:17 2008 +0000
@@ -458,7 +458,7 @@ void vioapic_update_EOI(struct domain *d
 
     ent->fields.remote_irr = 0;
 
-    if ( vtd_enabled )
+    if ( iommu_enabled )
     {
         spin_unlock(&d->arch.hvm_domain.irq_lock);
         hvm_dpci_eoi(current->domain, gsi, ent);
diff -r c9d9bbf1204c -r 72f52dd2dba8 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
--- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c    Thu Feb 14 10:36:47 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c    Thu Feb 14 11:14:17 2008 +0000
@@ -1047,7 +1047,7 @@ static void free_iommu(struct iommu *iom
         agaw = 64;                              \
     agaw; })
 
-int iommu_domain_init(struct domain *domain)
+int intel_iommu_domain_init(struct domain *domain)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(domain);
     struct iommu *iommu = NULL;
@@ -1055,11 +1055,6 @@ int iommu_domain_init(struct domain *dom
     int adjust_width, agaw;
     unsigned long sagaw;
     struct acpi_drhd_unit *drhd;
-
-    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 ( !vtd_enabled || list_empty(&acpi_drhd_units) )
         return 0;
@@ -1550,7 +1545,8 @@ static int domain_context_mapped(struct 
     return 0;
 }
 
-int iommu_map_page(struct domain *d, paddr_t gfn, paddr_t mfn)
+int intel_iommu_map_page(
+    struct domain *d, unsigned long gfn, unsigned long mfn)
 {
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
@@ -1566,12 +1562,12 @@ int iommu_map_page(struct domain *d, pad
         return 0;
 #endif
 
-    pg = addr_to_dma_page(d, gfn << PAGE_SHIFT_4K);
+    pg = addr_to_dma_page(d, (paddr_t)gfn << PAGE_SHIFT_4K);
     if ( !pg )
         return -ENOMEM;
     pte = (struct dma_pte *)map_domain_page(page_to_mfn(pg));
     pte += gfn & LEVEL_MASK;
-    dma_set_pte_addr(*pte, mfn << PAGE_SHIFT_4K);
+    dma_set_pte_addr(*pte, (paddr_t)mfn << PAGE_SHIFT_4K);
     dma_set_pte_prot(*pte, DMA_PTE_READ | DMA_PTE_WRITE);
     iommu_flush_cache_entry(iommu, pte);
     unmap_domain_page(pte);
@@ -1581,7 +1577,7 @@ int iommu_map_page(struct domain *d, pad
         iommu = drhd->iommu;
         if ( cap_caching_mode(iommu->cap) )
             iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d),
-                                  gfn << PAGE_SHIFT_4K, 1, 0);
+                                  (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0);
         else if ( cap_rwbf(iommu->cap) )
             iommu_flush_write_buffer(iommu);
     }
@@ -1589,7 +1585,7 @@ int iommu_map_page(struct domain *d, pad
     return 0;
 }
 
-int iommu_unmap_page(struct domain *d, dma_addr_t gfn)
+int intel_iommu_unmap_page(struct domain *d, unsigned long gfn)
 {
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
@@ -1603,12 +1599,12 @@ int iommu_unmap_page(struct domain *d, d
         return 0;
 #endif
 
-    dma_pte_clear_one(d, gfn << PAGE_SHIFT_4K);
+    dma_pte_clear_one(d, (paddr_t)gfn << PAGE_SHIFT_4K);
 
     return 0;
 }
 
-int iommu_page_mapping(struct domain *domain, dma_addr_t iova,
+int iommu_page_mapping(struct domain *domain, paddr_t iova,
                        void *hpa, size_t size, int prot)
 {
     struct acpi_drhd_unit *drhd;
@@ -1655,14 +1651,14 @@ int iommu_page_mapping(struct domain *do
     return 0;
 }
 
-int iommu_page_unmapping(struct domain *domain, dma_addr_t addr, size_t size)
+int iommu_page_unmapping(struct domain *domain, paddr_t addr, size_t size)
 {
     dma_pte_clear_range(domain, addr, addr + size);
 
     return 0;
 }
 
-void iommu_flush(struct domain *d, dma_addr_t gfn, u64 *p2m_entry)
+void iommu_flush(struct domain *d, unsigned long gfn, u64 *p2m_entry)
 {
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu = NULL;
@@ -1673,7 +1669,7 @@ void iommu_flush(struct domain *d, dma_a
         iommu = drhd->iommu;
         if ( cap_caching_mode(iommu->cap) )
             iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d),
-                                  gfn << PAGE_SHIFT_4K, 1, 0);
+                                  (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0);
         else if ( cap_rwbf(iommu->cap) )
             iommu_flush_write_buffer(iommu);
     }
@@ -1921,7 +1917,7 @@ int device_assigned(u8 bus, u8 devfn)
     return 1;
 }
 
-int assign_device(struct domain *d, u8 bus, u8 devfn)
+int intel_iommu_assign_device(struct domain *d, u8 bus, u8 devfn)
 {
     struct acpi_rmrr_unit *rmrr;
     struct pci_dev *pdev;
@@ -2151,6 +2147,14 @@ int iommu_resume(void)
     return 0;
 }
 
+struct iommu_ops intel_iommu_ops = {
+    .init = intel_iommu_domain_init,
+    .assign_device  = intel_iommu_assign_device,
+    .teardown = iommu_domain_teardown,
+    .map_page = intel_iommu_map_page,
+    .unmap_page = intel_iommu_unmap_page,
+};
+
 /*
  * Local variables:
  * mode: C
diff -r c9d9bbf1204c -r 72f52dd2dba8 xen/arch/x86/hvm/vmx/vtd/io.c
--- a/xen/arch/x86/hvm/vmx/vtd/io.c     Thu Feb 14 10:36:47 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/vtd/io.c     Thu Feb 14 11:14:17 2008 +0000
@@ -141,7 +141,7 @@ int hvm_do_IRQ_dpci(struct domain *d, un
 {
     struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
 
-    if ( !vtd_enabled || (d == dom0) || (hvm_irq->dpci == NULL) ||
+    if ( !iommu_enabled || (d == dom0) || (hvm_irq->dpci == NULL) ||
          !hvm_irq->dpci->mirq[mirq].valid )
         return 0;
 
@@ -167,7 +167,7 @@ static void hvm_dpci_isairq_eoi(struct d
     int i;
 
     ASSERT(isairq < NR_ISAIRQS);
-    if ( !vtd_enabled || !dpci ||
+    if ( !iommu_enabled || !dpci ||
          !test_bit(isairq, dpci->isairq_map) )
         return;
 
@@ -205,7 +205,7 @@ void hvm_dpci_eoi(struct domain *d, unsi
     struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
     uint32_t device, intx, machine_gsi;
 
-    if ( !vtd_enabled || (hvm_irq_dpci == NULL) ||
+    if ( !iommu_enabled || (hvm_irq_dpci == NULL) ||
          (guest_gsi >= NR_ISAIRQS &&
           !hvm_irq_dpci->girq[guest_gsi].valid) )
         return;
@@ -235,50 +235,3 @@ void hvm_dpci_eoi(struct domain *d, unsi
     else
         spin_unlock(&hvm_irq_dpci->dirq_lock);
 }
-
-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 ( !vtd_enabled )
-        return;
-
-    if ( hvm_irq_dpci != NULL )
-    {
-        for ( i = 0; i < NR_IRQS; i++ )
-            if ( hvm_irq_dpci->mirq[i].valid )
-            {
-                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);
-        }
-    }
-
-    iommu_domain_teardown(d);
-}
diff -r c9d9bbf1204c -r 72f52dd2dba8 xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c     Thu Feb 14 10:36:47 2008 +0000
+++ b/xen/arch/x86/mm/p2m.c     Thu Feb 14 11:14:17 2008 +0000
@@ -255,8 +255,21 @@ set_p2m_entry(struct domain *d, unsigned
     /* level 1 entry */
     paging_write_p2m_entry(d, gfn, p2m_entry, table_mfn, entry_content, 1);
 
-    if ( vtd_enabled && (p2mt == p2m_mmio_direct) && is_hvm_domain(d) )
-        iommu_flush(d, gfn, (u64*)p2m_entry);
+    if ( iommu_enabled && is_hvm_domain(d) )
+    {
+        if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+        {
+            if ( (p2mt == p2m_mmio_direct) )
+                iommu_flush(d, gfn, (u64*)p2m_entry);
+        }
+        else if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
+        {
+            if ( p2mt == p2m_ram_rw )
+                iommu_map_page(d, gfn, mfn_x(mfn));
+            else
+                iommu_unmap_page(d, gfn);
+        }
+    }
 
     /* Success */
     rv = 1;
diff -r c9d9bbf1204c -r 72f52dd2dba8 xen/include/asm-x86/hvm/iommu.h
--- a/xen/include/asm-x86/hvm/iommu.h   Thu Feb 14 10:36:47 2008 +0000
+++ b/xen/include/asm-x86/hvm/iommu.h   Thu Feb 14 11:14:17 2008 +0000
@@ -48,6 +48,9 @@ struct hvm_iommu {
     int domain_id;
     int paging_mode;
     void *root_table;
+
+    /* iommu_ops */
+    struct iommu_ops *platform_ops;
 };
 
 #endif // __ASM_X86_HVM_IOMMU_H__
diff -r c9d9bbf1204c -r 72f52dd2dba8 
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h      Thu Feb 14 10:36:47 
2008 +0000
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h      Thu Feb 14 11:14:17 
2008 +0000
@@ -262,6 +262,10 @@
 #define IOMMU_INV_IOMMU_PAGES_ADDR_LOW_SHIFT   12
 #define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK   0xFFFFFFFF
 #define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT  0
+
+/* INVALIDATE_DEVTAB_ENTRY command */
+#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_MASK   0x0000FFFF
+#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_SHIFT  0
 
 /* Event Log */
 #define IOMMU_EVENT_LOG_BASE_LOW_OFFSET                0x10
@@ -415,5 +419,6 @@
 #define IOMMU_PAGE_TABLE_LEVEL_4        4
 #define IOMMU_IO_WRITE_ENABLED          1
 #define IOMMU_IO_READ_ENABLED           1
+#define HACK_BIOS_SETTINGS                  0
 
 #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */
diff -r c9d9bbf1204c -r 72f52dd2dba8 
xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h     Thu Feb 14 10:36:47 
2008 +0000
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h     Thu Feb 14 11:14:17 
2008 +0000
@@ -27,13 +27,15 @@
     list_for_each_entry(amd_iommu, \
         &amd_iommu_head, list)
 
+#define for_each_pdev(domain, pdev) \
+    list_for_each_entry(pdev, \
+         &(domain->arch.hvm_domain.hvm_iommu.pdev_list), list)
+
 #define DMA_32BIT_MASK  0x00000000ffffffffULL
 #define PAGE_ALIGN(addr)    (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-#define PAGE_SHIFT_4K                   (12)
-#define PAGE_SIZE_4K                    (1UL << PAGE_SHIFT_4K)
-#define PAGE_MASK_4K                    (((u64)-1) << PAGE_SHIFT_4K)
 
-typedef int (*iommu_detect_callback_ptr_t)(u8 bus, u8 dev, u8 func, u8 
cap_ptr);
+typedef int (*iommu_detect_callback_ptr_t)(
+    u8 bus, u8 dev, u8 func, u8 cap_ptr);
 
 /* amd-iommu-detect functions */
 int __init scan_for_iommu(iommu_detect_callback_ptr_t iommu_detect_callback);
@@ -49,16 +51,20 @@ void __init enable_iommu(struct amd_iomm
 void __init enable_iommu(struct amd_iommu *iommu);
 
 /* mapping functions */
-int amd_iommu_map_page(struct domain *d, unsigned long gfn,
-        unsigned long mfn);
+int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn);
 int amd_iommu_unmap_page(struct domain *d, unsigned long gfn);
+void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry);
 
 /* device table functions */
 void amd_iommu_set_dev_table_entry(u32 *dte,
         u64 root_ptr, u16 domain_id, u8 paging_mode);
+int amd_iommu_is_dte_page_translation_valid(u32 *entry);
+void invalidate_dev_table_entry(struct amd_iommu *iommu,
+            u16 devic_id);
 
 /* send cmd to iommu */
 int send_iommu_command(struct amd_iommu *iommu, u32 cmd[]);
+void flush_command_buffer(struct amd_iommu *iommu);
 
 /* iommu domain funtions */
 int amd_iommu_domain_init(struct domain *domain);
diff -r c9d9bbf1204c -r 72f52dd2dba8 xen/include/asm-x86/hvm/vmx/intel-iommu.h
--- a/xen/include/asm-x86/hvm/vmx/intel-iommu.h Thu Feb 14 10:36:47 2008 +0000
+++ b/xen/include/asm-x86/hvm/vmx/intel-iommu.h Thu Feb 14 11:14:17 2008 +0000
@@ -422,8 +422,6 @@ struct poll_info {
 #define VTD_PAGE_TABLE_LEVEL_3  3
 #define VTD_PAGE_TABLE_LEVEL_4  4
 
-typedef paddr_t dma_addr_t;
-
 #define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
 #define MAX_IOMMUS 32
 #define MAX_IOMMU_REGS 0xc0
@@ -447,8 +445,10 @@ struct ir_ctrl {
 };
 
 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);
+    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 {
diff -r c9d9bbf1204c -r 72f52dd2dba8 xen/include/asm-x86/iommu.h
--- a/xen/include/asm-x86/iommu.h       Thu Feb 14 10:36:47 2008 +0000
+++ b/xen/include/asm-x86/iommu.h       Thu Feb 14 11:14:17 2008 +0000
@@ -28,7 +28,9 @@
 #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));
@@ -72,9 +74,9 @@ void iommu_domain_destroy(struct domain 
 void iommu_domain_destroy(struct domain *d);
 int device_assigned(u8 bus, u8 devfn);
 int assign_device(struct domain *d, u8 bus, u8 devfn);
-int iommu_map_page(struct domain *d, dma_addr_t gfn, dma_addr_t mfn);
-int iommu_unmap_page(struct domain *d, dma_addr_t gfn);
-void iommu_flush(struct domain *d, dma_addr_t gfn, u64 *p2m_entry);
+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);
@@ -89,4 +91,12 @@ void io_apic_write_remap_rte(unsigned in
 #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);
+};
+
 #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] x86 iommu: Define vendor-neutral interface for access to IOMMU., Xen patchbot-unstable <=