On Wed, Feb 02, 2022 at 09:46:21AM +0000, Oleksandr Andrushchenko wrote:
>
> >>> + gdprintk(XENLOG_G_DEBUG,
> >>> + "%smap [%lx, %lx] -> %#"PRI_gfn" for %pd\n",
> >>> + map->map ? "" : "un", s, e, gfn_x(start_gfn),
> >>> + map->d);
> >> That's too chatty IMO, I could be fine with printing something along
> >> this lines from modify_bars, but not here because that function can be
> >> preempted and called multiple times.
> > Ok, will move to modify_bars as these prints are really helpful for debug
> I tried to implement the same, but now in init_bars:
>
> diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c
> index 667c04cee3ae..92407e617609 100644
> --- a/xen/drivers/vpci/header.c
> +++ b/xen/drivers/vpci/header.c
> @@ -57,10 +57,6 @@ static int map_range(unsigned long s, unsigned long e,
> void *data,
> */
> start_gfn = gfn_add(start_gfn, s - mfn_x(start_mfn));
>
> - gdprintk(XENLOG_G_DEBUG,
> - "%smap [%lx, %lx] -> %#"PRI_gfn" for %pd\n",
> - map->map ? "" : "un", s, e, gfn_x(start_gfn),
> - map->d);
> /*
> * ARM TODOs:
> * - On ARM whether the memory is prefetchable or not should be
> passed
> @@ -258,6 +254,28 @@ static void defer_map(struct domain *d, struct pci_dev
> *pdev,
> raise_softirq(SCHEDULE_SOFTIRQ);
> }
>
> +static int print_range(unsigned long s, unsigned long e, void *data)
> +{
> + const struct map_data *map = data;
> +
> + for ( ; ; )
> + {
> + gfn_t start_gfn = _gfn(PFN_DOWN(is_hardware_domain(map->d)
> + ? map->bar->addr
> + : map->bar->guest_reg));
> + mfn_t start_mfn = _mfn(PFN_DOWN(map->bar->addr));
> +
> + start_gfn = gfn_add(start_gfn, s - mfn_x(start_mfn));
> +
> + gdprintk(XENLOG_G_DEBUG,
> + "%smap [%lx, %lx] -> %#"PRI_gfn" for %pd\n",
> + map->map ? "" : "un", s, e, gfn_x(start_gfn),
> + map->d);
> + }
This is an infinite loop AFAICT. Why do you need the for for?
> +
> + return 0;
> +}
> +
> static int modify_bars(const struct pci_dev *pdev, uint16_t cmd, bool
> rom_only)
> {
> struct vpci_header *header = &pdev->vpci->header;
> @@ -423,7 +441,25 @@ static int modify_bars(const struct pci_dev *pdev,
> uint16_t cmd, bool rom_only)
> if ( !map_pending )
> pci_conf_write16(pdev->sbdf, PCI_COMMAND, cmd);
> else
> + {
> + struct map_data data = {
> + .d = pdev->domain,
> + .map = cmd & PCI_COMMAND_MEMORY,
> + };
> +
> + for ( i = 0; i < ARRAY_SIZE(header->bars); i++ )
> + {
> + const struct vpci_bar *bar = &header->bars[i];
> +
> + if ( rangeset_is_empty(bar->mem) )
> + continue;
> +
> + data.bar = bar;
> + rc = rangeset_report_ranges(bar->mem, 0, ~0ul, print_range,
> &data);
Since this is per-BAR we should also print that information and the
SBDF of the device, ie:
%pd SBDF: (ROM)BAR%u %map [%lx, %lx] -> ...
> + }
> +
> defer_map(dev->domain, dev, cmd, rom_only);
> + }
>
> return 0;
>
>
> To me, to implement a single DEBUG print, it is a bit an overkill.
> I do understand your concerns that "that function can be
> preempted and called multiple times", but taking look at the code
> above I think we can accept that for DEBUG builds.
It might be better if you print the per BAR positions at the top of
modify_bars, where each BAR is added to the rangeset? Or do you care
about reporting the holes also?
Thanks, Roger.