@@ -2566,7 +2566,15 @@ int __init construct_dom0(struct domain *d)
if ( rc < 0 )
return rc;
- return construct_domain(d, &kinfo);
+ rc = construct_domain(d, &kinfo);
+ if ( rc < 0 )
+ return rc;
+
+#ifdef CONFIG_HAS_PCI
+ if ( has_vpci(d) )
+ rc = pci_host_bridge_update_mappings(d);
+#endif
+ return rc;
}
/*
@@ -235,6 +235,21 @@ int pci_host_iterate_bridges(struct domain *d,
}
return 0;
}
+
+static int pci_host_bridge_update_mapping(struct domain *d,
+ struct pci_host_bridge *bridge)
+{
+ if ( !bridge->ops->update_mappings )
+ return 0;
+
+ return bridge->ops->update_mappings(d, bridge);
+}
+
+int pci_host_bridge_update_mappings(struct domain *d)
+{
+ return pci_host_iterate_bridges(d, pci_host_bridge_update_mapping);
+}
+
/*
* Local variables:
* mode: C
@@ -21,6 +21,8 @@
#include <asm/device.h>
#include <asm/io.h>
#include <xen/pci.h>
+#include <xen/sched.h>
+#include <asm/p2m.h>
#include <asm/pci.h>
/*
@@ -85,6 +87,31 @@ int pci_ecam_config_read(struct pci_host_bridge *bridge, uint32_t sbdf,
return 0;
}
+/*
+ * TODO: This is called late on domain creation to mangle p2m if needed:
+ * for ECAM host controller for mmio region traps to work for Domain-0
+ * we need to unmap those mappings in p2m.
+ * This is WIP:
+ * julieng: I think it would be best if we avoid the map/unmap operation.
+ * So maybe we want to introduce another way to avoid the mapping.
+ * Maybe by changing the type of the controller to "PCI_HOSTCONTROLLER"
+ * and check if this is a PCI hostcontroller avoid the mapping.
+ */
+static int pci_ecam_update_mappings(struct domain *d,
+ struct pci_host_bridge *bridge)
+{
+ struct pci_config_window *cfg = bridge->sysdata;
+ int ret;
+
+ /* Only for control domain which owns this PCI host bridge. */
+ if ( !is_control_domain(d) )
+ return 0;
+
+ ret = unmap_regions_p2mt(d, gaddr_to_gfn(cfg->phys_addr),
+ cfg->size >> PAGE_SHIFT, INVALID_MFN);
+ return ret;
+}
+
static int pci_ecam_register_mmio_handler(struct domain *d,
struct pci_host_bridge *bridge,
const struct mmio_handler_ops *ops)
@@ -101,6 +128,7 @@ struct pci_ecam_ops pci_generic_ecam_ops = {
.pci_ops = {
.read = pci_ecam_config_read,
.write = pci_ecam_config_write,
+ .update_mappings = pci_ecam_update_mappings,
.register_mmio_handler = pci_ecam_register_mmio_handler,
}
};
@@ -65,6 +65,7 @@ struct pci_ops {
uint32_t sbdf, int where, int size, u32 *val);
int (*write)(struct pci_host_bridge *bridge,
uint32_t sbdf, int where, int size, u32 val);
+ int (*update_mappings)(struct domain *d, struct pci_host_bridge *bridge);
int (*register_mmio_handler)(struct domain *d,
struct pci_host_bridge *bridge,
const struct mmio_handler_ops *ops);
@@ -108,6 +109,7 @@ bool dt_pci_parse_bus_range(struct dt_device_node *dev,
int pci_host_iterate_bridges(struct domain *d,
int (*clb)(struct domain *d,
struct pci_host_bridge *bridge));
+int pci_host_bridge_update_mappings(struct domain *d);
#else /*!CONFIG_ARM_PCI*/
struct arch_pci_dev { };
static inline void pci_init(void) { }