[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v9 04/28] ARM: GICv3: introduce separate pending_irq structs for LPIs
On Thu, 11 May 2017, Andre Przywara wrote: > For the same reason that allocating a struct irq_desc for each > possible LPI is not an option, having a struct pending_irq for each LPI > is also not feasible. We only care about mapped LPIs, so we can get away > with having struct pending_irq's only for them. > Maintain a radix tree per domain where we drop the pointer to the > respective pending_irq. The index used is the virtual LPI number. > The memory for the actual structures has been allocated already per > device at device mapping time. > Teach the existing VGIC functions to find the right pointer when being > given a virtual LPI number. > > Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> Reviewed-by: Stefano Stabellini <sstabellini@xxxxxxxxxx> > --- > xen/arch/arm/vgic-v2.c | 8 ++++++++ > xen/arch/arm/vgic-v3.c | 30 ++++++++++++++++++++++++++++++ > xen/arch/arm/vgic.c | 2 ++ > xen/include/asm-arm/domain.h | 2 ++ > xen/include/asm-arm/vgic.h | 2 ++ > 5 files changed, 44 insertions(+) > > diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c > index dc9f95b..0587569 100644 > --- a/xen/arch/arm/vgic-v2.c > +++ b/xen/arch/arm/vgic-v2.c > @@ -702,10 +702,18 @@ static void vgic_v2_domain_free(struct domain *d) > /* Nothing to be cleanup for this driver */ > } > > +static struct pending_irq *vgic_v2_lpi_to_pending(struct domain *d, > + unsigned int vlpi) > +{ > + /* Dummy function, no LPIs on a VGICv2. */ > + BUG(); > +} > + > static const struct vgic_ops vgic_v2_ops = { > .vcpu_init = vgic_v2_vcpu_init, > .domain_init = vgic_v2_domain_init, > .domain_free = vgic_v2_domain_free, > + .lpi_to_pending = vgic_v2_lpi_to_pending, > .max_vcpus = 8, > }; > > diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c > index 25e16dc..44d2b50 100644 > --- a/xen/arch/arm/vgic-v3.c > +++ b/xen/arch/arm/vgic-v3.c > @@ -1454,6 +1454,9 @@ static int vgic_v3_domain_init(struct domain *d) > d->arch.vgic.nr_regions = rdist_count; > d->arch.vgic.rdist_regions = rdist_regions; > > + rwlock_init(&d->arch.vgic.pend_lpi_tree_lock); > + radix_tree_init(&d->arch.vgic.pend_lpi_tree); > + > /* > * Domain 0 gets the hardware address. > * Guests get the virtual platform layout. > @@ -1535,14 +1538,41 @@ static int vgic_v3_domain_init(struct domain *d) > static void vgic_v3_domain_free(struct domain *d) > { > vgic_v3_its_free_domain(d); > + /* > + * It is expected that at this point all actual ITS devices have been > + * cleaned up already. The struct pending_irq's, for which the pointers > + * have been stored in the radix tree, are allocated and freed by device. > + * On device unmapping all the entries are removed from the tree and > + * the backing memory is freed. > + */ > + radix_tree_destroy(&d->arch.vgic.pend_lpi_tree, NULL); > xfree(d->arch.vgic.rdist_regions); > } > > +/* > + * Looks up a virtual LPI number in our tree of mapped LPIs. This will return > + * the corresponding struct pending_irq, which we also use to store the > + * enabled and pending bit plus the priority. > + * Returns NULL if an LPI cannot be found (or no LPIs are supported). > + */ > +static struct pending_irq *vgic_v3_lpi_to_pending(struct domain *d, > + unsigned int lpi) > +{ > + struct pending_irq *pirq; > + > + read_lock(&d->arch.vgic.pend_lpi_tree_lock); > + pirq = radix_tree_lookup(&d->arch.vgic.pend_lpi_tree, lpi); > + read_unlock(&d->arch.vgic.pend_lpi_tree_lock); > + > + return pirq; > +} > + > static const struct vgic_ops v3_ops = { > .vcpu_init = vgic_v3_vcpu_init, > .domain_init = vgic_v3_domain_init, > .domain_free = vgic_v3_domain_free, > .emulate_reg = vgic_v3_emulate_reg, > + .lpi_to_pending = vgic_v3_lpi_to_pending, > /* > * We use both AFF1 and AFF0 in (v)MPIDR. Thus, the max number of CPU > * that can be supported is up to 4096(==256*16) in theory. > diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c > index 8a5d93b..bf6fb60 100644 > --- a/xen/arch/arm/vgic.c > +++ b/xen/arch/arm/vgic.c > @@ -457,6 +457,8 @@ struct pending_irq *irq_to_pending(struct vcpu *v, > unsigned int irq) > * are used for SPIs; the rests are used for per cpu irqs */ > if ( irq < 32 ) > n = &v->arch.vgic.pending_irqs[irq]; > + else if ( is_lpi(irq) ) > + n = v->domain->arch.vgic.handler->lpi_to_pending(v->domain, irq); > else > n = &v->domain->arch.vgic.pending_irqs[irq - 32]; > return n; > diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h > index 7c3829d..3d8e84c 100644 > --- a/xen/include/asm-arm/domain.h > +++ b/xen/include/asm-arm/domain.h > @@ -111,6 +111,8 @@ struct arch_domain > uint32_t rdist_stride; /* Re-Distributor stride */ > struct rb_root its_devices; /* Devices mapped to an ITS */ > spinlock_t its_devices_lock; /* Protects the its_devices tree > */ > + struct radix_tree_root pend_lpi_tree; /* Stores struct pending_irq's > */ > + rwlock_t pend_lpi_tree_lock; /* Protects the pend_lpi_tree */ > unsigned int intid_bits; > #endif > } vgic; > diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h > index df75064..c9075a9 100644 > --- a/xen/include/asm-arm/vgic.h > +++ b/xen/include/asm-arm/vgic.h > @@ -134,6 +134,8 @@ struct vgic_ops { > void (*domain_free)(struct domain *d); > /* vGIC sysreg/cpregs emulate */ > bool (*emulate_reg)(struct cpu_user_regs *regs, union hsr hsr); > + /* lookup the struct pending_irq for a given LPI interrupt */ > + struct pending_irq *(*lpi_to_pending)(struct domain *d, unsigned int > vlpi); > /* Maximum number of vCPU supported */ > const unsigned int max_vcpus; > }; > -- > 2.9.0 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxx > https://lists.xen.org/xen-devel > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |