Message ID | 20201109125031.26409-4-andr2000@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | ARM PCI passthrough configuration and vPCI | expand |
On Mon, Nov 09, 2020 at 02:50:24PM +0200, Oleksandr Andrushchenko wrote: > From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> > > In order vPCI to work it needs all access to PCI configuration space > access to be synchronized among all entities, e.g. hardware domain and > guests. For that implement PCI host bridge specific callbacks to > propelry setup those ranges depending on host bridge implementation. > > This callback is optional and may not be used by non-ECAM host bridges. > > Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> > --- > xen/arch/arm/pci/pci-host-common.c | 16 ++++++++++++++++ > xen/arch/arm/pci/pci-host-generic.c | 15 +++++++++++++-- > xen/arch/arm/vpci.c | 16 +++++++++++++++- So this is based on top of another series, maybe it would make sense to post those together, or else it's hard to get the right context. > xen/include/asm-arm/pci.h | 7 +++++++ > 4 files changed, 51 insertions(+), 3 deletions(-) > > diff --git a/xen/arch/arm/pci/pci-host-common.c b/xen/arch/arm/pci/pci-host-common.c > index b011c7eff3c8..b81184d34980 100644 > --- a/xen/arch/arm/pci/pci-host-common.c > +++ b/xen/arch/arm/pci/pci-host-common.c > @@ -219,6 +219,22 @@ struct device *pci_find_host_bridge_device(struct device *dev) > } > return dt_to_dev(bridge->dt_node); > } > + > +int pci_host_iterate_bridges(struct domain *d, > + int (*clb)(struct domain *d, > + struct pci_host_bridge *bridge)) > +{ > + struct pci_host_bridge *bridge; > + int err; > + > + list_for_each_entry( bridge, &pci_host_bridges, node ) > + { > + err = clb(d, bridge); > + if ( err ) > + return err; > + } > + return 0; > +} > /* > * Local variables: > * mode: C > diff --git a/xen/arch/arm/pci/pci-host-generic.c b/xen/arch/arm/pci/pci-host-generic.c > index 54dd123e95c7..469df3da0116 100644 > --- a/xen/arch/arm/pci/pci-host-generic.c > +++ b/xen/arch/arm/pci/pci-host-generic.c > @@ -85,12 +85,23 @@ int pci_ecam_config_read(struct pci_host_bridge *bridge, uint32_t sbdf, > return 0; > } > > +static int pci_ecam_register_mmio_handler(struct domain *d, > + struct pci_host_bridge *bridge, I think you can also constify bridge here. Thanks, Roger.
On 11/11/20 4:39 PM, Roger Pau Monné wrote: > On Mon, Nov 09, 2020 at 02:50:24PM +0200, Oleksandr Andrushchenko wrote: >> From: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> >> >> In order vPCI to work it needs all access to PCI configuration space >> access to be synchronized among all entities, e.g. hardware domain and >> guests. For that implement PCI host bridge specific callbacks to >> propelry setup those ranges depending on host bridge implementation. >> >> This callback is optional and may not be used by non-ECAM host bridges. >> >> Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> >> --- >> xen/arch/arm/pci/pci-host-common.c | 16 ++++++++++++++++ >> xen/arch/arm/pci/pci-host-generic.c | 15 +++++++++++++-- >> xen/arch/arm/vpci.c | 16 +++++++++++++++- > So this is based on top of another series, maybe it would make sense > to post those together, or else it's hard to get the right context. This is based on ARM's PCI passthrough RFC series [1] You can also see the whole picture at [2] > >> xen/include/asm-arm/pci.h | 7 +++++++ >> 4 files changed, 51 insertions(+), 3 deletions(-) >> >> diff --git a/xen/arch/arm/pci/pci-host-common.c b/xen/arch/arm/pci/pci-host-common.c >> index b011c7eff3c8..b81184d34980 100644 >> --- a/xen/arch/arm/pci/pci-host-common.c >> +++ b/xen/arch/arm/pci/pci-host-common.c >> @@ -219,6 +219,22 @@ struct device *pci_find_host_bridge_device(struct device *dev) >> } >> return dt_to_dev(bridge->dt_node); >> } >> + >> +int pci_host_iterate_bridges(struct domain *d, >> + int (*clb)(struct domain *d, >> + struct pci_host_bridge *bridge)) >> +{ >> + struct pci_host_bridge *bridge; >> + int err; >> + >> + list_for_each_entry( bridge, &pci_host_bridges, node ) >> + { >> + err = clb(d, bridge); >> + if ( err ) >> + return err; >> + } >> + return 0; >> +} >> /* >> * Local variables: >> * mode: C >> diff --git a/xen/arch/arm/pci/pci-host-generic.c b/xen/arch/arm/pci/pci-host-generic.c >> index 54dd123e95c7..469df3da0116 100644 >> --- a/xen/arch/arm/pci/pci-host-generic.c >> +++ b/xen/arch/arm/pci/pci-host-generic.c >> @@ -85,12 +85,23 @@ int pci_ecam_config_read(struct pci_host_bridge *bridge, uint32_t sbdf, >> return 0; >> } >> >> +static int pci_ecam_register_mmio_handler(struct domain *d, >> + struct pci_host_bridge *bridge, > I think you can also constify bridge here. Makes sense > > Thanks, Roger. Thank you, Oleksandr [1] https://www.mail-archive.com/xen-devel@lists.xenproject.org/msg84452.html [2] https://github.com/andr2000/xen/tree/vpci_rfc
diff --git a/xen/arch/arm/pci/pci-host-common.c b/xen/arch/arm/pci/pci-host-common.c index b011c7eff3c8..b81184d34980 100644 --- a/xen/arch/arm/pci/pci-host-common.c +++ b/xen/arch/arm/pci/pci-host-common.c @@ -219,6 +219,22 @@ struct device *pci_find_host_bridge_device(struct device *dev) } return dt_to_dev(bridge->dt_node); } + +int pci_host_iterate_bridges(struct domain *d, + int (*clb)(struct domain *d, + struct pci_host_bridge *bridge)) +{ + struct pci_host_bridge *bridge; + int err; + + list_for_each_entry( bridge, &pci_host_bridges, node ) + { + err = clb(d, bridge); + if ( err ) + return err; + } + return 0; +} /* * Local variables: * mode: C diff --git a/xen/arch/arm/pci/pci-host-generic.c b/xen/arch/arm/pci/pci-host-generic.c index 54dd123e95c7..469df3da0116 100644 --- a/xen/arch/arm/pci/pci-host-generic.c +++ b/xen/arch/arm/pci/pci-host-generic.c @@ -85,12 +85,23 @@ int pci_ecam_config_read(struct pci_host_bridge *bridge, uint32_t sbdf, return 0; } +static int pci_ecam_register_mmio_handler(struct domain *d, + struct pci_host_bridge *bridge, + const struct mmio_handler_ops *ops) +{ + struct pci_config_window *cfg = bridge->sysdata; + + register_mmio_handler(d, ops, cfg->phys_addr, cfg->size, NULL); + return 0; +} + /* ECAM ops */ struct pci_ecam_ops pci_generic_ecam_ops = { .bus_shift = 20, .pci_ops = { - .read = pci_ecam_config_read, - .write = pci_ecam_config_write, + .read = pci_ecam_config_read, + .write = pci_ecam_config_write, + .register_mmio_handler = pci_ecam_register_mmio_handler, } }; diff --git a/xen/arch/arm/vpci.c b/xen/arch/arm/vpci.c index 49e473ab0d10..2b9bf34c8fe6 100644 --- a/xen/arch/arm/vpci.c +++ b/xen/arch/arm/vpci.c @@ -80,11 +80,25 @@ static const struct mmio_handler_ops vpci_mmio_handler = { .write = vpci_mmio_write, }; +static int vpci_setup_mmio_handler(struct domain *d, + struct pci_host_bridge *bridge) +{ + if ( bridge->ops->register_mmio_handler ) + return bridge->ops->register_mmio_handler(d, bridge, + &vpci_mmio_handler); + return 0; +} + + int domain_vpci_init(struct domain *d) { - if ( !has_vpci(d) || is_hardware_domain(d) ) + if ( !has_vpci(d) ) return 0; + if ( is_hardware_domain(d) ) + return pci_host_iterate_bridges(d, vpci_setup_mmio_handler); + + /* Guest domains use what is programmed in their device tree. */ register_mmio_handler(d, &vpci_mmio_handler, GUEST_VPCI_ECAM_BASE,GUEST_VPCI_ECAM_SIZE,NULL); diff --git a/xen/include/asm-arm/pci.h b/xen/include/asm-arm/pci.h index ba23178f67ab..e3a02429b8d4 100644 --- a/xen/include/asm-arm/pci.h +++ b/xen/include/asm-arm/pci.h @@ -27,6 +27,7 @@ #include <xen/pci.h> #include <xen/device_tree.h> #include <asm/device.h> +#include <asm/mmio.h> #ifdef CONFIG_ARM_PCI @@ -64,6 +65,9 @@ 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 (*register_mmio_handler)(struct domain *d, + struct pci_host_bridge *bridge, + const struct mmio_handler_ops *ops); }; /* @@ -101,6 +105,9 @@ void pci_init(void); bool dt_pci_parse_bus_range(struct dt_device_node *dev, struct pci_config_window *cfg); +int pci_host_iterate_bridges(struct domain *d, + int (*clb)(struct domain *d, + struct pci_host_bridge *bridge)); #else /*!CONFIG_ARM_PCI*/ struct arch_pci_dev { }; static inline void pci_init(void) { }