[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2] xen/arm: implement GICD_I[S/C]ACTIVER reads
This is a simple implementation of GICD_ICACTIVER / GICD_ISACTIVER reads. It doesn't take into account the latest state of interrupts on other vCPUs. Only the current vCPU is up-to-date. A full solution is not possible because it would require synchronization among all vCPUs, which would be very expensive in terms or latency. Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxx> CC: Wei Xu <xuwei5@xxxxxxxxxxxxx> CC: Peng Fan <peng.fan@xxxxxxx> --- Changes in v2: - improve commit message - do not invert result - use 1U - use common patter with vgic_rank_offset - move implementation into a separate function called vgic_isactiver - add vgic2 implementation - tested on vgic2 by hacking the Linux gicv2 driver --- xen/arch/arm/vgic-v2.c | 13 +++++++++++-- xen/arch/arm/vgic-v3.c | 15 ++++++++++++--- xen/arch/arm/vgic.c | 20 ++++++++++++++++++++ xen/include/asm-arm/vgic.h | 1 + 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c index 64b141fea5..454408d11d 100644 --- a/xen/arch/arm/vgic-v2.c +++ b/xen/arch/arm/vgic-v2.c @@ -245,10 +245,19 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, case VRANGE32(GICD_ICPENDR, GICD_ICPENDRN): goto read_as_zero; - /* Read the active status of an IRQ via GICD is not supported */ case VRANGE32(GICD_ISACTIVER, GICD_ISACTIVERN): + if ( dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER, DABT_WORD); + if ( rank == NULL ) goto read_as_zero; + *r = vgic_isactiver(v, 32 * rank->index); + return 1; + case VRANGE32(GICD_ICACTIVER, GICD_ICACTIVERN): - goto read_as_zero; + if ( dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER, DABT_WORD); + if ( rank == NULL ) goto read_as_zero; + *r = vgic_isactiver(v, 32 * rank->index); + return 1; case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): { diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c index 4e60ba15cc..a2cd39c45d 100644 --- a/xen/arch/arm/vgic-v3.c +++ b/xen/arch/arm/vgic-v3.c @@ -712,10 +712,19 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, case VRANGE32(GICD_ICPENDR, GICD_ICPENDR): goto read_as_zero; - /* Read the active status of an IRQ via GICD/GICR is not supported */ - case VRANGE32(GICD_ISACTIVER, GICD_ISACTIVER): + case VRANGE32(GICD_ISACTIVER, GICD_ISACTIVERN): + if ( dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 1, reg - GICD_ISACTIVER, DABT_WORD); + if ( rank == NULL ) goto read_as_zero; + *r = vgic_isactiver(v, 32 * rank->index); + return 1; + case VRANGE32(GICD_ICACTIVER, GICD_ICACTIVERN): - goto read_as_zero; + if ( dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 1, reg - GICD_ICACTIVER, DABT_WORD); + if ( rank == NULL ) goto read_as_zero; + *r = vgic_isactiver(v, 32 * rank->index); + return 1; case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): { diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 82f524a35c..d491fa38a5 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -423,6 +423,26 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n) } } +uint32_t vgic_isactiver(struct vcpu *v, unsigned int start_irq) +{ + struct pending_irq *p; + unsigned int irq; + uint32_t r = 0; + + /* + * The following won't reflect the latest status of interrupts on + * other vcpus. + */ + for ( irq = start_irq; irq < start_irq + 32; irq++ ) + { + p = irq_to_pending(v, irq); + if ( p != NULL && test_bit(GIC_IRQ_GUEST_ACTIVE, &p->status) ) + r |= 1U << (irq - start_irq); + } + + return r; +} + bool vgic_to_sgi(struct vcpu *v, register_t sgir, enum gic_sgi_mode irqmode, int virq, const struct sgi_target *target) { diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h index ce1e3c4bbd..a9e3f2fa60 100644 --- a/xen/include/asm-arm/vgic.h +++ b/xen/include/asm-arm/vgic.h @@ -288,6 +288,7 @@ extern struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n, int extern struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq); extern void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n); extern void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n); +extern uint32_t vgic_isactiver(struct vcpu *v, unsigned int start_irq); extern void register_vgic_ops(struct domain *d, const struct vgic_ops *ops); int vgic_v2_init(struct domain *d, int *mmio_count); int vgic_v3_init(struct domain *d, int *mmio_count); -- 2.17.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |