[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH 07/10] ARM: vGIC: move enable status from irq_rank to struct pending_irq
Currently we store the enable bit of an interrupt in the rank structure. Remove it from there and let the MMIO emulation use the already existing GIC_IRQ_GUEST_ENABLED in the status bits of struct pending_irq. Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> --- xen/arch/arm/vgic-v2.c | 38 ++++++++++++-------------------- xen/arch/arm/vgic-v3.c | 55 ++++++++++++++++++++++------------------------ xen/arch/arm/vgic.c | 27 +++++++++++++---------- xen/include/asm-arm/vgic.h | 7 +++--- 4 files changed, 58 insertions(+), 69 deletions(-) diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c index 795173c..22c679c 100644 --- a/xen/arch/arm/vgic-v2.c +++ b/xen/arch/arm/vgic-v2.c @@ -224,20 +224,15 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, case VRANGE32(GICD_ISENABLER, GICD_ISENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD); - if ( rank == NULL) goto read_as_zero; - vgic_lock_rank(v, rank, flags); - *r = vgic_reg32_extract(rank->ienable, info); - vgic_unlock_rank(v, rank, flags); + irq = (gicd_reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto read_as_zero; + *r = vgic_reg32_extract(gather_irq_info_enabled(v, irq), info); return 1; case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD); - if ( rank == NULL) goto read_as_zero; - vgic_lock_rank(v, rank, flags); - *r = vgic_reg32_extract(rank->ienable, info); - vgic_unlock_rank(v, rank, flags); + irq = (gicd_reg - GICD_ISENABLER) * 8; + *r = vgic_reg32_extract(gather_irq_info_enabled(v, irq), info); return 1; /* Read the pending status of an IRQ via GICD is not supported */ @@ -430,24 +425,19 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, case VRANGE32(GICD_ISENABLER, GICD_ISENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER, DABT_WORD); - if ( rank == NULL) goto write_ignore; - vgic_lock_rank(v, rank, flags); - tr = rank->ienable; - vgic_reg32_setbits(&rank->ienable, r, info); - vgic_enable_irqs(v, (rank->ienable) & (~tr), rank->index); - vgic_unlock_rank(v, rank, flags); + irq = (gicd_reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto write_ignore; + tr = gather_irq_info_enabled(v, irq); + vgic_reg32_setbits(&tr, r, info); + vgic_enable_irqs(v, irq, tr); return 1; case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER, DABT_WORD); - if ( rank == NULL) goto write_ignore; - vgic_lock_rank(v, rank, flags); - tr = rank->ienable; - vgic_reg32_clearbits(&rank->ienable, r, info); - vgic_disable_irqs(v, (~rank->ienable) & tr, rank->index); - vgic_unlock_rank(v, rank, flags); + irq = (gicd_reg - GICD_ISENABLER) * 8; + tr = gather_irq_info_enabled(v, irq); + vgic_reg32_clearbits(&tr, r, info); + vgic_disable_irqs(v, irq, tr); return 1; case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN): diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c index 7989989..01764c9 100644 --- a/xen/arch/arm/vgic-v3.c +++ b/xen/arch/arm/vgic-v3.c @@ -474,8 +474,6 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, register_t *r) { struct hsr_dabt dabt = info->dabt; - struct vgic_irq_rank *rank; - unsigned long flags; unsigned int irq; switch ( reg ) @@ -487,20 +485,16 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, case VRANGE32(GICD_ISENABLER, GICD_ISENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, reg - GICD_ISENABLER, DABT_WORD); - if ( rank == NULL ) goto read_as_zero; - vgic_lock_rank(v, rank, flags); - *r = vgic_reg32_extract(rank->ienable, info); - vgic_unlock_rank(v, rank, flags); + irq = (reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto read_as_zero; + *r = vgic_reg32_extract(gather_irq_info_enabled(v, irq), info); return 1; case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN): if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, reg - GICD_ICENABLER, DABT_WORD); - if ( rank == NULL ) goto read_as_zero; - vgic_lock_rank(v, rank, flags); - *r = vgic_reg32_extract(rank->ienable, info); - vgic_unlock_rank(v, rank, flags); + irq = (reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto read_as_zero; + *r = vgic_reg32_extract(gather_irq_info_enabled(v, irq), info); return 1; /* Read the pending status of an IRQ via GICD/GICR is not supported */ @@ -550,9 +544,6 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, register_t r) { struct hsr_dabt dabt = info->dabt; - struct vgic_irq_rank *rank; - uint32_t tr; - unsigned long flags; unsigned int irq; switch ( reg ) @@ -562,26 +553,32 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, goto write_ignore_32; case VRANGE32(GICD_ISENABLER, GICD_ISENABLERN): + { + uint32_t new_reg, tr; + if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, reg - GICD_ISENABLER, DABT_WORD); - if ( rank == NULL ) goto write_ignore; - vgic_lock_rank(v, rank, flags); - tr = rank->ienable; - vgic_reg32_setbits(&rank->ienable, r, info); - vgic_enable_irqs(v, (rank->ienable) & (~tr), rank->index); - vgic_unlock_rank(v, rank, flags); + irq = (reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto write_ignore; + new_reg = gather_irq_info_enabled(v, irq); + tr = new_reg; + vgic_reg32_setbits(&new_reg, r, info); + vgic_enable_irqs(v, irq, new_reg & (~tr)); return 1; + } case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN): + { + uint32_t new_reg, tr; + if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 1, reg - GICD_ICENABLER, DABT_WORD); - if ( rank == NULL ) goto write_ignore; - vgic_lock_rank(v, rank, flags); - tr = rank->ienable; - vgic_reg32_clearbits(&rank->ienable, r, info); - vgic_disable_irqs(v, (~rank->ienable) & tr, rank->index); - vgic_unlock_rank(v, rank, flags); + irq = (reg - GICD_ISENABLER) * 8; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto write_ignore; + new_reg = gather_irq_info_enabled(v, irq); + tr = new_reg; + vgic_reg32_clearbits(&new_reg, r, info); + vgic_disable_irqs(v, irq, (~new_reg) & tr); return 1; + } case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN): if ( dabt.size != DABT_WORD ) goto bad_width; diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index 02c1d12..a23079a 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -235,6 +235,11 @@ static void set_priority(struct pending_irq *p, uint8_t prio) p->new_priority = prio; } +unsigned int extract_enabled(struct pending_irq *p) +{ + return test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) ? 1 : 0; +} + unsigned int extract_config(struct pending_irq *p) { return test_bit(GIC_IRQ_GUEST_EDGE, &p->status) ? 2 : 0; @@ -280,6 +285,7 @@ void scatter_irq_info_##name(struct vcpu *v, unsigned int irq, \ /* grep fodder: gather_irq_info_priority, scatter_irq_info_priority below */ DEFINE_GATHER_IRQ_INFO(priority, extract_priority, 8) DEFINE_SCATTER_IRQ_INFO(priority, set_priority, 8) +DEFINE_GATHER_IRQ_INFO(enabled, extract_enabled, 1) DEFINE_GATHER_IRQ_INFO(config, extract_config, 2) DEFINE_SCATTER_IRQ_INFO(config, set_config, 2) @@ -347,21 +353,19 @@ void arch_move_irqs(struct vcpu *v) } } -void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n) +void vgic_disable_irqs(struct vcpu *v, unsigned int irq, uint32_t r) { const unsigned long mask = r; struct pending_irq *p; - unsigned int irq; unsigned long flags; int i = 0; struct vcpu *v_target; while ( (i = find_next_bit(&mask, 32, i)) < 32 ) { - irq = i + (32 * n); - v_target = vgic_get_target_vcpu(v, irq); - p = irq_to_pending(v_target, irq); + v_target = vgic_get_target_vcpu(v, irq + i); + p = irq_to_pending(v_target, irq + i); clear_bit(GIC_IRQ_GUEST_ENABLED, &p->status); - gic_remove_from_queues(v_target, irq); + gic_remove_from_queues(v_target, irq + i); if ( p->desc != NULL ) { spin_lock_irqsave(&p->desc->lock, flags); @@ -372,22 +376,21 @@ void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n) } } -void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n) +void vgic_enable_irqs(struct vcpu *v, unsigned int irq, uint32_t r) { const unsigned long mask = r; struct pending_irq *p; - unsigned int irq, int_type; + unsigned int int_type; unsigned long flags; int i = 0; struct vcpu *v_target; struct domain *d = v->domain; while ( (i = find_next_bit(&mask, 32, i)) < 32 ) { - irq = i + (32 * n); - v_target = vgic_get_target_vcpu(v, irq); + v_target = vgic_get_target_vcpu(v, irq + i); spin_lock_irqsave(&v_target->arch.vgic.lock, flags); - p = irq_to_pending(v_target, irq); + p = irq_to_pending(v_target, irq + i); spin_lock(&p->lock); set_bit(GIC_IRQ_GUEST_ENABLED, &p->status); @@ -406,7 +409,7 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n) * The irq cannot be a PPI, we only support delivery of SPIs * to guests. */ - ASSERT(irq >= 32); + ASSERT(irq + i >= 32); if ( irq_type_set_by_domain(d) ) gic_set_irq_type(p->desc, int_type); p->desc->handler->enable(p->desc); diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h index 931a672..fe09fb8 100644 --- a/xen/include/asm-arm/vgic.h +++ b/xen/include/asm-arm/vgic.h @@ -104,8 +104,6 @@ struct vgic_irq_rank { uint8_t index; - uint32_t ienable; - /* * It's more convenient to store a target VCPU per vIRQ * than the register ITARGETSR/IROUTER itself. @@ -178,6 +176,7 @@ void scatter_irq_info_priority(struct vcpu *v, unsigned int irq, uint32_t gather_irq_info_config(struct vcpu *v, unsigned int irq); void scatter_irq_info_config(struct vcpu *v, unsigned int irq, unsigned int value); +uint32_t gather_irq_info_enabled(struct vcpu *v, unsigned int irq); #define VGIC_REG_MASK(size) ((~0UL) >> (BITS_PER_LONG - ((1 << (size)) * 8))) @@ -311,8 +310,8 @@ extern struct pending_irq *spi_to_pending(struct domain *d, unsigned int irq); extern struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n, int s); extern struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq); extern bool vgic_emulate(struct cpu_user_regs *regs, union hsr hsr); -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 void vgic_disable_irqs(struct vcpu *v, unsigned int irq, uint32_t r); +extern void vgic_enable_irqs(struct vcpu *v, unsigned int irq, uint32_t r); 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.9.0 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |