From: Luca Fancellu <luca.fancellu@arm.com>
Hook up existing PCI setup routines for hwdom into Arm iommu
initialization sequence, only assign endpoint devices.
During scanned PCI device assignment, also permit access to the BAR
ranges if hwdom is using vpci and hide host bridges from domains that
use the fully emulated one.
Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
Signed-off-by: Stewart Hildebrand <stewart.hildebrand@amd.com>
Signed-off-by: Mykyta Poturai <mykyta_poturai@epam.com>
---
v2->v3:
* style fixes
* rework iomem access configuration
v1->v2:
* add host bridge hiding
* fix build without CONFIG_HAS_PCI
---
xen/arch/arm/pci/pci-host-common.c | 11 +++++++++++
xen/drivers/passthrough/arm/iommu.c | 15 +++++++++++++++
xen/drivers/passthrough/pci.c | 11 +++++++++++
3 files changed, 37 insertions(+)
diff --git a/xen/arch/arm/pci/pci-host-common.c b/xen/arch/arm/pci/pci-host-common.c
index 28c26af9eb..110c334f59 100644
--- a/xen/arch/arm/pci/pci-host-common.c
+++ b/xen/arch/arm/pci/pci-host-common.c
@@ -430,6 +430,17 @@ int __init pci_host_bridge_mappings(struct domain *d)
unsigned int i;
bool need_mapping;
+ /*
+ * Only allow iomem access to ranges if we use pci-scan
+ * Actual mappings will be handled by VPCI code.
+ */
+ if ( has_vpci_bridge(d) )
+ {
+ mr_data.skip_mapping = true;
+ dt_for_each_range(dev, map_range_to_domain, &mr_data);
+ continue;
+ }
+
for ( i = 0; i < dt_number_of_address(dev); i++ )
{
paddr_t addr, size;
diff --git a/xen/drivers/passthrough/arm/iommu.c b/xen/drivers/passthrough/arm/iommu.c
index 100545e23f..124a99f198 100644
--- a/xen/drivers/passthrough/arm/iommu.c
+++ b/xen/drivers/passthrough/arm/iommu.c
@@ -19,6 +19,7 @@
#include <xen/device_tree.h>
#include <xen/iommu.h>
#include <xen/lib.h>
+#include <xen/sched.h>
#include <asm/device.h>
@@ -133,6 +134,16 @@ void arch_iommu_domain_destroy(struct domain *d)
{
}
+#ifdef CONFIG_HAS_PCI
+static int __hwdom_init iommu_add_hwdom_pci_device(u8 devfn,
+ struct pci_dev *pdev)
+{
+ const struct domain_iommu *hd = dom_iommu(hardware_domain);
+
+ return iommu_call(hd->platform_ops, add_device, devfn, pci_to_dev(pdev));
+}
+#endif
+
void __hwdom_init arch_iommu_hwdom_init(struct domain *d)
{
/* Set to false options not supported on ARM. */
@@ -142,6 +153,10 @@ void __hwdom_init arch_iommu_hwdom_init(struct domain *d)
if ( iommu_hwdom_reserved == 1 )
printk(XENLOG_WARNING "map-reserved dom0-iommu option is not supported on ARM\n");
iommu_hwdom_reserved = 0;
+
+#ifdef CONFIG_HAS_PCI
+ setup_hwdom_pci_devices(d, iommu_add_hwdom_pci_device);
+#endif
}
/*
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index 52c22fa50c..70c21403d5 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -20,6 +20,7 @@
#include <xen/pci_ids.h>
#include <xen/list.h>
#include <xen/prefetch.h>
+#include <xen/iocap.h>
#include <xen/iommu.h>
#include <xen/irq.h>
#include <xen/param.h>
@@ -1041,6 +1042,12 @@ enum pdev_type pdev_type(u16 seg, u8 bus, u8 devfn)
return pos ? DEV_TYPE_PCIe_ENDPOINT : DEV_TYPE_PCI;
}
+static bool __hwdom_init pdev_is_endpoint(const struct pci_dev *pdev)
+{
+ enum pdev_type type = pdev_type(pdev->seg, pdev->bus, pdev->devfn);
+ return type == DEV_TYPE_PCIe_ENDPOINT || type == DEV_TYPE_PCI;
+}
+
/*
* find the upstream PCIe-to-PCI/PCIX bridge or PCI legacy bridge
* return 0: the device is integrated PCI device or PCIe
@@ -1221,6 +1228,10 @@ static int __hwdom_init cf_check _setup_hwdom_pci_devices(
if ( !pdev )
continue;
+ /* Hide real bridges from HWdom when it's using the emulated one */
+ if ( has_vpci_bridge(hardware_domain) && !pdev_is_endpoint(pdev) )
+ pci_hide_device(pdev->seg, pdev->bus, pdev->devfn);
+
if ( !pdev->domain )
{
pdev->domain = ctxt->d;
--
2.51.2