|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v8 07/11] vpci/bars: add handlers to map the BARs
(re-sending with xen-devel re-added; not sure how it got lost)
>>> On 23.01.18 at 16:07, <roger.pau@xxxxxxxxxx> wrote:
> ---
> tools/tests/vpci/emul.h | 1 +
> xen/arch/x86/hvm/ioreq.c | 4 +
Again the Cc to Paul is missing (no matter that it's just a tiny change).
> +static int map_range(unsigned long s, unsigned long e, void *data,
> + unsigned long *c)
> +{
> + const struct map_data *map = data;
> + int rc;
> +
> + for ( ; ; )
> + {
> + unsigned long size = e - s + 1;
Considering the lack of a condition in the for() and the inclusiveness
of the range (which means you can't express an empty range) I don't
understand how ...
> + /*
> + * ARM TODOs:
> + * - On ARM whether the memory is prefetchable or not should be
> passed
> + * to map_mmio_regions in order to decide which memory attributes
> + * should be used.
> + *
> + * - {un}map_mmio_regions doesn't support preemption, hence the bodge
> + * below in order to limit the amount of mappings to 64 pages for
> + * each function call.
> + */
> +
> +#ifdef CONFIG_ARM
> + size = min(64ul, size);
> +#endif
> +
> + rc = (map->map ? map_mmio_regions : unmap_mmio_regions)
> + (map->d, _gfn(s), size, _mfn(s));
> + if ( rc == 0 )
> + {
> + *c += size;
> +#ifdef CONFIG_ARM
> + rc = -ERESTART;
> +#endif
> + break;
... this works in the ARM case. If the whole thing doesn't work (and
doesn't get built) for ARM right now, make this obvious by one or more
#error directives.
> +static void modify_decoding(const struct pci_dev *pdev, bool map, bool rom)
> +{
> + struct vpci_header *header = &pdev->vpci->header;
> + uint8_t slot = PCI_SLOT(pdev->devfn), func = PCI_FUNC(pdev->devfn);
> + unsigned int i;
> +
> + for ( i = 0; i < ARRAY_SIZE(header->bars); i++ )
> + {
> + if ( rom && header->bars[i].type == VPCI_BAR_ROM )
> + {
> + unsigned int rom_pos = (i == 6) ? PCI_ROM_ADDRESS
I probably should have mentioned this earlier, but I'm really unhappy
about such literal "magic" numbers. Please use a suitable expression
or #define.
> +bool vpci_process_pending(struct vcpu *v)
> +{
> + while ( v->vpci.mem )
> + {
> + struct map_data data = {
> + .d = v->domain,
> + .map = v->vpci.map,
> + };
> +
> + switch ( rangeset_consume_ranges(v->vpci.mem, map_range, &data) )
> + {
> + case -ERESTART:
> + return true;
> +
> + default:
> + if ( v->vpci.map )
> + {
> + spin_lock(&v->vpci.pdev->vpci->lock);
> + modify_decoding(v->vpci.pdev, v->vpci.map, v->vpci.rom);
> + spin_unlock(&v->vpci.pdev->vpci->lock);
> + }
> + /* fallthrough. */
> + case -ENOMEM:
You carefully handle this error here.
> +static void maybe_defer_map(struct domain *d, const struct pci_dev *pdev,
> + struct rangeset *mem, bool map, bool rom)
> +{
> + struct vcpu *curr = current;
> +
> + if ( is_idle_vcpu(curr) )
> + {
> + struct map_data data = { .d = d, .map = true };
> +
> + /*
> + * Only used for domain construction in order to map the BARs
> + * of devices with memory decoding enabled.
> + */
> + ASSERT(map && !rom);
> + rangeset_consume_ranges(mem, map_range, &data);
What if this produces -ENOMEM? And despite having looked at
several revisions of this, I can't make the connection to why this
is in an is_idle_vcpu() conditional (neither the direct caller nor the
next level up make this obvious to me). There's clearly a need
for extending the comment.
> +static void modify_bars(const struct pci_dev *pdev, bool map, bool rom)
> +{
> + struct vpci_header *header = &pdev->vpci->header;
> + struct rangeset *mem = rangeset_new(NULL, NULL, 0);
> + const struct pci_dev *tmp;
> + unsigned int i;
> + int rc;
> +
> + if ( !map )
> + modify_decoding(pdev, false, rom);
> +
> + if ( !mem )
> + return;
Similarly here - why is it okay (or what effect will it have) to return
here when we're out of memory, but the caller won't know?
> + /*
> + * Create a rangeset that represents the current device BARs memory
> region
> + * and compare it against all the currently active BAR memory regions. If
> + * an overlap is found, subtract it from the region to be
> + * mapped/unmapped.
> + *
> + * NB: the rangeset uses inclusive frame numbers.
> + */
> +
> + /*
> + * First fill the rangeset with all the BARs of this device or with the
> ROM
> + * BAR only, depending on whether the guest is toggling the memory decode
> + * bit of the command register, or the enable bit of the ROM BAR
> register.
> + */
> + for ( i = 0; i < ARRAY_SIZE(header->bars); i++ )
> + {
> + const struct vpci_bar *bar = &header->bars[i];
> +
> + if ( !MAPPABLE_BAR(bar) ||
> + (rom ? bar->type != VPCI_BAR_ROM
> + : (bar->type == VPCI_BAR_ROM && !header->rom_enabled)) )
> + continue;
Why does rom_enabled matter for the !rom case rather than for
the rom one? I.e.
if ( !MAPPABLE_BAR(bar) ||
(rom ? bar->type != VPCI_BAR_ROM || !header->rom_enabled
: bar->type == VPCI_BAR_ROM) )
continue;
?
> + rc = rangeset_add_range(mem, PFN_DOWN(bar->addr),
> + PFN_UP(bar->addr + bar->size - 1));
> + if ( rc )
> + {
> + printk(XENLOG_G_WARNING
> + "Failed to add [%" PRI_gfn ", %" PRI_gfn "): %d\n",
> + PFN_DOWN(bar->addr), PFN_UP(bar->addr + bar->size - 1),
Either you use [a,b) and don't subtract 1, or you use [a,b] with the
subtraction. Same below.
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |