diff --git a/xen/arch/arm/include/asm/pci.h b/xen/arch/arm/include/asm/pci.h index 37a6f14dd4..08ffcd4438 100644 --- a/xen/arch/arm/include/asm/pci.h +++ b/xen/arch/arm/include/asm/pci.h @@ -151,6 +151,8 @@ void pci_generic_init_bus_range_child(struct dt_device_node *dev, struct pci_host_bridge *bridge, struct pci_config_window *cfg); +bool arch_pci_device_physdevop(void); + #else /*!CONFIG_HAS_PCI*/ struct pci_dev; diff --git a/xen/arch/arm/pci/pci.c b/xen/arch/arm/pci/pci.c index 8d9692c92e..beb1f971fa 100644 --- a/xen/arch/arm/pci/pci.c +++ b/xen/arch/arm/pci/pci.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,17 @@ static int __init acpi_pci_init(void) } #endif +/* + * Platform-specific PCI host dependencies require dom0 to handle + * initialization and issue PHYSDEVOP_pci_device_add/remove calls for SMMU + * device registration. This check is used to enable the minimal PCI + * subsystem required for dom0 operation when PCI passthrough is disabled. + */ +bool arch_pci_device_physdevop(void) +{ + return iommu_enabled; +} + /* By default pci passthrough is disabled. */ bool __read_mostly pci_passthrough_enabled; boolean_param("pci-passthrough", pci_passthrough_enabled); @@ -85,7 +97,7 @@ static int __init pci_init(void) * Enable PCI passthrough when has been enabled explicitly * (pci-passthrough=on). */ - if ( !pci_passthrough_enabled ) + if ( !is_pci_passthrough_enabled() && !arch_pci_device_physdevop() ) return 0; if ( pci_add_segment(0) ) diff --git a/xen/arch/x86/include/asm/pci.h b/xen/arch/x86/include/asm/pci.h index 2e67cba8b9..665b321165 100644 --- a/xen/arch/x86/include/asm/pci.h +++ b/xen/arch/x86/include/asm/pci.h @@ -57,6 +57,16 @@ static always_inline bool is_pci_passthrough_enabled(void) return true; } +/* + * Since PCI passthrough is always enabled on x86, physdevop handling doesn't + * need special arch-specific behavior. Current call sites work with either + * return value, but true is more consistent with passthrough being enabled. + */ +static inline bool arch_pci_device_physdevop(void) +{ + return true; +} + void arch_pci_init_pdev(struct pci_dev *pdev); bool pci_check_bar(const struct pci_dev *pdev, mfn_t start, mfn_t end); diff --git a/xen/drivers/pci/physdev.c b/xen/drivers/pci/physdev.c index 78de67ec64..d46501b884 100644 --- a/xen/drivers/pci/physdev.c +++ b/xen/drivers/pci/physdev.c @@ -19,7 +19,7 @@ ret_t pci_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) struct pci_dev_info pdev_info; nodeid_t node = NUMA_NO_NODE; - if ( !is_pci_passthrough_enabled() ) + if ( !is_pci_passthrough_enabled() && !arch_pci_device_physdevop() ) return -EOPNOTSUPP; ret = -EFAULT; @@ -57,7 +57,7 @@ ret_t pci_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) case PHYSDEVOP_pci_device_remove: { struct physdev_pci_device dev; - if ( !is_pci_passthrough_enabled() ) + if ( !is_pci_passthrough_enabled() && !arch_pci_device_physdevop() ) return -EOPNOTSUPP; ret = -EFAULT; @@ -74,7 +74,7 @@ ret_t pci_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) struct pci_dev *pdev; pci_sbdf_t sbdf; - if ( !is_pci_passthrough_enabled() ) + if ( !is_pci_passthrough_enabled() && !arch_pci_device_physdevop() ) return -EOPNOTSUPP; ret = -EFAULT; diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h index ef60196653..130c2a8c1a 100644 --- a/xen/include/xen/pci.h +++ b/xen/include/xen/pci.h @@ -79,6 +79,11 @@ static inline bool is_pci_passthrough_enabled(void) return false; } +static inline bool arch_pci_device_physdevop(void) +{ + return false; +} + #endif struct pci_dev_info {