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] AMD IOMMU: Since device id covered by eac

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] AMD IOMMU: Since device id covered by each iommu can never overlap,
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 01 Aug 2008 02:20:24 -0700
Delivery-date: Fri, 01 Aug 2008 02:23:01 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1217507700 -3600
# Node ID d922ce861337d1911505bf89b805410453c36223
# Parent  6fabbba27009d1fab2fe6c061e27d1f2cf3d0bac
AMD IOMMU: Since device id covered by each iommu can never overlap,
use a global device table instead of allocating private tables for
each iommu. Migrate a few functions from pci_amd_iommu.c

Signed-off-by: Wei Wang <wei.wang2@xxxxxxx>
---
 xen/drivers/passthrough/amd/iommu_init.c |  233 +++++++++++++++++++++++++++----
 1 files changed, 206 insertions(+), 27 deletions(-)

diff -r 6fabbba27009 -r d922ce861337 xen/drivers/passthrough/amd/iommu_init.c
--- a/xen/drivers/passthrough/amd/iommu_init.c  Thu Jul 31 13:31:15 2008 +0100
+++ b/xen/drivers/passthrough/amd/iommu_init.c  Thu Jul 31 13:35:00 2008 +0100
@@ -27,10 +27,20 @@
 #include <asm/hvm/svm/amd-iommu-proto.h>
 #include <asm-x86/fixmap.h>
 
-extern int nr_amd_iommus;
 static struct amd_iommu *vector_to_iommu[NR_VECTORS];
-
-int __init map_iommu_mmio_region(struct amd_iommu *iommu)
+static int nr_amd_iommus;
+static long amd_iommu_cmd_buffer_entries = IOMMU_CMD_BUFFER_DEFAULT_ENTRIES;
+static long amd_iommu_event_log_entries = IOMMU_EVENT_LOG_DEFAULT_ENTRIES;
+
+unsigned short ivrs_bdf_entries;
+struct ivrs_mappings *ivrs_mappings;
+struct list_head amd_iommu_head;
+struct table_struct device_table;
+
+extern void *int_remap_table;
+extern spinlock_t int_remap_table_lock;
+
+static int __init map_iommu_mmio_region(struct amd_iommu *iommu)
 {
     unsigned long mfn;
 
@@ -51,7 +61,7 @@ int __init map_iommu_mmio_region(struct 
     return 0;
 }
 
-void __init unmap_iommu_mmio_region(struct amd_iommu *iommu)
+static void __init unmap_iommu_mmio_region(struct amd_iommu *iommu)
 {
     if ( iommu->mmio_base )
     {
@@ -60,7 +70,7 @@ void __init unmap_iommu_mmio_region(stru
     }
 }
 
-void __init register_iommu_dev_table_in_mmio_space(struct amd_iommu *iommu)
+static void __init register_iommu_dev_table_in_mmio_space(struct amd_iommu 
*iommu)
 {
     u64 addr_64, addr_lo, addr_hi;
     u32 entry;
@@ -83,7 +93,7 @@ void __init register_iommu_dev_table_in_
     writel(entry, iommu->mmio_base + IOMMU_DEV_TABLE_BASE_HIGH_OFFSET);
 }
 
-void __init register_iommu_cmd_buffer_in_mmio_space(struct amd_iommu *iommu)
+static void __init register_iommu_cmd_buffer_in_mmio_space(struct amd_iommu 
*iommu)
 {
     u64 addr_64, addr_lo, addr_hi;
     u32 power_of2_entries;
@@ -110,7 +120,7 @@ void __init register_iommu_cmd_buffer_in
     writel(entry, iommu->mmio_base+IOMMU_CMD_BUFFER_BASE_HIGH_OFFSET);
 }
 
-void __init register_iommu_event_log_in_mmio_space(struct amd_iommu *iommu)
+static void __init register_iommu_event_log_in_mmio_space(struct amd_iommu 
*iommu)
 {
     u64 addr_64, addr_lo, addr_hi;
     u32 power_of2_entries;
@@ -266,12 +276,13 @@ static int amd_iommu_read_event_log(stru
     return -EFAULT;
 }
 
-static void amd_iommu_msi_data_init(struct amd_iommu *iommu, int vector)
+static void amd_iommu_msi_data_init(struct amd_iommu *iommu)
 {
     u32 msi_data;
     u8 bus = (iommu->bdf >> 8) & 0xff;
     u8 dev = PCI_SLOT(iommu->bdf & 0xff);
     u8 func = PCI_FUNC(iommu->bdf & 0xff);
+    int vector = iommu->vector;
 
     msi_data = MSI_DATA_TRIGGER_EDGE |
         MSI_DATA_LEVEL_ASSERT |
@@ -434,7 +445,6 @@ static int set_iommu_interrupt_handler(s
 static int set_iommu_interrupt_handler(struct amd_iommu *iommu)
 {
     int vector, ret;
-    unsigned long flags;
 
     vector = assign_irq_vector(AUTO_ASSIGN);
     vector_to_iommu[vector] = iommu;
@@ -450,38 +460,207 @@ static int set_iommu_interrupt_handler(s
     }
 
     irq_desc[vector].handler = &iommu_msi_type;
-    ret = request_irq(vector, amd_iommu_page_fault, 0, "dmar", iommu);
+    ret = request_irq(vector, amd_iommu_page_fault, 0, "amd_iommu", iommu);
     if ( ret )
     {
         amd_iov_error("can't request irq\n");
         return 0;
     }
 
+    return vector;
+}
+
+void __init enable_iommu(struct amd_iommu *iommu)
+{
+    unsigned long flags;
+
     spin_lock_irqsave(&iommu->lock, flags);
 
-    amd_iommu_msi_data_init (iommu, vector);
+    if ( iommu->enabled )
+        return;
+
+    iommu->dev_table.alloc_size = device_table.alloc_size;
+    iommu->dev_table.entries = device_table.entries;
+    iommu->dev_table.buffer = device_table.buffer;
+
+    register_iommu_dev_table_in_mmio_space(iommu);
+    register_iommu_cmd_buffer_in_mmio_space(iommu);
+    register_iommu_event_log_in_mmio_space(iommu);
+    register_iommu_exclusion_range(iommu);
+
+    amd_iommu_msi_data_init (iommu);
     amd_iommu_msi_addr_init(iommu, cpu_physical_id(first_cpu(cpu_online_map)));
     amd_iommu_msi_enable(iommu, IOMMU_CONTROL_ENABLED);
 
-    spin_unlock_irqrestore(&iommu->lock, flags);
-
-    return vector;
-}
-
-void __init enable_iommu(struct amd_iommu *iommu)
-{
-    unsigned long flags;
-
-    set_iommu_interrupt_handler(iommu);
-
-    spin_lock_irqsave(&iommu->lock, flags);
-
-    register_iommu_exclusion_range(iommu);
     set_iommu_command_buffer_control(iommu, IOMMU_CONTROL_ENABLED);
     set_iommu_event_log_control(iommu, IOMMU_CONTROL_ENABLED);
     set_iommu_translation_control(iommu, IOMMU_CONTROL_ENABLED);
 
+    printk("AMD_IOV: IOMMU %d Enabled.\n", nr_amd_iommus );
+    nr_amd_iommus++;
+
+    iommu->enabled = 1;
     spin_unlock_irqrestore(&iommu->lock, flags);
 
-    printk("AMD_IOV: IOMMU %d Enabled.\n", nr_amd_iommus);
-}
+}
+
+static void __init deallocate_iommu_table_struct(
+    struct table_struct *table)
+{
+    if ( table->buffer )
+    {
+        free_xenheap_pages(table->buffer,
+            get_order_from_bytes(table->alloc_size));
+        table->buffer = NULL;
+    }
+}
+
+static void __init deallocate_iommu_tables(struct amd_iommu *iommu)
+{
+    deallocate_iommu_table_struct(&iommu->cmd_buffer);
+    deallocate_iommu_table_struct(&iommu->event_log);
+}
+
+static int __init allocate_iommu_table_struct(struct table_struct *table,
+                                              const char *name)
+{
+    table->buffer = (void *) alloc_xenheap_pages(
+        get_order_from_bytes(table->alloc_size));
+
+    if ( !table->buffer )
+    {
+        amd_iov_error("Error allocating %s\n", name);
+        return -ENOMEM;
+    }
+
+    memset(table->buffer, 0, table->alloc_size);
+    return 0;
+}
+
+static int __init allocate_iommu_tables(struct amd_iommu *iommu)
+{
+    /* 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 =
+        iommu->cmd_buffer.alloc_size / IOMMU_CMD_BUFFER_ENTRY_SIZE;
+
+    if ( allocate_iommu_table_struct(&iommu->cmd_buffer, "Command Buffer") != 
0 )
+        goto error_out;
+
+    /* allocate 'event log' in power of 2 increments of 4K */
+    iommu->event_log_head = 0;
+    iommu->event_log.alloc_size = PAGE_SIZE << get_order_from_bytes(
+        PAGE_ALIGN(amd_iommu_event_log_entries * IOMMU_EVENT_LOG_ENTRY_SIZE));
+    iommu->event_log.entries =
+        iommu->event_log.alloc_size / IOMMU_EVENT_LOG_ENTRY_SIZE;
+
+    if ( allocate_iommu_table_struct(&iommu->event_log, "Event Log") != 0 )
+        goto error_out;
+
+    return 0;
+
+ error_out:
+    deallocate_iommu_tables(iommu);
+    return -ENOMEM;
+}
+
+int __init amd_iommu_init_one(struct amd_iommu *iommu)
+{
+
+    if ( allocate_iommu_tables(iommu) != 0 )
+        goto error_out;
+
+    if ( map_iommu_mmio_region(iommu) != 0 )
+        goto error_out;
+
+    if ( set_iommu_interrupt_handler(iommu) == 0 )
+        goto error_out;
+
+    enable_iommu(iommu);
+    return 0;
+
+error_out:
+    return -ENODEV;
+}
+
+void __init amd_iommu_init_cleanup(void)
+{
+    struct amd_iommu *iommu, *next;
+
+    list_for_each_entry_safe ( iommu, next, &amd_iommu_head, list )
+    {
+        list_del(&iommu->list);
+        if ( iommu->enabled )
+        {
+            deallocate_iommu_tables(iommu);
+            unmap_iommu_mmio_region(iommu);
+        }
+        xfree(iommu);
+    }
+}
+
+static int __init init_ivrs_mapping(void)
+{
+    int bdf;
+
+    BUG_ON( !ivrs_bdf_entries );
+
+    ivrs_mappings = xmalloc_array( struct ivrs_mappings, ivrs_bdf_entries);
+    if ( ivrs_mappings == NULL )
+    {
+        amd_iov_error("Error allocating IVRS Mappings table\n");
+        return -ENOMEM;
+    }
+    memset(ivrs_mappings, 0, ivrs_bdf_entries * sizeof(struct ivrs_mappings));
+
+    /* assign default values for device entries */
+    for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
+    {
+        ivrs_mappings[bdf].dte_requestor_id = bdf;
+        ivrs_mappings[bdf].dte_sys_mgt_enable =
+            IOMMU_DEV_TABLE_SYS_MGT_MSG_FORWARDED;
+        ivrs_mappings[bdf].dte_allow_exclusion = IOMMU_CONTROL_DISABLED;
+        ivrs_mappings[bdf].unity_map_enable = IOMMU_CONTROL_DISABLED;
+        ivrs_mappings[bdf].iommu = NULL;
+    }
+    return 0;
+}
+
+static int __init amd_iommu_setup_device_table(void)
+{
+    /* allocate 'device table' on a 4K boundary */
+    device_table.alloc_size = PAGE_SIZE << get_order_from_bytes(
+        PAGE_ALIGN(ivrs_bdf_entries * IOMMU_DEV_TABLE_ENTRY_SIZE));
+    device_table.entries = device_table.alloc_size / 
IOMMU_DEV_TABLE_ENTRY_SIZE;
+
+    return ( allocate_iommu_table_struct(&device_table, "Device Table") );
+}
+
+int __init amd_iommu_setup_shared_tables(void)
+{
+    BUG_ON( !ivrs_bdf_entries );
+
+    if (init_ivrs_mapping() != 0 )
+        goto error_out;
+
+    if ( amd_iommu_setup_device_table() != 0 )
+        goto error_out;
+
+    if ( amd_iommu_setup_intremap_table() != 0 )
+        goto error_out;
+
+    return 0;
+
+error_out:
+    deallocate_intremap_table();
+    deallocate_iommu_table_struct(&device_table);
+
+    if ( ivrs_mappings )
+    {
+        xfree(ivrs_mappings);
+        ivrs_mappings = NULL;
+    }
+    return -ENOMEM;
+}

_______________________________________________
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] AMD IOMMU: Since device id covered by each iommu can never overlap,, Xen patchbot-unstable <=