[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v6a 14/17] xen/arm: calculate vgic irq rank based on register size
From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> vGIC irq rank was computed assuming the register offset is byte size.Use the HSR abort address size in calculating register size. So, with this patch following are acheived (1) In the code 'dabt.size != number' this number is always BYTE/HALF_WORD/WORD/DOUBLE defined by hsr registers. Instead of checking for hard coded values use HSR abort address size values. (2) The vgic_irq_rank also depends on the same HSR defined values to calculate irq rank. This make vgic_irq_rank generic as it takes register size as parameter to calculate irq rank instead of hard coding to value 2 in previous patches Also, output of REG_RANK_INDEX macro is modulo by 32 to make sure register index is always within irq rank Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx> --- xen/arch/arm/vgic.c | 139 ++++++++++++++++++++------------------- xen/include/asm-arm/processor.h | 8 +++ xen/include/asm-arm/vgic.h | 4 +- 3 files changed, 83 insertions(+), 68 deletions(-) diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c index d29474b..ca9eeda 100644 --- a/xen/arch/arm/vgic.c +++ b/xen/arch/arm/vgic.c @@ -40,9 +40,10 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info); * Returns rank corresponding to a GICD_<FOO><n> register for * GICD_<FOO> with <b>-bits-per-interrupt. */ -static struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n) +static struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n, + int s) { - int rank = REG_RANK_NR(b, (n >> 2)); + int rank = REG_RANK_NR(b, (n >> s)); if ( rank == 0 ) return v->arch.vgic.private_irqs; @@ -54,7 +55,7 @@ static struct vgic_irq_rank *vgic_rank_offset(struct vcpu *v, int b, int n) static struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, unsigned int irq) { - return vgic_rank_offset(v, 8, irq); + return vgic_rank_offset(v, 8, irq, DABT_WORD); } static const struct mmio_handler_ops vgic_distr_mmio_handler = { @@ -161,13 +162,13 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) switch ( gicd_reg ) { case GICD_CTLR: - if ( dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_WORD ) goto bad_width; vgic_lock(v); *r = v->domain->arch.vgic.ctlr; vgic_unlock(v); return 1; case GICD_TYPER: - if ( dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_WORD ) goto bad_width; /* No secure world support for guests. */ vgic_lock(v); *r = ( (v->domain->max_vcpus<<5) & GICD_TYPE_CPUS ) @@ -175,7 +176,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) vgic_unlock(v); return 1; case GICD_IIDR: - if ( dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_WORD ) goto bad_width; /* * XXX Do we need a JEP106 manufacturer ID? * Just use the physical h/w value for now @@ -192,8 +193,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) goto read_as_zero; case GICD_ISENABLER ... GICD_ISENABLERN: - if ( dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER); + 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); *r = rank->ienable; @@ -201,8 +202,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) return 1; case GICD_ICENABLER ... GICD_ICENABLERN: - if ( dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER); + 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); *r = rank->ienable; @@ -210,8 +211,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) return 1; case GICD_ISPENDR ... GICD_ISPENDRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISPENDR); + if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISPENDR, DABT_WORD); if ( rank == NULL) goto read_as_zero; vgic_lock_rank(v, rank); *r = vgic_byte_read(rank->ipend, dabt.sign, offset); @@ -219,8 +220,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) return 1; case GICD_ICPENDR ... GICD_ICPENDRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICPENDR); + if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICPENDR, DABT_WORD); if ( rank == NULL) goto read_as_zero; vgic_lock_rank(v, rank); *r = vgic_byte_read(rank->ipend, dabt.sign, offset); @@ -228,8 +229,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) return 1; case GICD_ISACTIVER ... GICD_ISACTIVERN: - if ( dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER); + 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; vgic_lock_rank(v, rank); *r = rank->iactive; @@ -237,8 +238,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) return 1; case GICD_ICACTIVER ... GICD_ICACTIVERN: - if ( dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER); + 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; vgic_lock_rank(v, rank); *r = rank->iactive; @@ -246,35 +247,37 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) return 1; case GICD_ITARGETSR ... GICD_ITARGETSRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR); + if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR, DABT_WORD); if ( rank == NULL) goto read_as_zero; vgic_lock_rank(v, rank); - *r = rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR)]; - if ( dabt.size == 0 ) + *r = rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR, + DABT_WORD)]; + if ( dabt.size == DABT_BYTE ) *r = vgic_byte_read(*r, dabt.sign, offset); vgic_unlock_rank(v, rank); return 1; case GICD_IPRIORITYR ... GICD_IPRIORITYRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR); + if ( dabt.size != 0 && dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD); if ( rank == NULL) goto read_as_zero; vgic_lock_rank(v, rank); - *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR)]; - if ( dabt.size == 0 ) + *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR, + DABT_WORD)]; + if ( dabt.size == DABT_BYTE ) *r = vgic_byte_read(*r, dabt.sign, offset); vgic_unlock_rank(v, rank); return 1; case GICD_ICFGR ... GICD_ICFGRN: - if ( dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 2, gicd_reg - GICD_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); - *r = rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR)]; + *r = rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)]; vgic_unlock_rank(v, rank); return 1; @@ -283,14 +286,14 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) goto read_as_zero; case GICD_SGIR: - if ( dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_WORD ) goto bad_width; /* Write only -- read unknown */ *r = 0xdeadbeef; return 1; case GICD_CPENDSGIR ... GICD_CPENDSGIRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_CPENDSGIR); + if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 1, gicd_reg - GICD_CPENDSGIR, DABT_WORD); if ( rank == NULL) goto read_as_zero; vgic_lock_rank(v, rank); *r = vgic_byte_read(rank->pendsgi, dabt.sign, offset); @@ -298,8 +301,8 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) return 1; case GICD_SPENDSGIR ... GICD_SPENDSGIRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_SPENDSGIR); + if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 1, gicd_reg - GICD_SPENDSGIR, DABT_WORD); if ( rank == NULL) goto read_as_zero; vgic_lock_rank(v, rank); *r = vgic_byte_read(rank->pendsgi, dabt.sign, offset); @@ -311,7 +314,7 @@ static int vgic_distr_mmio_read(struct vcpu *v, mmio_info_t *info) goto read_as_zero; case GICD_ICPIDR2: - if ( dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_WORD ) goto bad_width; printk("vGICD: unhandled read from ICPIDR2\n"); return 0; @@ -341,7 +344,7 @@ bad_width: return 0; read_as_zero: - if ( dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_WORD ) goto bad_width; *r = 0; return 1; } @@ -467,7 +470,7 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info) switch ( gicd_reg ) { case GICD_CTLR: - if ( dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_WORD ) goto bad_width; /* Ignore all but the enable bit */ v->domain->arch.vgic.ctlr = (*r) & GICD_CTL_ENABLE; return 1; @@ -486,42 +489,44 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info) goto write_ignore; case GICD_ISENABLER ... GICD_ISENABLERN: - if ( dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISENABLER); + 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); tr = rank->ienable; rank->ienable |= *r; vgic_unlock_rank(v, rank); - vgic_enable_irqs(v, (*r) & (~tr), (gicd_reg - GICD_ISENABLER) >> 2); + vgic_enable_irqs(v, (*r) & (~tr), + (gicd_reg - GICD_ISENABLER) >> DABT_WORD); return 1; case GICD_ICENABLER ... GICD_ICENABLERN: - if ( dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICENABLER); + 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); tr = rank->ienable; rank->ienable &= ~*r; vgic_unlock_rank(v, rank); - vgic_disable_irqs(v, (*r) & tr, (gicd_reg - GICD_ICENABLER) >> 2); + vgic_disable_irqs(v, (*r) & tr, + (gicd_reg - GICD_ICENABLER) >> DABT_WORD); return 1; case GICD_ISPENDR ... GICD_ISPENDRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDR%d\n", dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ISPENDR); return 0; case GICD_ICPENDR ... GICD_ICPENDRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDR%d\n", dabt.size ? "word" : "byte", *r, gicd_reg - GICD_ICPENDR); return 0; case GICD_ISACTIVER ... GICD_ISACTIVERN: - if ( dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER); + if ( dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ISACTIVER, DABT_WORD); if ( rank == NULL) goto write_ignore; vgic_lock_rank(v, rank); rank->iactive &= ~*r; @@ -529,8 +534,8 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info) return 1; case GICD_ICACTIVER ... GICD_ICACTIVERN: - if ( dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER); + if ( dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 1, gicd_reg - GICD_ICACTIVER, DABT_WORD); if ( rank == NULL) goto write_ignore; vgic_lock_rank(v, rank); rank->iactive &= ~*r; @@ -542,30 +547,32 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info) goto write_ignore; case GICD_ITARGETSR + 8 ... GICD_ITARGETSRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR); + if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 8, gicd_reg - GICD_ITARGETSR, DABT_WORD); if ( rank == NULL) goto write_ignore; vgic_lock_rank(v, rank); - if ( dabt.size == 2 ) - rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR)] = *r; + if ( dabt.size == DABT_WORD ) + rank->itargets[REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR, + DABT_WORD)] = *r; else { - tr = REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR); + tr = REG_RANK_INDEX(8, gicd_reg - GICD_ITARGETSR, DABT_WORD); vgic_byte_write(&rank->itargets[tr], *r, offset); } vgic_unlock_rank(v, rank); return 1; case GICD_IPRIORITYR ... GICD_IPRIORITYRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR); + if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; + rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD); if ( rank == NULL) goto write_ignore; vgic_lock_rank(v, rank); - if ( dabt.size == 2 ) - rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR)] = *r; + if ( dabt.size == DABT_WORD ) + rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR, + DABT_WORD)] = *r; else { - tr = REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR); + tr = REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR, DABT_WORD); vgic_byte_write(&rank->ipriority[tr], *r, offset); } vgic_unlock_rank(v, rank); @@ -577,11 +584,11 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info) /* It is implementation defined if these are writeable. We chose not */ goto write_ignore; case GICD_ICFGR + 2 ... GICD_ICFGRN: /* SPIs */ - if ( dabt.size != 2 ) goto bad_width; - rank = vgic_rank_offset(v, 2, gicd_reg - GICD_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 write_ignore; vgic_lock_rank(v, rank); - rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR)] = *r; + rank->icfg[REG_RANK_INDEX(2, gicd_reg - GICD_ICFGR, DABT_WORD)] = *r; vgic_unlock_rank(v, rank); return 1; @@ -595,13 +602,13 @@ static int vgic_distr_mmio_write(struct vcpu *v, mmio_info_t *info) return vgic_to_sgi(v, *r); case GICD_CPENDSGIR ... GICD_CPENDSGIRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; printk("vGICD: unhandled %s write %#"PRIregister" to ICPENDSGIR%d\n", dabt.size ? "word" : "byte", *r, gicd_reg - GICD_CPENDSGIR); return 0; case GICD_SPENDSGIR ... GICD_SPENDSGIRN: - if ( dabt.size != 0 && dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; printk("vGICD: unhandled %s write %#"PRIregister" to ISPENDSGIR%d\n", dabt.size ? "word" : "byte", *r, gicd_reg - GICD_SPENDSGIR); return 0; @@ -640,7 +647,7 @@ bad_width: return 0; write_ignore: - if ( dabt.size != 2 ) goto bad_width; + if ( dabt.size != DABT_WORD ) goto bad_width; return 1; } @@ -692,7 +699,7 @@ void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq) return; } - priority = vgic_byte_read(rank->ipriority[REG_RANK_INDEX(8, irq)], 0, irq & 0x3); + priority = vgic_byte_read(rank->ipriority[REG_RANK_INDEX(8, irq, DABT_WORD)], 0, irq & 0x3); n->irq = irq; set_bit(GIC_IRQ_GUEST_QUEUED, &n->status); diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h index ebc683d..22a1998 100644 --- a/xen/include/asm-arm/processor.h +++ b/xen/include/asm-arm/processor.h @@ -251,6 +251,14 @@ extern struct cpuinfo_arm cpu_data[]; extern u32 __cpu_logical_map[]; #define cpu_logical_map(cpu) __cpu_logical_map[cpu] +/* HSR data abort size definition */ +enum dabt_size { + DABT_BYTE = 0, + DABT_HALF_WORD = 1, + DABT_WORD = 2, + DABT_DOUBLE_WORD = 3, +}; + union hsr { uint32_t bits; struct { diff --git a/xen/include/asm-arm/vgic.h b/xen/include/asm-arm/vgic.h index 003c3e9..7c71d16 100644 --- a/xen/include/asm-arm/vgic.h +++ b/xen/include/asm-arm/vgic.h @@ -134,10 +134,10 @@ static inline void vgic_byte_write(uint32_t *reg, uint32_t var, int offset) } /* - * Offset of GICD_<FOO><n> with its rank, for GICD_<FOO> with + * Offset of GICD_<FOO><n> with its rank, for GICD_<FOO> size <s> with * <b>-bits-per-interrupt. */ -#define REG_RANK_INDEX(b, n) (((n) >> 2) & ((b)-1)) +#define REG_RANK_INDEX(b, n, s) ((((n) >> s) & ((b)-1)) % 32) extern int domain_vgic_init(struct domain *d); extern void domain_vgic_free(struct domain *d); -- 1.7.9.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |