[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v3 11/11] xen/arm: Translate virtual PCI bus topology for guests
Hi, Roger! On 26.10.21 16:30, Roger Pau Monné wrote: > diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c >> index fa6fcc5e467c..095671742ad8 100644 >> --- a/xen/arch/arm/domain.c >> +++ b/xen/arch/arm/domain.c >> @@ -797,6 +797,7 @@ void arch_domain_destroy(struct domain *d) >> get_order_from_bytes(d->arch.efi_acpi_len)); >> #endif >> domain_io_free(d); >> + domain_vpci_free(d); > It's a nit, but I think from a logical PoV this should be inverted? > You first free the handlers and then the IO infrastructure. Indeed, thanks > >> } >> >> void arch_domain_shutdown(struct domain *d) >> diff --git a/xen/arch/arm/vpci.c b/xen/arch/arm/vpci.c >> index 5d6c29c8dcd9..26ec2fa7cf2d 100644 >> --- a/xen/arch/arm/vpci.c >> +++ b/xen/arch/arm/vpci.c >> @@ -17,6 +17,14 @@ >> >> #define REGISTER_OFFSET(addr) ( (addr) & 0x00000fff) >> >> +struct vpci_mmio_priv { >> + /* >> + * Set to true if the MMIO handlers were set up for the emulated >> + * ECAM host PCI bridge. >> + */ >> + bool is_virt_ecam; >> +}; > Is this strictly required? It feels a bit odd to have a structure to > store and single boolean. > > I think you could replace it's usage with is_hardware_domain. I am working on some "earlier" patch fixes [1] which already needs some private to be passed to the handlers: we need to set sbdf.seg to the proper host bridge segment instead of always setting it to 0. And then I can pass "struct pci_host_bridge *bridge" as the private member and use is_hardware_domain(v->domain) to see if this is guest or hwdom. So, I'll remove the structure completely [snip] >> + */ >> static int vpci_setup_mmio_handler(struct domain *d, >> struct pci_host_bridge *bridge) >> { >> - struct pci_config_window *cfg = bridge->cfg; >> + struct vpci_mmio_priv *priv; >> + >> + priv = xzalloc(struct vpci_mmio_priv); >> + if ( !priv ) >> + return -ENOMEM; >> + >> + priv->is_virt_ecam = !is_hardware_domain(d); >> >> - register_mmio_handler(d, &vpci_mmio_handler, >> - cfg->phys_addr, cfg->size, NULL); >> + if ( is_hardware_domain(d) ) >> + { >> + struct pci_config_window *cfg = bridge->cfg; >> + >> + bridge->mmio_priv = priv; >> + register_mmio_handler(d, &vpci_mmio_handler, >> + cfg->phys_addr, cfg->size, >> + priv); >> + } >> + else >> + { >> + d->vpci_mmio_priv = priv; >> + /* 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, >> + priv); >> + } >> return 0; >> } >> >> @@ -95,14 +154,25 @@ int domain_vpci_init(struct domain *d) >> if ( !has_vpci(d) ) >> return 0; >> >> + return pci_host_iterate_bridges(d, vpci_setup_mmio_handler); > I think this is wrong for unprivileged domains: you iterate against > host bridges but just setup a single ECAM region from > GUEST_VPCI_ECAM_BASE to GUEST_VPCI_ECAM_SIZE, so you are leaking > multiple allocations of vpci_mmio_priv, and also adding a bunch of > duplicated IO handlers for the same ECAM region. > > IMO you should iterate against host bridges only for the hardware > domain case. For the unpriviledged domain case there's no need to > iterate against the list of physical host bridges as you end up > exposing a fully emulated bus which bears no resemblance to the > physical setup. Yes, I am moving this code into that "earlier" patch [1] and already spotted the leak: thus I am also re-working this code. > >> +} >> + >> +static int domain_vpci_free_cb(struct domain *d, >> + struct pci_host_bridge *bridge) >> +{ >> if ( is_hardware_domain(d) ) >> - return pci_host_iterate_bridges(d, vpci_setup_mmio_handler); >> + XFREE(bridge->mmio_priv); >> + else >> + XFREE(d->vpci_mmio_priv); >> + return 0; >> +} >> >> - /* 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); >> +void domain_vpci_free(struct domain *d) >> +{ >> + if ( !has_vpci(d) ) >> + return; >> >> - return 0; >> + pci_host_iterate_bridges(d, domain_vpci_free_cb); > Why do we need to iterate the host bridges for unprivileged domains? No need, I am taking care of this > AFAICT it just causes duplicated calls to XFREE(d->vpci_mmio_priv). I > would expect something like: > > static int bridge_free_cb(struct domain *d, > struct pci_host_bridge *bridge) > { > ASSERT(is_hardware_domain(d)); > XFREE(bridge->mmio_priv); > return 0; > } > > void domain_vpci_free(struct domain *d) > { > if ( !has_vpci(d) ) > return; > > if ( is_hardware_domain(d) ) > pci_host_iterate_bridges(d, bridge_free_cb); > else > XFREE(d->vpci_mmio_priv); > } > > Albeit I think there's no need for vpci_mmio_priv in the first place. > > Thanks, Roger. Thank you, Oleksandr [1] https://patchwork.kernel.org/project/xen-devel/patch/20211008055535.337436-9-andr2000@xxxxxxxxx/
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |