[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v9 15/28] ARM: vITS: provide access to struct pending_irq
Hi Andre, On 11/05/17 18:53, Andre Przywara wrote: For each device we allocate one struct pending_irq for each virtual event (MSI). Provide a helper function which returns the pointer to the appropriate struct, to be able to find the right struct when given a virtual deviceID/eventID pair. Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> --- xen/arch/arm/gic-v3-its.c | 69 ++++++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/gic_v3_its.h | 4 +++ 2 files changed, 73 insertions(+) diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c index aebc257..fd6a394 100644 --- a/xen/arch/arm/gic-v3-its.c +++ b/xen/arch/arm/gic-v3-its.c @@ -800,6 +800,75 @@ out: return ret; } +/* Must be called with the its_device_lock held. */ +static struct its_device *get_its_device(struct domain *d, paddr_t vdoorbell, + uint32_t vdevid) +{ + struct rb_node *node = d->arch.vgic.its_devices.rb_node; + struct its_device *dev; + + ASSERT(spin_is_locked(&d->arch.vgic.its_devices_lock)); + + while (node) + { + int cmp; + + dev = rb_entry(node, struct its_device, rbnode); + cmp = compare_its_guest_devices(dev, vdoorbell, vdevid); + + if ( !cmp ) + return dev; + + if ( cmp > 0 ) + node = node->rb_left; + else + node = node->rb_right; + } + + return NULL; +} + +static uint32_t get_host_lpi(struct its_device *dev, uint32_t eventid) +{ + uint32_t host_lpi = INVALID_LPI; + + if ( dev && (eventid < dev->eventids) ) + host_lpi = dev->host_lpi_blocks[eventid / LPI_BLOCK] + + (eventid % LPI_BLOCK); + + return host_lpi; IHMO, it would be easier to read if you invert the condition: if ( !dev || (eventid >= dev->eventids) ) return INVALID_LPI; return dev->host_lpi_blocks[eventid / LPI_BLOCK] + (eventid % LPI_BLOCK);Also, whilst I agree about sanitizing eventid, someone calling this function with dev = NULL is already wrong. Defensive programming is good, but there are some place where I don't think it is necessary. You have to trust a bit the caller, otherwise you will end up making the check 10 times before accessing it. +} + +static struct pending_irq *get_event_pending_irq(struct domain *d, + paddr_t vdoorbell_address, + uint32_t vdevid, + uint32_t veventid, s/veventid/ as it is not virtual a virtual one and make the call to get_host_lpi fairly confusing. + uint32_t *host_lpi) +{ + struct its_device *dev; + struct pending_irq *pirq = NULL; + + spin_lock(&d->arch.vgic.its_devices_lock); + dev = get_its_device(d, vdoorbell_address, vdevid); + if ( dev && veventid <= dev->eventids ) Why are you using "<=" here and not "<" like in get_host_lpi? Surely one of them is wrong. + { + pirq = &dev->pend_irqs[veventid]; + if ( host_lpi ) + *host_lpi = get_host_lpi(dev, veventid); Getting the host_lpi is fairly cheap. I would impose to pass host_lpi. This would also avoid multiple check on the eventid as you currently do. I.e dev = ... if ( !dev ) goto out; *host_lpi = get_host_lpi(dev, ...); if ( *host_lpi == INVALID_LPI ) goto out; pirq = &dev->pend_irqs[veventid]; out: spin_unlock(...) return pirq; + } + spin_unlock(&d->arch.vgic.its_devices_lock); + + return pirq; +} + +struct pending_irq *gicv3_its_get_event_pending_irq(struct domain *d, + paddr_t vdoorbell_address, + uint32_t vdevid, + uint32_t veventid) s/veventid/eventid/ +{ + return get_event_pending_irq(d, vdoorbell_address, vdevid, veventid, NULL); +} This wrapper looks a bit pointless to me. Why don't you directly expose get_event_pending_irq(...)? + /* Scan the DT for any ITS nodes and create a list of host ITSes out of it. */ void gicv3_its_dt_init(const struct dt_device_node *node) { diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h index 40f4ef5..d162e89 100644 --- a/xen/include/asm-arm/gic_v3_its.h +++ b/xen/include/asm-arm/gic_v3_its.h @@ -169,6 +169,10 @@ int gicv3_its_map_guest_device(struct domain *d, int gicv3_allocate_host_lpi_block(struct domain *d, uint32_t *first_lpi); void gicv3_free_host_lpi_block(uint32_t first_lpi); +struct pending_irq *gicv3_its_get_event_pending_irq(struct domain *d, + paddr_t vdoorbell_address, + uint32_t vdevid, + uint32_t veventid); #else static inline void gicv3_its_dt_init(const struct dt_device_node *node) Cheers, -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |