diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S index b773f91f1c..08016948ab 100644 --- a/xen/arch/arm/xen.lds.S +++ b/xen/arch/arm/xen.lds.S @@ -60,7 +60,7 @@ SECTIONS *(.proc.info) __proc_info_end = .; -#if defined(CONFIG_HAS_VPCI) && defined(CONFIG_LATE_HWDOM) +#ifdef CONFIG_HAS_VPCI . = ALIGN(POINTER_ALIGN); __start_vpci_array = .; *(SORT(.data.vpci.*)) @@ -189,13 +189,6 @@ SECTIONS *(.init_array) *(SORT(.init_array.*)) __ctors_end = .; - -#if defined(CONFIG_HAS_VPCI) && !defined(CONFIG_LATE_HWDOM) - . = ALIGN(POINTER_ALIGN); - __start_vpci_array = .; - *(SORT(.data.vpci.*)) - __end_vpci_array = .; -#endif } :text __init_end_efi = .; . = ALIGN(STACK_SIZE); diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index 11b1da2154..87e344d4dd 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -134,7 +134,7 @@ SECTIONS *(.ex_table.pre) __stop___pre_ex_table = .; -#if defined(CONFIG_HAS_VPCI) && defined(CONFIG_LATE_HWDOM) +#ifdef CONFIG_HAS_VPCI . = ALIGN(POINTER_ALIGN); __start_vpci_array = .; *(SORT(.data.vpci.*)) @@ -247,13 +247,6 @@ SECTIONS *(.init_array) *(SORT(.init_array.*)) __ctors_end = .; - -#if defined(CONFIG_HAS_VPCI) && !defined(CONFIG_LATE_HWDOM) - . = ALIGN(POINTER_ALIGN); - __start_vpci_array = .; - *(SORT(.data.vpci.*)) - __end_vpci_array = .; -#endif } PHDR(text) . = ALIGN(SECTION_ALIGN); diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c index 35e0190796..0d8ab2e716 100644 --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -756,27 +756,28 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn, if ( !pdev->domain ) { pdev->domain = hardware_domain; -#ifdef CONFIG_ARM + list_add(&pdev->domain_list, &hardware_domain->pdev_list); + /* - * On ARM PCI devices discovery will be done by Dom0. Add vpci handler - * when Dom0 inform XEN to add the PCI devices in XEN. + * For devices not discovered by Xen during boot, add vPCI handlers + * when Dom0 first informs Xen about such devices. */ ret = vpci_add_handlers(pdev); if ( ret ) { printk(XENLOG_ERR "Setup of vPCI failed: %d\n", ret); + list_del(&pdev->domain_list); pdev->domain = NULL; goto out; } -#endif ret = iommu_add_device(pdev); if ( ret ) { + vpci_remove_device(pdev); + list_del(&pdev->domain_list); pdev->domain = NULL; goto out; } - - list_add(&pdev->domain_list, &hardware_domain->pdev_list); } else iommu_enable_device(pdev); @@ -819,6 +820,7 @@ int pci_remove_device(u16 seg, u8 bus, u8 devfn) list_for_each_entry ( pdev, &pseg->alldevs_list, alldevs_list ) if ( pdev->bus == bus && pdev->devfn == devfn ) { + vpci_remove_device(pdev); pci_cleanup_msi(pdev); ret = iommu_remove_device(pdev); if ( pdev->domain ) diff --git a/xen/drivers/vpci/vpci.c b/xen/drivers/vpci/vpci.c index decf7d87a1..657697fe34 100644 --- a/xen/drivers/vpci/vpci.c +++ b/xen/drivers/vpci/vpci.c @@ -37,6 +37,9 @@ extern vpci_register_init_t *const __end_vpci_array[]; void vpci_remove_device(struct pci_dev *pdev) { + if ( !has_vpci(pdev->domain) ) + return; + spin_lock(&pdev->vpci->lock); while ( !list_empty(&pdev->vpci->handlers) ) { @@ -54,7 +57,7 @@ void vpci_remove_device(struct pci_dev *pdev) pdev->vpci = NULL; } -int __hwdom_init vpci_add_handlers(struct pci_dev *pdev) +int vpci_add_handlers(struct pci_dev *pdev) { unsigned int i; int rc = 0; @@ -62,6 +65,9 @@ int __hwdom_init vpci_add_handlers(struct pci_dev *pdev) if ( !has_vpci(pdev->domain) ) return 0; + /* We should not get here twice for the same device. */ + ASSERT(!pdev->vpci); + pdev->vpci = xzalloc(struct vpci); if ( !pdev->vpci ) return -ENOMEM; diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h index 6746c2589a..9ea66e033f 100644 --- a/xen/include/xen/vpci.h +++ b/xen/include/xen/vpci.h @@ -230,6 +230,8 @@ static inline int vpci_add_handlers(struct pci_dev *pdev) return 0; } +static inline void vpci_remove_device(struct pci_dev *pdev) { } + static inline void vpci_dump_msi(void) { } static inline uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg,