All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] AMD IOMMU: Code cleanup and bug fix to satisfy recent iommu changes
@ 2009-09-04 13:01 Wei Wang2
  0 siblings, 0 replies; only message in thread
From: Wei Wang2 @ 2009-09-04 13:01 UTC (permalink / raw)
  To: xen-devel; +Cc: osrc-patches

[-- Attachment #1: Type: text/plain, Size: 745 bytes --]

Hi,
Attached 2 patches fix 2 bugs introduced by recent iommu change sets on amd 
iommu systems. Please see below the detail:
1) fix-mapping.patch: Remove an useless flag and fix I/O page fault for hvm 
passthru devices.
2) fix-init.patch: Cleanup initialization functions and fix a fatal page fault 
caused by out-of-bounds access to irq_to_iommu array.
Thanks,
-Wei

Signed-off-by: Wei Wang <wei.wang2@amd.com>
-- 
AMD GmbH, Germany
Operating System Research Center

Legal Information:
Advanced Micro Devices GmbH
Karl-Hammerschmidt-Str. 34
85609 Dornach b. München

Geschäftsführer: Andrew Bowd, Thomas M. McCoy, Giuliano Meroni
Sitz: Dornach, Gemeinde Aschheim, Landkreis München
Registergericht München, HRB Nr. 43632

[-- Attachment #2: fix-init.patch --]
[-- Type: text/x-diff, Size: 7209 bytes --]

diff -r 543e60c18086 xen/drivers/passthrough/amd/iommu_init.c
--- a/xen/drivers/passthrough/amd/iommu_init.c	Fri Sep 04 12:21:43 2009 +0200
+++ b/xen/drivers/passthrough/amd/iommu_init.c	Fri Sep 04 14:14:12 2009 +0200
@@ -514,10 +514,6 @@ void enable_iommu(struct amd_iommu *iomm
 
     spin_lock_irqsave(&iommu->lock, flags);
 
-    irq_to_iommu = xmalloc_array(struct amd_iommu *, nr_irqs);
-    BUG_ON(!irq_to_iommu);
-    memset(irq_to_iommu, 0, nr_irqs * sizeof(struct iommu*));
-
     if ( iommu->enabled )
     {
         spin_unlock_irqrestore(&iommu->lock, flags); 
@@ -551,12 +547,6 @@ static void __init deallocate_iommu_tabl
         __free_amd_iommu_tables(table->buffer, order);
         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,
@@ -578,7 +568,7 @@ static int __init allocate_iommu_table_s
     return 0;
 }
 
-static int __init allocate_iommu_tables(struct amd_iommu *iommu)
+static int __init allocate_cmd_buffer(struct amd_iommu *iommu)
 {
     /* allocate 'command buffer' in power of 2 increments of 4K */
     iommu->cmd_buffer_tail = 0;
@@ -589,10 +579,12 @@ static int __init allocate_iommu_tables(
     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 */
+    return (allocate_iommu_table_struct(&iommu->cmd_buffer, "Command Buffer"));
+}
+
+static int __init allocate_event_log(struct amd_iommu *iommu)
+{
+   /* 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(
@@ -601,19 +593,15 @@ static int __init allocate_iommu_tables(
     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;
+    return (allocate_iommu_table_struct(&iommu->event_log, "Event Log"));
 }
 
 int __init amd_iommu_init_one(struct amd_iommu *iommu)
 {
-    if ( allocate_iommu_tables(iommu) != 0 )
+    if ( allocate_cmd_buffer(iommu) != 0 )
+        goto error_out;
+
+    if ( allocate_event_log(iommu) != 0 )
         goto error_out;
 
     if ( map_iommu_mmio_region(iommu) != 0 )
@@ -640,20 +628,46 @@ error_out:
     return -ENODEV;
 }
 
-void __init amd_iommu_init_cleanup(void)
+static void __init amd_iommu_init_cleanup(void)
 {
     struct amd_iommu *iommu, *next;
 
+    /* free amd iommu list */
     list_for_each_entry_safe ( iommu, next, &amd_iommu_head, list )
     {
         list_del(&iommu->list);
         if ( iommu->enabled )
         {
-            deallocate_iommu_tables(iommu);
+            deallocate_iommu_table_struct(&iommu->cmd_buffer);
+            deallocate_iommu_table_struct(&iommu->event_log);
             unmap_iommu_mmio_region(iommu);
         }
         xfree(iommu);
     }
+
+    /* free interrupt remapping table */
+    deallocate_intremap_table();
+
+    /* free device table */
+    deallocate_iommu_table_struct(&device_table);
+
+    /* free ivrs_mappings[] */
+    if ( ivrs_mappings )
+    {
+        xfree(ivrs_mappings);
+        ivrs_mappings = NULL;
+    }
+
+    /* free irq_to_iommu[] */
+    if ( irq_to_iommu )
+    {
+        xfree(irq_to_iommu);
+        irq_to_iommu = NULL;
+    }
+
+    iommu_enabled = 0;
+    iommu_passthrough = 0;
+    iommu_intremap = 0;
 }
 
 static int __init init_ivrs_mapping(void)
@@ -696,31 +710,45 @@ static int __init amd_iommu_setup_device
     return ( allocate_iommu_table_struct(&device_table, "Device Table") );
 }
 
-int __init amd_iommu_setup_shared_tables(void)
-{
-    BUG_ON( !ivrs_bdf_entries );
+int __init amd_iommu_init(void)
+{
+    struct amd_iommu *iommu;
+
+    BUG_ON( !iommu_found() );
+
+    irq_to_iommu = xmalloc_array(struct amd_iommu *, nr_irqs);
+    BUG_ON(!irq_to_iommu);
+    memset(irq_to_iommu, 0, nr_irqs * sizeof(struct iommu*));
+
+    ivrs_bdf_entries = amd_iommu_get_ivrs_dev_entries();
+
+    if ( !ivrs_bdf_entries )
+        goto error_out;
 
     if ( init_ivrs_mapping() != 0 )
         goto error_out;
 
+    if ( amd_iommu_update_ivrs_mapping_acpi() != 0 )
+        goto error_out;
+
+    /* allocate and initialize a global device table shared by all iommus */
     if ( amd_iommu_setup_device_table() != 0 )
         goto error_out;
 
+    /* initialize io-apic interrupt remapping entries */
     if ( amd_iommu_setup_intremap_table() != 0 )
         goto error_out;
 
+    /* per iommu initialization  */
+    for_each_amd_iommu ( iommu )
+        if ( amd_iommu_init_one(iommu) != 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;
+    amd_iommu_init_cleanup();
+    return -ENODEV;
 }
 
 static void disable_iommu(struct amd_iommu *iommu)
diff -r 543e60c18086 xen/drivers/passthrough/amd/pci_amd_iommu.c
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c	Fri Sep 04 12:21:43 2009 +0200
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c	Fri Sep 04 14:14:12 2009 +0200
@@ -28,34 +28,6 @@ extern struct ivrs_mappings *ivrs_mappin
 extern struct ivrs_mappings *ivrs_mappings;
 extern void *int_remap_table;
 
-int __init amd_iommu_init(void)
-{
-    struct amd_iommu *iommu;
-
-    BUG_ON( !iommu_found() );
-
-    ivrs_bdf_entries = amd_iommu_get_ivrs_dev_entries();
-
-    if ( !ivrs_bdf_entries )
-        goto error_out;
-
-    if ( amd_iommu_setup_shared_tables() != 0 )
-        goto error_out;
-
-    if ( amd_iommu_update_ivrs_mapping_acpi() != 0 )
-        goto error_out;
-
-    for_each_amd_iommu ( iommu )
-        if ( amd_iommu_init_one(iommu) != 0 )
-            goto error_out;
-
-    return 0;
-
-error_out:
-    amd_iommu_init_cleanup();
-    return -ENODEV;
-}
-
 struct amd_iommu *find_iommu_for_device(int bus, int devfn)
 {
     u16 bdf = (bus << 8) | devfn;
diff -r 543e60c18086 xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h	Fri Sep 04 12:21:43 2009 +0200
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h	Fri Sep 04 14:14:12 2009 +0200
@@ -52,10 +52,7 @@ int __init amd_iommu_detect_acpi(void);
 
 /* amd-iommu-init functions */
 int __init amd_iommu_init(void);
-int __init amd_iommu_init_one(struct amd_iommu *iommu);
 int __init amd_iommu_update_ivrs_mapping_acpi(void);
-void __init amd_iommu_init_cleanup(void);
-int __init amd_iommu_setup_shared_tables(void);
 
 /* mapping functions */
 int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn);

[-- Attachment #3: fix-mapping.patch --]
[-- Type: text/x-diff, Size: 2061 bytes --]

diff -r 8f81bdd57afe xen/drivers/passthrough/amd/iommu_map.c
--- a/xen/drivers/passthrough/amd/iommu_map.c	Thu Sep 03 09:51:37 2009 +0100
+++ b/xen/drivers/passthrough/amd/iommu_map.c	Fri Sep 04 14:25:49 2009 +0200
@@ -459,9 +459,6 @@ int amd_iommu_map_page(struct domain *d,
 
     spin_lock(&hd->mapping_lock);
 
-    if ( is_hvm_domain(d) && !hd->p2m_synchronized )
-        goto out;
-
     iommu_l2e = iommu_l2e_from_pfn(hd->root_table, hd->paging_mode, gfn);
     if ( iommu_l2e == 0 )
     {
@@ -472,7 +469,6 @@ int amd_iommu_map_page(struct domain *d,
     }
     set_iommu_l1e_present(iommu_l2e, gfn, (u64)mfn << PAGE_SHIFT, iw, ir);
 
-out:
     spin_unlock(&hd->mapping_lock);
     return 0;
 }
@@ -487,12 +483,6 @@ int amd_iommu_unmap_page(struct domain *
     BUG_ON( !hd->root_table );
 
     spin_lock(&hd->mapping_lock);
-
-    if ( is_hvm_domain(d) && !hd->p2m_synchronized )
-    {
-        spin_unlock(&hd->mapping_lock);
-        return 0;
-    }
 
     iommu_l2e = iommu_l2e_from_pfn(hd->root_table, hd->paging_mode, gfn);
 
diff -r 8f81bdd57afe xen/drivers/passthrough/iommu.c
--- a/xen/drivers/passthrough/iommu.c	Thu Sep 03 09:51:37 2009 +0100
+++ b/xen/drivers/passthrough/iommu.c	Fri Sep 04 14:25:49 2009 +0200
@@ -158,7 +158,8 @@ static int iommu_populate_page_table(str
 
     page_list_for_each ( page, &d->page_list )
     {
-        if ( (page->u.inuse.type_info & PGT_type_mask) == PGT_writable_page )
+        if ( is_hvm_domain(d) ||
+            (page->u.inuse.type_info & PGT_type_mask) == PGT_writable_page )
         {
             rc = hd->platform_ops->map_page(
                 d, mfn_to_gmfn(d, page_to_mfn(page)), page_to_mfn(page));
diff -r 8f81bdd57afe xen/include/xen/hvm/iommu.h
--- a/xen/include/xen/hvm/iommu.h	Thu Sep 03 09:51:37 2009 +0100
+++ b/xen/include/xen/hvm/iommu.h	Fri Sep 04 14:25:49 2009 +0200
@@ -41,7 +41,6 @@ struct hvm_iommu {
     int domain_id;
     int paging_mode;
     struct page_info *root_table;
-    bool_t p2m_synchronized;
 
     /* iommu_ops */
     struct iommu_ops *platform_ops;

[-- Attachment #4: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2009-09-04 13:01 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-09-04 13:01 [PATCH] AMD IOMMU: Code cleanup and bug fix to satisfy recent iommu changes Wei Wang2

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.