[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v1 6/8] xen/arm: vgic: Optimize the way to store the target vCPU in the rank
On Fri, 2015-09-25 at 15:51 +0100, Julien Grall wrote: > Xen is currently directly storing the value of register GICD_ITARGETSR > (for GICv2) and GICD_IROUTER (for GICv3) in the rank. This makes the > emulation of the registers access very simple but makes the code to get > the target vCPU for a given IRQ more complex. > > While the target vCPU of an IRQ is retrieved everytime an IRQ is > injected to the guest, the access to the register occurs less often. > > So the data structure should be optimized for the most common case > rather than the inverse. > > This patch introduce the usage of an array to store the target vCPU for > every interrupt in the rank. This will make the code to get the target > very quick. The emulation code will now have to generate the > GICD_ITARGETSR > and GICD_IROUTER register for read access and split it to store in a > convenient way. > > Note that with these changes, any read to those registers will list only > the target vCPU used by Xen. This is fine because the GIC spec doesn't > require to return exactly the value written and it can be seen as if we > decide to implement the register read-only. I think this is probably OK, but skirting round what the spec actually says a fair bit. > Finally take the opportunity to fix coding style in section we are > modifying. > > Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx> > > --- > The real reason is I'd like to drop vgic_byte_* helpers in favor of > more > generic access helpers. Although it would make the code to retrieve > the > priority more complex. So reworking the code to get the target vCPU > was the best solution. > > Changes in v2: > - Patch added > --- > xen/arch/arm/vgic-v2.c | 172 ++++++++++++++++++++++++++------------- > ------ > xen/arch/arm/vgic-v3.c | 121 +++++++++++++++++-------------- > xen/arch/arm/vgic.c | 28 ++++++-- > xen/include/asm-arm/vgic.h | 13 ++-- > 4 files changed, 197 insertions(+), 137 deletions(-) > > diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c > index 23d1982..b6db64f 100644 > --- a/xen/arch/arm/vgic-v2.c > +++ b/xen/arch/arm/vgic-v2.c > @@ -50,6 +50,90 @@ void vgic_v2_setup_hw(paddr_t dbase, paddr_t cbase, > paddr_t vbase) > vgic_v2_hw.vbase = vbase; > } > > +#define NR_TARGET_PER_REG 4U > +#define NR_BIT_PER_TARGET 8U > + > +/* > + * Generate the associated ITARGETSR register based on the offset from > + * ITARGETSR0. Only one vCPU will be listed for a given IRQ. > + * > + * Note the offset will be round down to match a real HW register. "rounded down". Although I'm not 100% sure what that comment is trying to say. From the code I think you mean aligned to the appropriate 4 byte boundary? > + */ > +static uint32_t vgic_generate_itargetsr(struct vgic_irq_rank *rank, For all these why not s/generate/read/? Or since you use "store" for the other half "fetch". ("generate" is a bit of an implementation detail, the caller doesn't care where or how the result is achieved) > + unsigned int offset) > +{ > + uint32_t reg = 0; > + unsigned int i; > + > + ASSERT(spin_is_locked(&rank->lock)); > + > + offset &= INTERRUPT_RANK_MASK; > + offset &= ~(NR_TARGET_PER_REG - 1); > + > + for ( i = 0; i < NR_TARGET_PER_REG; i++, offset++ ) > + reg |= (1 << rank->vcpu[offset]) << (i * NR_BIT_PER_TARGET); > + > + return reg; > +} > + > +/* > + * Store a ITARGETSR register in a convenient way and migrate the IRQ > + * if necessary. > + * Note the offset will be round down to match a real HW register. As above. > + */ > +static void vgic_store_itargetsr(struct domain *d, struct vgic_irq_rank > *rank, > + unsigned int offset, uint32_t > itargetsr) > +{ > + unsigned int i, rank_idx; > + > + ASSERT(spin_is_locked(&rank->lock)); > + > + rank_idx = offset / NR_INTERRUPT_PER_RANK; > + > + offset &= INTERRUPT_RANK_MASK; > + offset &= ~(NR_TARGET_PER_REG - 1); > + > + for ( i = 0; i < NR_TARGET_PER_REG; i++, offset++ ) > + { > + unsigned int new_target, old_target; > + > + /* > + * SPI are using the 1-N model (see 1.4.3 in ARM IHI 0048B). > + * While the interrupt could be set pending to all the vCPUs in > + * target list, it's not guarantee by the spec. > + * For simplicity, always route the IRQ to the first interrupt > + * in the target list > + */ I don't see anything which is handling the PPI and SGI special case (which is that they are r/o). Likewise on read they are supposed to always reflect the value of the CPU doing the read. Are both of those handled elsewhere in some way I'm missing? [...] > + * Note the offset will be round down to match a real HW register As earlier. > + * Note the offset will be round down to match a real HW register. Again. > + */ > +static void vgic_store_irouter(struct domain *d, struct vgic_irq_rank > *rank, > + unsigned int offset, uint64_t irouter) > +{ > + struct vcpu *new_vcpu, *old_vcpu; > + unsigned int rank_idx, irq; > + > + > + /* There is 1 IRQ per IROUTER */ > + irq = offset / NR_BYTE_PER_IROUTER; > + > + rank_idx = irq / NR_INTERRUPT_PER_RANK; > + > + /* Get the index in the rank */ > + offset &= irq & INTERRUPT_RANK_MASK; > + > + new_vcpu = vgic_v3_irouter_to_vcpu(d, irouter); > + old_vcpu = d->vcpu[rank->vcpu[offset]]; > + > + /* > + * From the spec (see 8.9.13 in IHI 0069A), any write with an > + * invalid vCPU will lead to ignore the interrupt. "to the interrupt being ignored" > static struct vcpu *vgic_v3_get_target_vcpu(struct vcpu *v, unsigned int > irq) > { > - struct vcpu *v_target; > struct vgic_irq_rank *rank = vgic_rank_irq(v, irq); > > ASSERT(spin_is_locked(&rank->lock)); > > - v_target = vgic_v3_irouter_to_vcpu(v->domain, rank->v3.irouter[irq % > 32]); > - > - ASSERT(v_target != NULL); > - > - return v_target; > + return v->domain->vcpu[rank->vcpu[irq & INTERRUPT_RANK_MASK]]; Looks like there isn't much call for this to be specific to a given revision of the gic any more? Are there sufficient checks for the range of rank->vcpu[...] elsewhere that we needn't worry about running of domain->vcpu[] here? Ian. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |