[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v3] vPCI: account for hidden devices
On Tue, May 30, 2023 at 02:38:56PM +0200, Jan Beulich wrote: > Hidden devices (e.g. an add-in PCI serial card used for Xen's serial > console) are associated with DomXEN, not Dom0. This means that while > looking for overlapping BARs such devices cannot be found on Dom0's list > of devices; DomXEN's list also needs to be scanned. > > Suppress vPCI init altogether for r/o devices (which constitute a subset > of hidden ones). > > Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> Just one nit below. > --- > v3: Also consider pdev being DomXEN's in modify_bars(). Also consult > DomXEN in vpci_{read,write}(). Move vpci_write()'s check of the r/o > map out of mainline code. Re-base over the standalone addition of > the loop continuation in modify_bars(), and finally make the code > change there well-formed. > v2: Extend existing comment. Relax assertion. Don't initialize vPCI for > r/o devices. > > --- a/xen/drivers/vpci/header.c > +++ b/xen/drivers/vpci/header.c > @@ -218,6 +218,7 @@ static int modify_bars(const struct pci_ > struct vpci_header *header = &pdev->vpci->header; > struct rangeset *mem = rangeset_new(NULL, NULL, 0); > struct pci_dev *tmp, *dev = NULL; > + const struct domain *d; > const struct vpci_msix *msix = pdev->vpci->msix; > unsigned int i; > int rc; > @@ -285,58 +286,69 @@ static int modify_bars(const struct pci_ > > /* > * Check for overlaps with other BARs. Note that only BARs that are > - * currently mapped (enabled) are checked for overlaps. > + * currently mapped (enabled) are checked for overlaps. Note also that > + * for hwdom we also need to include hidden, i.e. DomXEN's, devices. > */ > - for_each_pdev ( pdev->domain, tmp ) > + for ( d = pdev->domain != dom_xen ? pdev->domain : hardware_domain; ; ) > { > - if ( !tmp->vpci ) > - /* > - * For the hardware domain it's possible to have devices assigned > - * to it that are not handled by vPCI, either because those are > - * read-only devices, or because vPCI setup has failed. > - */ > - continue; > - > - if ( tmp == pdev ) > + for_each_pdev ( d, tmp ) > { > - /* > - * Need to store the device so it's not constified and defer_map > - * can modify it in case of error. > - */ > - dev = tmp; > - if ( !rom_only ) > + if ( !tmp->vpci ) > /* > - * If memory decoding is toggled avoid checking against the > - * same device, or else all regions will be removed from the > - * memory map in the unmap case. > + * For the hardware domain it's possible to have devices > + * assigned to it that are not handled by vPCI, either > because > + * those are read-only devices, or because vPCI setup has > + * failed. > */ > continue; > - } > > - for ( i = 0; i < ARRAY_SIZE(tmp->vpci->header.bars); i++ ) > - { > - const struct vpci_bar *bar = &tmp->vpci->header.bars[i]; > - unsigned long start = PFN_DOWN(bar->addr); > - unsigned long end = PFN_DOWN(bar->addr + bar->size - 1); > - > - if ( !bar->enabled || !rangeset_overlaps_range(mem, start, end) > || > - /* > - * If only the ROM enable bit is toggled check against other > - * BARs in the same device for overlaps, but not against the > - * same ROM BAR. > - */ > - (rom_only && tmp == pdev && bar->type == VPCI_BAR_ROM) ) > - continue; > + if ( tmp == pdev ) > + { > + /* > + * Need to store the device so it's not constified and > defer_map > + * can modify it in case of error. > + */ > + dev = tmp; > + if ( !rom_only ) > + /* > + * If memory decoding is toggled avoid checking against > the > + * same device, or else all regions will be removed from > the > + * memory map in the unmap case. > + */ > + continue; > + } > > - rc = rangeset_remove_range(mem, start, end); > - if ( rc ) > + for ( i = 0; i < ARRAY_SIZE(tmp->vpci->header.bars); i++ ) > { > - printk(XENLOG_G_WARNING "Failed to remove [%lx, %lx]: %d\n", > - start, end, rc); > - rangeset_destroy(mem); > - return rc; > + const struct vpci_bar *bar = &tmp->vpci->header.bars[i]; > + unsigned long start = PFN_DOWN(bar->addr); > + unsigned long end = PFN_DOWN(bar->addr + bar->size - 1); > + > + if ( !bar->enabled || > + !rangeset_overlaps_range(mem, start, end) || > + /* > + * If only the ROM enable bit is toggled check against > + * other BARs in the same device for overlaps, but not > + * against the same ROM BAR. > + */ > + (rom_only && tmp == pdev && bar->type == VPCI_BAR_ROM) ) > + continue; > + > + rc = rangeset_remove_range(mem, start, end); > + if ( rc ) > + { > + printk(XENLOG_G_WARNING "Failed to remove [%lx, %lx]: > %d\n", > + start, end, rc); > + rangeset_destroy(mem); > + return rc; > + } > } > } > + > + if ( !is_hardware_domain(d) ) > + break; > + > + d = dom_xen; Nit: don't you want to do this in the advancement to the next iteration? Thanks, Roger.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |