From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Wang2 Subject: [PATCH] AMD IOMMU: Code cleanup and bug fix to satisfy recent iommu changes Date: Fri, 4 Sep 2009 15:01:48 +0200 Message-ID: <200909041501.49045.wei.wang2@amd.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary-00=_9+QoK0TnakxdbTk" Return-path: Content-Disposition: inline List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com Cc: osrc-patches List-Id: xen-devel@lists.xenproject.org --Boundary-00=_9+QoK0TnakxdbTk Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Hi, Attached 2 patches fix 2 bugs introduced by recent iommu change sets on amd= =20 iommu systems. Please see below the detail: 1) fix-mapping.patch: Remove an useless flag and fix I/O page fault for hvm= =20 passthru devices. 2) fix-init.patch: Cleanup initialization functions and fix a fatal page fa= ult=20 caused by out-of-bounds access to irq_to_iommu array. Thanks, =2DWei Signed-off-by: Wei Wang =2D-=20 AMD GmbH, Germany Operating System Research Center Legal Information: Advanced Micro Devices GmbH Karl-Hammerschmidt-Str. 34 85609 Dornach b. M=FCnchen Gesch=E4ftsf=FChrer: Andrew Bowd, Thomas M. McCoy, Giuliano Meroni Sitz: Dornach, Gemeinde Aschheim, Landkreis M=FCnchen Registergericht M=FCnchen, HRB Nr. 43632 --Boundary-00=_9+QoK0TnakxdbTk Content-Type: text/x-diff; charset="iso-8859-1"; name="fix-init.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="fix-init.patch" 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); --Boundary-00=_9+QoK0TnakxdbTk Content-Type: text/x-diff; charset="iso-8859-1"; name="fix-mapping.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="fix-mapping.patch" 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; --Boundary-00=_9+QoK0TnakxdbTk Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --Boundary-00=_9+QoK0TnakxdbTk--