[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] xen/arm: vgic: Properly emulate the full register
commit a2b83f95bfad7c3533629cc7f3935cccc8e2d63d Author: Julien Grall <julien.grall@xxxxxxxxxx> AuthorDate: Wed Nov 18 17:28:00 2015 +0000 Commit: Ian Campbell <ian.campbell@xxxxxxxxxx> CommitDate: Wed Nov 25 12:29:28 2015 +0000 xen/arm: vgic: Properly emulate the full register The offset in the emulation is based on byte. As most of the registers are 64/32 bits, they will span over multiple bytes. However, the current emulation only cares about the first offset. This will result in not properly emulating any access on the register with any other offset. Introduce new macros to help implementing access on multiple byte and use them over the vGIC emulation. Note that I didn't convert the reserved/implementation defined registers. It will be done in a follow-up. Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx> Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx> --- xen/arch/arm/vgic-v2.c | 81 ++++++------ xen/arch/arm/vgic-v3.c | 287 +++++++++++++++++++++++--------------- xen/include/asm-arm/vgic-emul.h | 24 ++++ 3 files changed, 240 insertions(+), 152 deletions(-) diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c index 4fb954b..d1860a9 100644 --- a/xen/arch/arm/vgic-v2.c +++ b/xen/arch/arm/vgic-v2.c @@ -31,6 +31,7 @@ #include <asm/mmio.h> #include <asm/platform.h> #include <asm/vgic.h> +#include <asm/vgic-emul.h> static struct { bool_t enabled; @@ -177,13 +178,14 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, switch ( gicd_reg ) { - case GICD_CTLR: + case VREG32(GICD_CTLR): if ( dabt.size != DABT_WORD ) goto bad_width; vgic_lock(v); *r = vgic_reg32_extract(v->domain->arch.vgic.ctlr, info); vgic_unlock(v); return 1; - case GICD_TYPER: + + case VREG32(GICD_TYPER): { uint32_t typer; @@ -198,7 +200,8 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, return 1; } - case GICD_IIDR: + + case VREG32(GICD_IIDR): if ( dabt.size != DABT_WORD ) goto bad_width; /* * XXX Do we need a JEP106 manufacturer ID? @@ -211,11 +214,11 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, case 0x020 ... 0x03c: goto read_as_zero; - case GICD_IGROUPR ... GICD_IGROUPRN: + case VRANGE32(GICD_IGROUPR, GICD_IGROUPRN): /* We do not implement security extensions for guests, read zero */ goto read_as_zero_32; - case GICD_ISENABLER ... GICD_ISENABLERN: + 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; @@ -224,7 +227,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, vgic_unlock_rank(v, rank, flags); return 1; - case GICD_ICENABLER ... GICD_ICENABLERN: + 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; @@ -234,16 +237,16 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, return 1; /* Read the pending status of an IRQ via GICD is not supported */ - case GICD_ISPENDR ... GICD_ISPENDRN: - case GICD_ICPENDR ... GICD_ICPENDRN: + case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN): + case VRANGE32(GICD_ICPENDR, GICD_ICPENDRN): goto read_as_zero; /* Read the active status of an IRQ via GICD is not supported */ - case GICD_ISACTIVER ... GICD_ISACTIVERN: - case GICD_ICACTIVER ... GICD_ICACTIVERN: + case VRANGE32(GICD_ISACTIVER, GICD_ISACTIVERN): + case VRANGE32(GICD_ICACTIVER, GICD_ICACTIVERN): goto read_as_zero; - case GICD_ITARGETSR ... GICD_ITARGETSRN: + case VRANGE32(GICD_ITARGETSR, GICD_ITARGETSRN): { uint32_t itargetsr; @@ -258,7 +261,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, return 1; } - case GICD_IPRIORITYR ... GICD_IPRIORITYRN: + case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): { uint32_t ipriorityr; @@ -276,7 +279,7 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, return 1; } - case GICD_ICFGR ... GICD_ICFGRN: + case VRANGE32(GICD_ICFGR, GICD_ICFGRN): { uint32_t icfgr; @@ -292,26 +295,26 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info, return 1; } - case GICD_NSACR ... GICD_NSACRN: + case VRANGE32(GICD_NSACR, GICD_NSACRN): /* We do not implement security extensions for guests, read zero */ goto read_as_zero_32; - case GICD_SGIR: + case VREG32(GICD_SGIR): if ( dabt.size != DABT_WORD ) goto bad_width; /* Write only -- read unknown */ *r = 0xdeadbeef; return 1; /* Setting/Clearing the SGI pending bit via GICD is not supported */ - case GICD_CPENDSGIR ... GICD_CPENDSGIRN: - case GICD_SPENDSGIR ... GICD_SPENDSGIRN: + case VRANGE32(GICD_CPENDSGIR, GICD_CPENDSGIRN): + case VRANGE32(GICD_SPENDSGIR, GICD_SPENDSGIRN): goto read_as_zero; /* Implementation defined -- read as zero */ case 0xfd0 ... 0xfe4: goto read_as_zero; - case GICD_ICPIDR2: + case VREG32(GICD_ICPIDR2): if ( dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: vGICD: unhandled read from ICPIDR2\n", v); return 0; @@ -396,7 +399,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, switch ( gicd_reg ) { - case GICD_CTLR: + case VREG32(GICD_CTLR): if ( dabt.size != DABT_WORD ) goto bad_width; /* Ignore all but the enable bit */ vgic_lock(v); @@ -407,19 +410,19 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, return 1; /* R/O -- write ignored */ - case GICD_TYPER: - case GICD_IIDR: + case VREG32(GICD_TYPER): + case VREG32(GICD_IIDR): goto write_ignore_32; /* Implementation defined -- write ignored */ case 0x020 ... 0x03c: goto write_ignore; - case GICD_IGROUPR ... GICD_IGROUPRN: + case VRANGE32(GICD_IGROUPR, GICD_IGROUPRN): /* We do not implement security extensions for guests, write ignore */ goto write_ignore_32; - case GICD_ISENABLER ... GICD_ISENABLERN: + 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; @@ -430,7 +433,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, vgic_unlock_rank(v, rank, flags); return 1; - case GICD_ICENABLER ... GICD_ICENABLERN: + 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; @@ -441,39 +444,39 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, vgic_unlock_rank(v, rank, flags); return 1; - case GICD_ISPENDR ... GICD_ISPENDRN: + case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN): if ( dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: vGICD: unhandled word write %#"PRIregister" to ISPENDR%d\n", v, r, gicd_reg - GICD_ISPENDR); return 0; - case GICD_ICPENDR ... GICD_ICPENDRN: + case VRANGE32(GICD_ICPENDR, GICD_ICPENDRN): if ( dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: vGICD: unhandled word write %#"PRIregister" to ICPENDR%d\n", v, r, gicd_reg - GICD_ICPENDR); return 0; - case GICD_ISACTIVER ... GICD_ISACTIVERN: + case VRANGE32(GICD_ISACTIVER, GICD_ISACTIVERN): if ( dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: vGICD: unhandled word write %#"PRIregister" to ISACTIVER%d\n", v, r, gicd_reg - GICD_ISACTIVER); return 0; - case GICD_ICACTIVER ... GICD_ICACTIVERN: + case VRANGE32(GICD_ICACTIVER, GICD_ICACTIVERN): if ( dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: vGICD: unhandled word write %#"PRIregister" to ICACTIVER%d\n", v, r, gicd_reg - GICD_ICACTIVER); return 0; - case GICD_ITARGETSR ... GICD_ITARGETSR7: + case VRANGE32(GICD_ITARGETSR, GICD_ITARGETSR7): /* SGI/PPI target is read only */ goto write_ignore_32; - case GICD_ITARGETSR8 ... GICD_ITARGETSRN: + case VRANGE32(GICD_ITARGETSR8, GICD_ITARGETSRN): { uint32_t itargetsr; @@ -489,7 +492,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, return 1; } - case GICD_IPRIORITYR ... GICD_IPRIORITYRN: + case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): { uint32_t *ipriorityr; @@ -505,14 +508,14 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, return 1; } - case GICD_ICFGR: /* SGIs */ + case VREG32(GICD_ICFGR): /* SGIs */ goto write_ignore_32; - case GICD_ICFGR1: + case VREG32(GICD_ICFGR1): /* It is implementation defined if these are writeable. We chose not */ goto write_ignore_32; - case GICD_ICFGR2 ... GICD_ICFGRN: /* SPIs */ + 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; @@ -523,22 +526,22 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, vgic_unlock_rank(v, rank, flags); return 1; - case GICD_NSACR ... GICD_NSACRN: + case VRANGE32(GICD_NSACR, GICD_NSACRN): /* We do not implement security extensions for guests, write ignore */ goto write_ignore_32; - case GICD_SGIR: + case VREG32(GICD_SGIR): if ( dabt.size != DABT_WORD ) goto bad_width; return vgic_v2_to_sgi(v, r); - case GICD_CPENDSGIR ... GICD_CPENDSGIRN: + case VRANGE32(GICD_CPENDSGIR, GICD_CPENDSGIRN): if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: vGICD: unhandled %s write %#"PRIregister" to ICPENDSGIR%d\n", v, dabt.size ? "word" : "byte", r, gicd_reg - GICD_CPENDSGIR); return 0; - case GICD_SPENDSGIR ... GICD_SPENDSGIRN: + case VRANGE32(GICD_SPENDSGIR, GICD_SPENDSGIRN): if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: vGICD: unhandled %s write %#"PRIregister" to ISPENDSGIR%d\n", @@ -550,7 +553,7 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, mmio_info_t *info, goto write_ignore; /* R/O -- write ignore */ - case GICD_ICPIDR2: + case VREG32(GICD_ICPIDR2): goto write_ignore_32; /* Implementation defined -- write ignored */ diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c index 0f6cb95..892104d 100644 --- a/xen/arch/arm/vgic-v3.c +++ b/xen/arch/arm/vgic-v3.c @@ -30,6 +30,7 @@ #include <asm/mmio.h> #include <asm/gic_v3_defs.h> #include <asm/vgic.h> +#include <asm/vgic-emul.h> /* * PIDR2: Only bits[7:4] are not implementation defined. We are @@ -172,15 +173,16 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, mmio_info_t *info, switch ( gicr_reg ) { - case GICR_CTLR: + case VREG32(GICR_CTLR): /* We have not implemented LPI's, read zero */ goto read_as_zero_32; - case GICR_IIDR: + + case VREG32(GICR_IIDR): if ( dabt.size != DABT_WORD ) goto bad_width; *r = vgic_reg32_extract(GICV3_GICR_IIDR_VAL, info); return 1; - case GICR_TYPER: - case GICR_TYPER + 4: + + case VREG64(GICR_TYPER): { uint64_t typer, aff; @@ -199,40 +201,51 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, mmio_info_t *info, return 1; } - case GICR_STATUSR: + + case VREG32(GICR_STATUSR): /* Not implemented */ goto read_as_zero_32; - case GICR_WAKER: + + case VREG32(GICR_WAKER): /* Power management is not implemented */ goto read_as_zero_32; - case GICR_SETLPIR: + + case VREG64(GICR_SETLPIR): /* WO. Read as zero */ goto read_as_zero_64; - case GICR_CLRLPIR: + + case VREG64(GICR_CLRLPIR): /* WO. Read as zero */ goto read_as_zero_64; - case GICR_PROPBASER: + + case VREG64(GICR_PROPBASER): /* LPI's not implemented */ goto read_as_zero_64; - case GICR_PENDBASER: + + case VREG64(GICR_PENDBASER): /* LPI's not implemented */ goto read_as_zero_64; - case GICR_INVLPIR: + + case VREG64(GICR_INVLPIR): /* WO. Read as zero */ goto read_as_zero_64; - case GICR_INVALLR: + + case VREG64(GICR_INVALLR): /* WO. Read as zero */ goto read_as_zero_64; return 0; - case GICR_SYNCR: + + case VREG32(GICR_SYNCR): if ( dabt.size != DABT_WORD ) goto bad_width; /* RO . But when read it always returns busy bito bit[0] */ *r = vgic_reg32_extract(GICR_SYNCR_NOT_BUSY, info); return 1; - case GICR_MOVLPIR: + + case VREG64(GICR_MOVLPIR): /* WO Read as zero */ goto read_as_zero_64; - case GICR_MOVALLR: + + case VREG64(GICR_MOVALLR): /* WO Read as zero */ goto read_as_zero_64; @@ -240,7 +253,7 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, mmio_info_t *info, /* Implementation defined identification registers */ goto read_impl_defined; - case GICR_PIDR2: + case VREG32(GICR_PIDR2): if ( dabt.size != DABT_WORD ) goto bad_width; *r = vgic_reg32_extract(GICV3_GICR_PIDR2, info); return 1; @@ -287,46 +300,59 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, mmio_info_t *info, switch ( gicr_reg ) { - case GICR_CTLR: + case VREG32(GICR_CTLR): /* LPI's not implemented */ goto write_ignore_32; - case GICR_IIDR: + + case VREG32(GICR_IIDR): /* RO */ goto write_ignore_32; - case GICR_TYPER: + + case VREG64(GICR_TYPER): /* RO */ goto write_ignore_64; - case GICR_STATUSR: + + case VREG32(GICR_STATUSR): /* Not implemented */ goto write_ignore_32; - case GICR_WAKER: + + case VREG32(GICR_WAKER): /* Power mgmt not implemented */ goto write_ignore_32; - case GICR_SETLPIR: + + case VREG64(GICR_SETLPIR): /* LPI is not implemented */ goto write_ignore_64; - case GICR_CLRLPIR: + + case VREG64(GICR_CLRLPIR): /* LPI is not implemented */ goto write_ignore_64; - case GICR_PROPBASER: + + case VREG64(GICR_PROPBASER): /* LPI is not implemented */ goto write_ignore_64; - case GICR_PENDBASER: + + case VREG64(GICR_PENDBASER): /* LPI is not implemented */ goto write_ignore_64; - case GICR_INVLPIR: + + case VREG64(GICR_INVLPIR): /* LPI is not implemented */ goto write_ignore_64; - case GICR_INVALLR: + + case VREG64(GICR_INVALLR): /* LPI is not implemented */ goto write_ignore_64; - case GICR_SYNCR: + + case VREG32(GICR_SYNCR): /* RO */ goto write_ignore_32; - case GICR_MOVLPIR: + + case VREG64(GICR_MOVLPIR): /* LPI is not implemented */ goto write_ignore_64; - case GICR_MOVALLR: + + case VREG64(GICR_MOVALLR): /* LPI is not implemented */ goto write_ignore_64; @@ -334,7 +360,7 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu *v, mmio_info_t *info, /* Implementation defined identification registers */ goto write_impl_defined; - case GICR_PIDR2: + case VREG32(GICR_PIDR2): /* RO */ goto write_ignore_32; @@ -379,11 +405,12 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, switch ( reg ) { - case GICD_IGROUPR ... GICD_IGROUPRN: + case VRANGE32(GICD_IGROUPR, GICD_IGROUPRN): /* We do not implement security extensions for guests, read zero */ if ( dabt.size != DABT_WORD ) goto bad_width; goto read_as_zero; - case GICD_ISENABLER ... GICD_ISENABLERN: + + 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; @@ -391,7 +418,8 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, *r = vgic_reg32_extract(rank->ienable, info); vgic_unlock_rank(v, rank, flags); return 1; - case GICD_ICENABLER ... GICD_ICENABLERN: + + 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; @@ -399,17 +427,18 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, *r = vgic_reg32_extract(rank->ienable, info); vgic_unlock_rank(v, rank, flags); return 1; + /* Read the pending status of an IRQ via GICD/GICR is not supported */ - case GICD_ISPENDR ... GICD_ISPENDRN: - case GICD_ICPENDR ... GICD_ICPENDRN: + case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN): + case VRANGE32(GICD_ICPENDR, GICD_ICPENDR): goto read_as_zero; /* Read the active status of an IRQ via GICD/GICR is not supported */ - case GICD_ISACTIVER ... GICD_ISACTIVERN: - case GICD_ICACTIVER ... GICD_ICACTIVERN: + case VRANGE32(GICD_ISACTIVER, GICD_ISACTIVER): + case VRANGE32(GICD_ICACTIVER, GICD_ICACTIVERN): goto read_as_zero; - case GICD_IPRIORITYR ... GICD_IPRIORITYRN: + case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): { uint32_t ipriorityr; @@ -427,7 +456,7 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, return 1; } - case GICD_ICFGR ... GICD_ICFGRN: + case VRANGE32(GICD_ICFGR, GICD_ICFGRN): { uint32_t icfgr; @@ -442,6 +471,7 @@ static int __vgic_v3_distr_common_mmio_read(const char *name, struct vcpu *v, return 1; } + default: printk(XENLOG_G_ERR "%pv: %s: unhandled read r%d offset %#08x\n", @@ -471,10 +501,11 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, switch ( reg ) { - case GICD_IGROUPR ... GICD_IGROUPRN: + case VRANGE32(GICD_IGROUPR, GICD_IGROUPRN): /* We do not implement security extensions for guests, write ignore */ goto write_ignore_32; - case GICD_ISENABLER ... GICD_ISENABLERN: + + 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 write_ignore; @@ -484,7 +515,8 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, vgic_enable_irqs(v, (rank->ienable) & (~tr), rank->index); vgic_unlock_rank(v, rank, flags); return 1; - case GICD_ICENABLER ... GICD_ICENABLERN: + + 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 write_ignore; @@ -494,35 +526,36 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, vgic_disable_irqs(v, (~rank->ienable) & tr, rank->index); vgic_unlock_rank(v, rank, flags); return 1; - case GICD_ISPENDR ... GICD_ISPENDRN: + + case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN): if ( dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: %s: unhandled word write %#"PRIregister" to ISPENDR%d\n", v, name, r, reg - GICD_ISPENDR); return 0; - case GICD_ICPENDR ... GICD_ICPENDRN: + case VRANGE32(GICD_ICPENDR, GICD_ICPENDRN): if ( dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: %s: unhandled word write %#"PRIregister" to ICPENDR%d\n", v, name, r, reg - GICD_ICPENDR); return 0; - case GICD_ISACTIVER ... GICD_ISACTIVERN: + case VRANGE32(GICD_ISACTIVER, GICD_ISACTIVERN): if ( dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: %s: unhandled word write %#"PRIregister" to ISACTIVER%d\n", v, name, r, reg - GICD_ISACTIVER); return 0; - case GICD_ICACTIVER ... GICD_ICACTIVERN: + case VRANGE32(GICD_ICACTIVER, GICD_ICACTIVERN): if ( dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: %s: unhandled word write %#"PRIregister" to ICACTIVER%d\n", v, name, r, reg - GICD_ICACTIVER); return 0; - case GICD_IPRIORITYR ... GICD_IPRIORITYRN: + case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): { uint32_t *ipriorityr; @@ -536,9 +569,11 @@ static int __vgic_v3_distr_common_mmio_write(const char *name, struct vcpu *v, vgic_unlock_rank(v, rank, flags); return 1; } - case GICD_ICFGR: /* Restricted to configure SGIs */ + + case VREG32(GICD_ICFGR): /* Restricted to configure SGIs */ goto write_ignore_32; - case GICD_ICFGR + 4 ... GICD_ICFGRN: /* PPI + SPIs */ + + case VRANGE32(GICD_ICFGR + 4, GICD_ICFGRN): /* PPI + SPIs */ /* 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; @@ -578,16 +613,17 @@ static int vgic_v3_rdistr_sgi_mmio_read(struct vcpu *v, mmio_info_t *info, switch ( gicr_reg ) { - case GICR_IGRPMODR0: + case VREG32(GICR_IGRPMODR0): /* We do not implement security extensions for guests, read zero */ goto read_as_zero_32; - case GICR_IGROUPR0: - case GICR_ISENABLER0: - case GICR_ICENABLER0: - case GICR_ISACTIVER0: - case GICR_ICACTIVER0: - case GICR_IPRIORITYR0...GICR_IPRIORITYR7: - case GICR_ICFGR0... GICR_ICFGR1: + + case VREG32(GICR_IGROUPR0): + case VREG32(GICR_ISENABLER0): + case VREG32(GICR_ICENABLER0): + case VREG32(GICR_ISACTIVER0): + case VREG32(GICR_ICACTIVER0): + case VRANGE32(GICR_IPRIORITYR0, GICR_IPRIORITYR7): + case VRANGE32(GICR_ICFGR0, GICR_ICFGR1): /* * Above registers offset are common with GICD. * So handle in common with GICD handling @@ -596,11 +632,11 @@ static int vgic_v3_rdistr_sgi_mmio_read(struct vcpu *v, mmio_info_t *info, gicr_reg, r); /* Read the pending status of an SGI is via GICR is not supported */ - case GICR_ISPENDR0: - case GICR_ICPENDR0: + case VREG32(GICR_ISPENDR0): + case VREG32(GICR_ICPENDR0): goto read_as_zero; - case GICR_NSACR: + case VREG32(GICR_NSACR): /* We do not implement security extensions for guests, read zero */ goto read_as_zero_32; @@ -630,39 +666,42 @@ static int vgic_v3_rdistr_sgi_mmio_write(struct vcpu *v, mmio_info_t *info, switch ( gicr_reg ) { - case GICR_IGRPMODR0: + case VREG32(GICR_IGRPMODR0): /* We do not implement security extensions for guests, write ignore */ goto write_ignore_32; - case GICR_IGROUPR0: - case GICR_ISENABLER0: - case GICR_ICENABLER0: - case GICR_ISACTIVER0: - case GICR_ICACTIVER0: - case GICR_ICFGR1: - case GICR_IPRIORITYR0...GICR_IPRIORITYR7: + + case VREG32(GICR_IGROUPR0): + case VREG32(GICR_ISENABLER0): + case VREG32(GICR_ICENABLER0): + case VREG32(GICR_ISACTIVER0): + case VREG32(GICR_ICACTIVER0): + case VREG32(GICR_ICFGR1): + case VRANGE32(GICR_IPRIORITYR0, GICR_IPRIORITYR7): /* * Above registers offset are common with GICD. * So handle common with GICD handling */ return __vgic_v3_distr_common_mmio_write("vGICR: SGI", v, info, gicr_reg, r); - case GICR_ISPENDR0: + + case VREG32(GICR_ISPENDR0): if ( dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: vGICR: SGI: unhandled word write %#"PRIregister" to ISPENDR0\n", v, r); return 0; - case GICR_ICPENDR0: + case VREG32(GICR_ICPENDR0): if ( dabt.size != DABT_WORD ) goto bad_width; printk(XENLOG_G_ERR "%pv: vGICR: SGI: unhandled word write %#"PRIregister" to ICPENDR0\n", v, r); return 0; - case GICR_NSACR: + case VREG32(GICR_NSACR): /* We do not implement security extensions for guests, write ignore */ goto write_ignore_32; + default: printk(XENLOG_G_ERR "%pv: vGICR: SGI: unhandled write r%d offset %#08x\n", @@ -761,13 +800,14 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, mmio_info_t *info, switch ( gicd_reg ) { - case GICD_CTLR: + case VREG32(GICD_CTLR): if ( dabt.size != DABT_WORD ) goto bad_width; vgic_lock(v); *r = vgic_reg32_extract(v->domain->arch.vgic.ctlr, info); vgic_unlock(v); return 1; - case GICD_TYPER: + + case VREG32(GICD_TYPER): { /* * Number of interrupt identifier bits supported by the GIC @@ -792,34 +832,39 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, mmio_info_t *info, return 1; } - case GICD_STATUSR: + + case VREG32(GICD_STATUSR): /* * Optional, Not implemented for now. * Update to support guest debugging. */ goto read_as_zero_32; - case GICD_IIDR: + + case VREG32(GICD_IIDR): if ( dabt.size != DABT_WORD ) goto bad_width; *r = vgic_reg32_extract(GICV3_GICD_IIDR_VAL, info); return 1; + case 0x020 ... 0x03c: case 0xc000 ... 0xffcc: /* Implementation defined -- read as zero */ goto read_as_zero_32; - case GICD_IGROUPR ... GICD_IGROUPRN: - case GICD_ISENABLER ... GICD_ISENABLERN: - case GICD_ICENABLER ... GICD_ICENABLERN: - case GICD_ISPENDR ... GICD_ISPENDRN: - case GICD_ICPENDR ... GICD_ICPENDRN: - case GICD_ISACTIVER ... GICD_ISACTIVERN: - case GICD_IPRIORITYR ... GICD_IPRIORITYRN: - case GICD_ICFGR ... GICD_ICFGRN: + + case VRANGE32(GICD_IGROUPR, GICD_IGROUPRN): + case VRANGE32(GICD_ISENABLER, GICD_ISENABLERN): + case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN): + case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN): + case VRANGE32(GICD_ICPENDR, GICD_ICPENDRN): + case VRANGE32(GICD_ISACTIVER, GICD_ISACTIVERN): + case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): + case VRANGE32(GICD_ICFGR, GICD_ICFGRN): /* * Above all register are common with GICR and GICD * Manage in common */ return __vgic_v3_distr_common_mmio_read("vGICD", v, info, gicd_reg, r); - case GICD_IROUTER32 ... GICD_IROUTER1019: + + case VRANGE64(GICD_IROUTER32, GICD_IROUTER1019): { uint64_t irouter; @@ -836,16 +881,19 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, mmio_info_t *info, return 1; } - case GICD_NSACR ... GICD_NSACRN: + case VRANGE32(GICD_NSACR, GICD_NSACRN): /* We do not implement security extensions for guests, read zero */ goto read_as_zero_32; - case GICD_SGIR: + + case VREG32(GICD_SGIR): /* Read as ICH_SGIR system register with SRE set. So ignore */ goto read_as_zero_32; - case GICD_CPENDSGIR ... GICD_CPENDSGIRN: + + case VRANGE32(GICD_CPENDSGIR, GICD_CPENDSGIRN): /* Replaced with GICR_ICPENDR0. So ignore write */ goto read_as_zero_32; - case GICD_SPENDSGIR ... GICD_SPENDSGIRN: + + case VRANGE32(GICD_SPENDSGIR, GICD_SPENDSGIRN): /* Replaced with GICR_ISPENDR0. So ignore write */ goto read_as_zero_32; @@ -853,7 +901,7 @@ static int vgic_v3_distr_mmio_read(struct vcpu *v, mmio_info_t *info, /* Implementation defined identification registers */ goto read_impl_defined; - case GICD_PIDR2: + case VREG32(GICD_PIDR2): /* GICv3 identification value */ if ( dabt.size != DABT_WORD ) goto bad_width; *r = vgic_reg32_extract(GICV3_GICD_PIDR2, info); @@ -915,7 +963,7 @@ static int vgic_v3_distr_mmio_write(struct vcpu *v, mmio_info_t *info, switch ( gicd_reg ) { - case GICD_CTLR: + case VREG32(GICD_CTLR): { uint32_t ctlr = 0; @@ -934,27 +982,35 @@ static int vgic_v3_distr_mmio_write(struct vcpu *v, mmio_info_t *info, return 1; } - case GICD_TYPER: + + case VREG32(GICD_TYPER): /* RO -- write ignored */ goto write_ignore_32; - case GICD_IIDR: + + case VREG32(GICD_IIDR): /* RO -- write ignored */ goto write_ignore_32; - case GICD_STATUSR: + + case VREG32(GICD_STATUSR): /* RO -- write ignored */ goto write_ignore_32; - case GICD_SETSPI_NSR: + + case VREG32(GICD_SETSPI_NSR): /* Message based SPI is not implemented */ goto write_ignore_32; - case GICD_CLRSPI_NSR: + + case VREG32(GICD_CLRSPI_NSR): /* Message based SPI is not implemented */ goto write_ignore_32; - case GICD_SETSPI_SR: + + case VREG32(GICD_SETSPI_SR): /* Message based SPI is not implemented */ goto write_ignore_32; - case GICD_CLRSPI_SR: + + case VREG32(GICD_CLRSPI_SR): /* Message based SPI is not implemented */ goto write_ignore_32; + case 0x020 ... 0x03c: case 0xc000 ... 0xffcc: /* Implementation defined -- write ignored */ @@ -962,20 +1018,22 @@ static int vgic_v3_distr_mmio_write(struct vcpu *v, mmio_info_t *info, "%pv: vGICD: WI on implementation defined register offset %#08x\n", v, gicd_reg); goto write_ignore_32; - case GICD_IGROUPR ... GICD_IGROUPRN: - case GICD_ISENABLER ... GICD_ISENABLERN: - case GICD_ICENABLER ... GICD_ICENABLERN: - case GICD_ISPENDR ... GICD_ISPENDRN: - case GICD_ICPENDR ... GICD_ICPENDRN: - case GICD_ISACTIVER ... GICD_ISACTIVERN: - case GICD_ICACTIVER ... GICD_ICACTIVERN: - case GICD_IPRIORITYR ... GICD_IPRIORITYRN: - case GICD_ICFGR ... GICD_ICFGRN: + + case VRANGE32(GICD_IGROUPR, GICD_IGROUPRN): + case VRANGE32(GICD_ISENABLER, GICD_ISENABLERN): + case VRANGE32(GICD_ICENABLER, GICD_ICENABLERN): + case VRANGE32(GICD_ISPENDR, GICD_ISPENDRN): + case VRANGE32(GICD_ICPENDR, GICD_ICPENDRN): + case VRANGE32(GICD_ISACTIVER, GICD_ISACTIVERN): + case VRANGE32(GICD_ICACTIVER, GICD_ICACTIVERN): + case VRANGE32(GICD_IPRIORITYR, GICD_IPRIORITYRN): + case VRANGE32(GICD_ICFGR, GICD_ICFGRN): /* Above registers are common with GICR and GICD * Manage in common */ return __vgic_v3_distr_common_mmio_write("vGICD", v, info, gicd_reg, r); - case GICD_IROUTER32 ... GICD_IROUTER1019: + + case VRANGE64(GICD_IROUTER32, GICD_IROUTER1019): { uint64_t irouter; @@ -991,17 +1049,20 @@ static int vgic_v3_distr_mmio_write(struct vcpu *v, mmio_info_t *info, return 1; } - case GICD_NSACR ... GICD_NSACRN: + case VRANGE32(GICD_NSACR, GICD_NSACRN): /* We do not implement security extensions for guests, write ignore */ goto write_ignore_32; - case GICD_SGIR: + + case VREG32(GICD_SGIR): /* it is accessed as system register in GICv3 */ goto write_ignore_32; - case GICD_CPENDSGIR ... GICD_CPENDSGIRN: + + case VRANGE32(GICD_CPENDSGIR, GICD_CPENDSGIRN): /* Replaced with GICR_ICPENDR0. So ignore write */ if ( dabt.size != DABT_WORD ) goto bad_width; return 0; - case GICD_SPENDSGIR ... GICD_SPENDSGIRN: + + case VRANGE32(GICD_SPENDSGIR, GICD_SPENDSGIRN): /* Replaced with GICR_ISPENDR0. So ignore write */ if ( dabt.size != DABT_WORD ) goto bad_width; return 0; @@ -1010,7 +1071,7 @@ static int vgic_v3_distr_mmio_write(struct vcpu *v, mmio_info_t *info, /* Implementation defined identification registers */ goto write_impl_defined; - case GICD_PIDR2: + case VREG32(GICD_PIDR2): /* RO -- write ignore */ goto write_ignore_32; diff --git a/xen/include/asm-arm/vgic-emul.h b/xen/include/asm-arm/vgic-emul.h new file mode 100644 index 0000000..184a1f0 --- /dev/null +++ b/xen/include/asm-arm/vgic-emul.h @@ -0,0 +1,24 @@ +#ifndef __ASM_ARM_VGIC_EMUL_H__ +#define __ASM_ARM_VGIC_EMUL_H__ + +/* + * Helpers to create easily a case to match emulate a single register or + * a range of registers + */ + +#define VREG32(reg) reg ... reg + 3 +#define VREG64(reg) reg ... reg + 7 + +#define VRANGE32(start, end) start ... end + 3 +#define VRANGE64(start, end) start ... end + 7 + +#endif /* __ASM_ARM_VGIC_EMUL_H__ */ + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |