[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH v2 14/22] ARM: vGIC: move virtual IRQ configuration from rank to pending_irq
The IRQ configuration (level or edge triggered) for a group of IRQs are still stored in the irq_rank structure. Introduce a new bit called GIC_IRQ_GUEST_LEVEL in the "status" field, which holds that information. Remove the storage from the irq_rank and use the existing wrappers to store and retrieve the configuration bit for multiple IRQs. Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> --- xen/arch/arm/vgic-v2.c | 21 +++--------- xen/arch/arm/vgic-v3.c | 25 ++++---------- xen/arch/arm/vgic.c | 81 +++++++++++++++++++++++++++++++++------------- xen/include/asm-arm/vgic.h | 5 ++- 4 files changed, 73 insertions(+), 59 deletions(-) diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c index a3fd500..0c8a598 100644 --- a/xen/arch/arm/vgic-v2.c +++ b/xen/arch/arm/vgic-v2.c @@ -278,20 +278,12 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, goto read_reserved; case VRANGE32(GICD_ICFGR, GICD_ICFGRN): - { - uint32_t icfgr; - if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR, DABT_WORD); - if ( rank == NULL) goto read_as_zero; - vgic_lock_rank(v, rank, flags); - icfgr = rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)]; - vgic_unlock_rank(v, rank, flags); - *r = vreg_reg32_extract(icfgr, info); + irq = (gicd_reg - GICD_ICFGR) * 4; + *r = vgic_fetch_irq_config(v, irq); return 1; - } case VRANGE32(0xD00, 0xDFC): goto read_impl_defined; @@ -529,13 +521,8 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, case VRANGE32(GICD_ICFGR2, GICD_ICFGRN): /* SPIs */ if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 2, gicd_reg - GICD_ICFGR, DABT_WORD); - if ( rank == NULL) goto write_ignore; - vgic_lock_rank(v, rank, flags); - vreg_reg32_update(&rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, - DABT_WORD)], - r, info); - vgic_unlock_rank(v, rank, flags); + irq = (gicd_reg - GICD_ICFGR) * 4; /* 2 bit per IRQ */ + vgic_store_irq_config(v, irq, r); return 1; case VRANGE32(0xD00, 0xDFC): diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c index d3356ae..e9e36eb 100644 --- a/xen/arch/arm/vgic-v3.c +++ b/xen/arch/arm/vgic-v3.c @@ -722,20 +722,11 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, return 1; case VRANGE32(GICD_ICFGR, GICD_ICFGRN): - { - uint32_t icfgr; - if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 2, reg - GICD_ICFGR, DABT_WORD); - if ( rank == NULL ) goto read_as_zero; - vgic_lock_rank(v, rank, flags); - icfgr = rank->icfg[REG_RANK_INDEX(2, reg - GICD_ICFGR, DABT_WORD)]; - vgic_unlock_rank(v, rank, flags); - - *r = vreg_reg32_extract(icfgr, info); - + irq = (reg - GICD_ICFGR) * 4; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto read_as_zero; + *r = vgic_fetch_irq_config(v, irq); return 1; - } default: printk(XENLOG_G_ERR @@ -834,13 +825,9 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, /* ICFGR1 for PPI's, which is implementation defined if ICFGR1 is programmable or not. We chose to program */ if ( dabt.size != DABT_WORD ) goto bad_width; - rank = vgic_rank_offset(v, 2, reg - GICD_ICFGR, DABT_WORD); - if ( rank == NULL ) goto write_ignore; - vgic_lock_rank(v, rank, flags); - vreg_reg32_update(&rank->icfg[REG_RANK_INDEX(2, reg - GICD_ICFGR, - DABT_WORD)], - r, info); - vgic_unlock_rank(v, rank, flags); + irq = (reg - GICD_ICFGR) * 4; + if ( irq >= v->domain->arch.vgic.nr_spis + 32 ) goto write_ignore; + vgic_store_irq_config(v, irq, r); return 1; default: diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index ddcd99b..e5a4765 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -268,6 +268,55 @@ void vgic_store_irq_priority(struct vcpu *v, unsigned int nrirqs, local_irq_restore(flags); } +#define IRQS_PER_CFGR 16 +/** + * vgic_fetch_irq_config: assemble the configuration bits for a group of 16 IRQs + * @v: the VCPU for private IRQs, any VCPU of a domain for SPIs + * @first_irq: the first IRQ to be queried, must be aligned to 16 + */ +uint32_t vgic_fetch_irq_config(struct vcpu *v, unsigned int first_irq) +{ + struct pending_irq *pirqs[IRQS_PER_CFGR]; + unsigned long flags; + uint32_t ret = 0, i; + + local_irq_save(flags); + vgic_lock_irqs(v, IRQS_PER_CFGR, first_irq, pirqs); + + for ( i = 0; i < IRQS_PER_CFGR; i++ ) + if ( test_bit(GIC_IRQ_GUEST_LEVEL, &pirqs[i]->status) ) + ret |= 1 << (i * 2); + else + ret |= 3 << (i * 2); + + vgic_unlock_irqs(pirqs, IRQS_PER_CFGR); + local_irq_restore(flags); + + return ret; +} + +void vgic_store_irq_config(struct vcpu *v, unsigned int first_irq, + uint32_t value) +{ + struct pending_irq *pirqs[IRQS_PER_CFGR]; + unsigned long flags; + unsigned int i; + + local_irq_save(flags); + vgic_lock_irqs(v, IRQS_PER_CFGR, first_irq, pirqs); + + for ( i = 0; i < IRQS_PER_CFGR; i++, value >>= 2 ) + { + if ( (value & 0x3) > 1 ) + clear_bit(GIC_IRQ_GUEST_LEVEL, &pirqs[i]->status); + else + set_bit(GIC_IRQ_GUEST_LEVEL, &pirqs[i]->status); + } + + vgic_unlock_irqs(pirqs, IRQS_PER_CFGR); + local_irq_restore(flags); +} + bool vgic_migrate_irq(struct vcpu *old, struct vcpu *new, unsigned int irq) { unsigned long flags; @@ -384,22 +433,6 @@ void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n) } } -#define VGIC_ICFG_MASK(intr) (1 << ((2 * ((intr) % 16)) + 1)) - -/* The function should be called with the rank lock taken */ -static inline unsigned int vgic_get_virq_type(struct vcpu *v, int n, int index) -{ - struct vgic_irq_rank *r = vgic_get_rank(v, n); - uint32_t tr = r->icfg[index >> 4]; - - ASSERT(spin_is_locked(&r->lock)); - - if ( tr & VGIC_ICFG_MASK(index) ) - return IRQ_TYPE_EDGE_RISING; - else - return IRQ_TYPE_LEVEL_HIGH; -} - void vgic_lock_irqs(struct vcpu *v, unsigned int nrirqs, unsigned int first_irq, struct pending_irq **pirqs) { @@ -424,8 +457,8 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n) { const unsigned long mask = r; struct pending_irq *p; - unsigned int irq; - unsigned long flags; + unsigned int irq, int_type; + unsigned long flags, vcpu_flags; int i = 0; struct vcpu *v_target; struct domain *d = v->domain; @@ -436,23 +469,27 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n) while ( (i = find_next_bit(&mask, 32, i)) < 32 ) { irq = i + (32 * n); v_target = vgic_get_target_vcpu(v, irq); - spin_lock_irqsave(&v_target->arch.vgic.lock, flags); + spin_lock_irqsave(&v_target->arch.vgic.lock, vcpu_flags); p = irq_to_pending(v_target, irq); + vgic_irq_lock(p, flags); set_bit(GIC_IRQ_GUEST_ENABLED, &p->status); + int_type = test_bit(GIC_IRQ_GUEST_LEVEL, &p->status) ? + IRQ_TYPE_LEVEL_HIGH : IRQ_TYPE_EDGE_RISING; if ( !list_empty(&p->inflight) && !test_bit(GIC_IRQ_GUEST_VISIBLE, &p->status) ) gic_raise_guest_irq(v_target, irq, p->cur_priority); - spin_unlock_irqrestore(&v_target->arch.vgic.lock, flags); + vgic_irq_unlock(p, flags); + spin_unlock_irqrestore(&v_target->arch.vgic.lock, vcpu_flags); if ( p->desc != NULL ) { - irq_set_affinity(p->desc, cpumask_of(v_target->processor)); spin_lock_irqsave(&p->desc->lock, flags); + irq_set_affinity(p->desc, cpumask_of(v_target->processor)); /* * The irq cannot be a PPI, we only support delivery of SPIs * to guests. */ ASSERT(irq >= 32); if ( irq_type_set_by_domain(d) ) - gic_set_irq_type(p->desc, vgic_get_virq_type(v, n, i)); + gic_set_irq_type(p->desc, int_type); p->desc->handler->enable(p->desc); spin_unlock_irqrestore(&p->desc->lock, flags); } diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h index 6343c95..14c22b2 100644 --- a/xen/include/asm-arm/vgic.h +++ b/xen/include/asm-arm/vgic.h @@ -73,6 +73,7 @@ struct pending_irq #define GIC_IRQ_GUEST_ENABLED 3 #define GIC_IRQ_GUEST_MIGRATING 4 #define GIC_IRQ_GUEST_PRISTINE_LPI 5 +#define GIC_IRQ_GUEST_LEVEL 6 unsigned long status; struct irq_desc *desc; /* only set it the irq corresponds to a physical irq */ unsigned int irq; @@ -110,7 +111,6 @@ struct vgic_irq_rank { uint8_t index; uint32_t ienable; - uint32_t icfg[2]; /* * It's more convenient to store a target VCPU per vIRQ @@ -191,6 +191,9 @@ uint32_t vgic_fetch_irq_priority(struct vcpu *v, unsigned int nrirqs, unsigned int first_irq); void vgic_store_irq_priority(struct vcpu *v, unsigned int nrirqs, unsigned int first_irq, uint32_t reg); +uint32_t vgic_fetch_irq_config(struct vcpu *v, unsigned int first_irq); +void vgic_store_irq_config(struct vcpu *v, unsigned int first_irq, + uint32_t reg); enum gic_sgi_mode; -- 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 |