diff options
Diffstat (limited to 'hw/intc')
-rw-r--r-- | hw/intc/arm_gicv3_dist.c | 205 | ||||
-rw-r--r-- | hw/intc/armv7m_nvic.c | 274 |
2 files changed, 112 insertions, 367 deletions
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c index b65f56f903..5beb7c4235 100644 --- a/hw/intc/arm_gicv3_dist.c +++ b/hw/intc/arm_gicv3_dist.c @@ -262,8 +262,21 @@ static void gicd_write_irouter(GICv3State *s, MemTxAttrs attrs, int irq, gicv3_update(s, irq, 1); } -static MemTxResult gicd_readb(GICv3State *s, hwaddr offset, - uint64_t *data, MemTxAttrs attrs) +/** + * gicd_readb + * gicd_readw + * gicd_readl + * gicd_readq + * gicd_writeb + * gicd_writew + * gicd_writel + * gicd_writeq + * + * Return %true if the operation succeeded, %false otherwise. + */ + +static bool gicd_readb(GICv3State *s, hwaddr offset, + uint64_t *data, MemTxAttrs attrs) { /* Most GICv3 distributor registers do not support byte accesses. */ switch (offset) { @@ -273,17 +286,17 @@ static MemTxResult gicd_readb(GICv3State *s, hwaddr offset, /* This GIC implementation always has affinity routing enabled, * so these registers are all RAZ/WI. */ - return MEMTX_OK; + return true; case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff: *data = gicd_read_ipriorityr(s, attrs, offset - GICD_IPRIORITYR); - return MEMTX_OK; + return true; default: - return MEMTX_ERROR; + return false; } } -static MemTxResult gicd_writeb(GICv3State *s, hwaddr offset, - uint64_t value, MemTxAttrs attrs) +static bool gicd_writeb(GICv3State *s, hwaddr offset, + uint64_t value, MemTxAttrs attrs) { /* Most GICv3 distributor registers do not support byte accesses. */ switch (offset) { @@ -293,25 +306,25 @@ static MemTxResult gicd_writeb(GICv3State *s, hwaddr offset, /* This GIC implementation always has affinity routing enabled, * so these registers are all RAZ/WI. */ - return MEMTX_OK; + return true; case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff: { int irq = offset - GICD_IPRIORITYR; if (irq < GIC_INTERNAL || irq >= s->num_irq) { - return MEMTX_OK; + return true; } gicd_write_ipriorityr(s, attrs, irq, value); gicv3_update(s, irq, 1); - return MEMTX_OK; + return true; } default: - return MEMTX_ERROR; + return false; } } -static MemTxResult gicd_readw(GICv3State *s, hwaddr offset, - uint64_t *data, MemTxAttrs attrs) +static bool gicd_readw(GICv3State *s, hwaddr offset, + uint64_t *data, MemTxAttrs attrs) { /* Only GICD_SETSPI_NSR, GICD_CLRSPI_NSR, GICD_SETSPI_SR and GICD_SETSPI_NSR * support 16 bit accesses, and those registers are all part of the @@ -319,11 +332,11 @@ static MemTxResult gicd_readw(GICv3State *s, hwaddr offset, * implement (ie for us GICD_TYPER.MBIS == 0), so for us they are * reserved. */ - return MEMTX_ERROR; + return false; } -static MemTxResult gicd_writew(GICv3State *s, hwaddr offset, - uint64_t value, MemTxAttrs attrs) +static bool gicd_writew(GICv3State *s, hwaddr offset, + uint64_t value, MemTxAttrs attrs) { /* Only GICD_SETSPI_NSR, GICD_CLRSPI_NSR, GICD_SETSPI_SR and GICD_SETSPI_NSR * support 16 bit accesses, and those registers are all part of the @@ -331,11 +344,11 @@ static MemTxResult gicd_writew(GICv3State *s, hwaddr offset, * implement (ie for us GICD_TYPER.MBIS == 0), so for us they are * reserved. */ - return MEMTX_ERROR; + return false; } -static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, - uint64_t *data, MemTxAttrs attrs) +static bool gicd_readl(GICv3State *s, hwaddr offset, + uint64_t *data, MemTxAttrs attrs) { /* Almost all GICv3 distributor registers are 32-bit. * Note that WO registers must return an UNKNOWN value on reads, @@ -363,7 +376,7 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, } else { *data = s->gicd_ctlr; } - return MEMTX_OK; + return true; case GICD_TYPER: { /* For this implementation: @@ -387,61 +400,61 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, *data = (1 << 25) | (1 << 24) | (sec_extn << 10) | (0xf << 19) | itlinesnumber; - return MEMTX_OK; + return true; } case GICD_IIDR: /* We claim to be an ARM r0p0 with a zero ProductID. * This is the same as an r0p0 GIC-500. */ *data = gicv3_iidr(); - return MEMTX_OK; + return true; case GICD_STATUSR: /* RAZ/WI for us (this is an optional register and our implementation * does not track RO/WO/reserved violations to report them to the guest) */ *data = 0; - return MEMTX_OK; + return true; case GICD_IGROUPR ... GICD_IGROUPR + 0x7f: { int irq; if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) { *data = 0; - return MEMTX_OK; + return true; } /* RAZ/WI for SGIs, PPIs, unimplemented irqs */ irq = (offset - GICD_IGROUPR) * 8; if (irq < GIC_INTERNAL || irq >= s->num_irq) { *data = 0; - return MEMTX_OK; + return true; } *data = *gic_bmp_ptr32(s->group, irq); - return MEMTX_OK; + return true; } case GICD_ISENABLER ... GICD_ISENABLER + 0x7f: *data = gicd_read_bitmap_reg(s, attrs, s->enabled, NULL, offset - GICD_ISENABLER); - return MEMTX_OK; + return true; case GICD_ICENABLER ... GICD_ICENABLER + 0x7f: *data = gicd_read_bitmap_reg(s, attrs, s->enabled, NULL, offset - GICD_ICENABLER); - return MEMTX_OK; + return true; case GICD_ISPENDR ... GICD_ISPENDR + 0x7f: *data = gicd_read_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge1, offset - GICD_ISPENDR); - return MEMTX_OK; + return true; case GICD_ICPENDR ... GICD_ICPENDR + 0x7f: *data = gicd_read_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge2, offset - GICD_ICPENDR); - return MEMTX_OK; + return true; case GICD_ISACTIVER ... GICD_ISACTIVER + 0x7f: *data = gicd_read_bitmap_reg(s, attrs, s->active, mask_nsacr_ge2, offset - GICD_ISACTIVER); - return MEMTX_OK; + return true; case GICD_ICACTIVER ... GICD_ICACTIVER + 0x7f: *data = gicd_read_bitmap_reg(s, attrs, s->active, mask_nsacr_ge2, offset - GICD_ICACTIVER); - return MEMTX_OK; + return true; case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff: { int i, irq = offset - GICD_IPRIORITYR; @@ -452,12 +465,12 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, value |= gicd_read_ipriorityr(s, attrs, i); } *data = value; - return MEMTX_OK; + return true; } case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff: /* RAZ/WI since affinity routing is always enabled */ *data = 0; - return MEMTX_OK; + return true; case GICD_ICFGR ... GICD_ICFGR + 0xff: { /* Here only the even bits are used; odd bits are RES0 */ @@ -466,7 +479,7 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, if (irq < GIC_INTERNAL || irq >= s->num_irq) { *data = 0; - return MEMTX_OK; + return true; } /* Since our edge_trigger bitmap is one bit per irq, we only need @@ -478,7 +491,7 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, value = extract32(value, (irq & 0x1f) ? 16 : 0, 16); value = half_shuffle32(value) << 1; *data = value; - return MEMTX_OK; + return true; } case GICD_IGRPMODR ... GICD_IGRPMODR + 0xff: { @@ -489,16 +502,16 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, * security enabled and this is an NS access */ *data = 0; - return MEMTX_OK; + return true; } /* RAZ/WI for SGIs, PPIs, unimplemented irqs */ irq = (offset - GICD_IGRPMODR) * 8; if (irq < GIC_INTERNAL || irq >= s->num_irq) { *data = 0; - return MEMTX_OK; + return true; } *data = *gic_bmp_ptr32(s->grpmod, irq); - return MEMTX_OK; + return true; } case GICD_NSACR ... GICD_NSACR + 0xff: { @@ -507,7 +520,7 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, if (irq < GIC_INTERNAL || irq >= s->num_irq) { *data = 0; - return MEMTX_OK; + return true; } if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) { @@ -515,17 +528,17 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, * security enabled and this is an NS access */ *data = 0; - return MEMTX_OK; + return true; } *data = s->gicd_nsacr[irq / 16]; - return MEMTX_OK; + return true; } case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf: case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf: /* RAZ/WI since affinity routing is always enabled */ *data = 0; - return MEMTX_OK; + return true; case GICD_IROUTER ... GICD_IROUTER + 0x1fdf: { uint64_t r; @@ -537,26 +550,26 @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset, } else { *data = (uint32_t)r; } - return MEMTX_OK; + return true; } case GICD_IDREGS ... GICD_IDREGS + 0x2f: /* ID registers */ *data = gicv3_idreg(offset - GICD_IDREGS); - return MEMTX_OK; + return true; case GICD_SGIR: /* WO registers, return unknown value */ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid guest read from WO register at offset " TARGET_FMT_plx "\n", __func__, offset); *data = 0; - return MEMTX_OK; + return true; default: - return MEMTX_ERROR; + return false; } } -static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, - uint64_t value, MemTxAttrs attrs) +static bool gicd_writel(GICv3State *s, hwaddr offset, + uint64_t value, MemTxAttrs attrs) { /* Almost all GICv3 distributor registers are 32-bit. Note that * RO registers must ignore writes, not abort. @@ -600,68 +613,68 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, s->gicd_ctlr &= ~(GICD_CTLR_EN_GRP1S | GICD_CTLR_ARE_NS); } gicv3_full_update(s); - return MEMTX_OK; + return true; } case GICD_STATUSR: /* RAZ/WI for our implementation */ - return MEMTX_OK; + return true; case GICD_IGROUPR ... GICD_IGROUPR + 0x7f: { int irq; if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) { - return MEMTX_OK; + return true; } /* RAZ/WI for SGIs, PPIs, unimplemented irqs */ irq = (offset - GICD_IGROUPR) * 8; if (irq < GIC_INTERNAL || irq >= s->num_irq) { - return MEMTX_OK; + return true; } *gic_bmp_ptr32(s->group, irq) = value; gicv3_update(s, irq, 32); - return MEMTX_OK; + return true; } case GICD_ISENABLER ... GICD_ISENABLER + 0x7f: gicd_write_set_bitmap_reg(s, attrs, s->enabled, NULL, offset - GICD_ISENABLER, value); - return MEMTX_OK; + return true; case GICD_ICENABLER ... GICD_ICENABLER + 0x7f: gicd_write_clear_bitmap_reg(s, attrs, s->enabled, NULL, offset - GICD_ICENABLER, value); - return MEMTX_OK; + return true; case GICD_ISPENDR ... GICD_ISPENDR + 0x7f: gicd_write_set_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge1, offset - GICD_ISPENDR, value); - return MEMTX_OK; + return true; case GICD_ICPENDR ... GICD_ICPENDR + 0x7f: gicd_write_clear_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge2, offset - GICD_ICPENDR, value); - return MEMTX_OK; + return true; case GICD_ISACTIVER ... GICD_ISACTIVER + 0x7f: gicd_write_set_bitmap_reg(s, attrs, s->active, NULL, offset - GICD_ISACTIVER, value); - return MEMTX_OK; + return true; case GICD_ICACTIVER ... GICD_ICACTIVER + 0x7f: gicd_write_clear_bitmap_reg(s, attrs, s->active, NULL, offset - GICD_ICACTIVER, value); - return MEMTX_OK; + return true; case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff: { int i, irq = offset - GICD_IPRIORITYR; if (irq < GIC_INTERNAL || irq + 3 >= s->num_irq) { - return MEMTX_OK; + return true; } for (i = irq; i < irq + 4; i++, value >>= 8) { gicd_write_ipriorityr(s, attrs, i, value); } gicv3_update(s, irq, 4); - return MEMTX_OK; + return true; } case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff: /* RAZ/WI since affinity routing is always enabled */ - return MEMTX_OK; + return true; case GICD_ICFGR ... GICD_ICFGR + 0xff: { /* Here only the odd bits are used; even bits are RES0 */ @@ -669,7 +682,7 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, uint32_t mask, oldval; if (irq < GIC_INTERNAL || irq >= s->num_irq) { - return MEMTX_OK; + return true; } /* Since our edge_trigger bitmap is one bit per irq, our input @@ -687,7 +700,7 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, oldval = *gic_bmp_ptr32(s->edge_trigger, (irq & ~0x1f)); value = (oldval & ~mask) | (value & mask); *gic_bmp_ptr32(s->edge_trigger, irq & ~0x1f) = value; - return MEMTX_OK; + return true; } case GICD_IGRPMODR ... GICD_IGRPMODR + 0xff: { @@ -697,16 +710,16 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, /* RAZ/WI if security disabled, or if * security enabled and this is an NS access */ - return MEMTX_OK; + return true; } /* RAZ/WI for SGIs, PPIs, unimplemented irqs */ irq = (offset - GICD_IGRPMODR) * 8; if (irq < GIC_INTERNAL || irq >= s->num_irq) { - return MEMTX_OK; + return true; } *gic_bmp_ptr32(s->grpmod, irq) = value; gicv3_update(s, irq, 32); - return MEMTX_OK; + return true; } case GICD_NSACR ... GICD_NSACR + 0xff: { @@ -714,41 +727,41 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, int irq = (offset - GICD_NSACR) * 4; if (irq < GIC_INTERNAL || irq >= s->num_irq) { - return MEMTX_OK; + return true; } if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) { /* RAZ/WI if security disabled, or if * security enabled and this is an NS access */ - return MEMTX_OK; + return true; } s->gicd_nsacr[irq / 16] = value; /* No update required as this only affects access permission checks */ - return MEMTX_OK; + return true; } case GICD_SGIR: /* RES0 if affinity routing is enabled */ - return MEMTX_OK; + return true; case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf: case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf: /* RAZ/WI since affinity routing is always enabled */ - return MEMTX_OK; + return true; case GICD_IROUTER ... GICD_IROUTER + 0x1fdf: { uint64_t r; int irq = (offset - GICD_IROUTER) / 8; if (irq < GIC_INTERNAL || irq >= s->num_irq) { - return MEMTX_OK; + return true; } /* Write half of the 64-bit register */ r = gicd_read_irouter(s, attrs, irq); r = deposit64(r, (offset & 7) ? 32 : 0, 32, value); gicd_write_irouter(s, attrs, irq, r); - return MEMTX_OK; + return true; } case GICD_IDREGS ... GICD_IDREGS + 0x2f: case GICD_TYPER: @@ -757,14 +770,14 @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset, qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid guest write to RO register at offset " TARGET_FMT_plx "\n", __func__, offset); - return MEMTX_OK; + return true; default: - return MEMTX_ERROR; + return false; } } -static MemTxResult gicd_writell(GICv3State *s, hwaddr offset, - uint64_t value, MemTxAttrs attrs) +static bool gicd_writeq(GICv3State *s, hwaddr offset, + uint64_t value, MemTxAttrs attrs) { /* Our only 64-bit registers are GICD_IROUTER<n> */ int irq; @@ -773,14 +786,14 @@ static MemTxResult gicd_writell(GICv3State *s, hwaddr offset, case GICD_IROUTER ... GICD_IROUTER + 0x1fdf: irq = (offset - GICD_IROUTER) / 8; gicd_write_irouter(s, attrs, irq, value); - return MEMTX_OK; + return true; default: - return MEMTX_ERROR; + return false; } } -static MemTxResult gicd_readll(GICv3State *s, hwaddr offset, - uint64_t *data, MemTxAttrs attrs) +static bool gicd_readq(GICv3State *s, hwaddr offset, + uint64_t *data, MemTxAttrs attrs) { /* Our only 64-bit registers are GICD_IROUTER<n> */ int irq; @@ -789,9 +802,9 @@ static MemTxResult gicd_readll(GICv3State *s, hwaddr offset, case GICD_IROUTER ... GICD_IROUTER + 0x1fdf: irq = (offset - GICD_IROUTER) / 8; *data = gicd_read_irouter(s, attrs, irq); - return MEMTX_OK; + return true; default: - return MEMTX_ERROR; + return false; } } @@ -799,7 +812,7 @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data, unsigned size, MemTxAttrs attrs) { GICv3State *s = (GICv3State *)opaque; - MemTxResult r; + bool r; switch (size) { case 1: @@ -812,14 +825,14 @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data, r = gicd_readl(s, offset, data, attrs); break; case 8: - r = gicd_readll(s, offset, data, attrs); + r = gicd_readq(s, offset, data, attrs); break; default: - r = MEMTX_ERROR; + r = false; break; } - if (r == MEMTX_ERROR) { + if (!r) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid guest read at offset " TARGET_FMT_plx "size %u\n", __func__, offset, size); @@ -829,19 +842,18 @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data, * trigger the guest-error logging but don't return it to * the caller, or we'll cause a spurious guest data abort. */ - r = MEMTX_OK; *data = 0; } else { trace_gicv3_dist_read(offset, *data, size, attrs.secure); } - return r; + return MEMTX_OK; } MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data, unsigned size, MemTxAttrs attrs) { GICv3State *s = (GICv3State *)opaque; - MemTxResult r; + bool r; switch (size) { case 1: @@ -854,14 +866,14 @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data, r = gicd_writel(s, offset, data, attrs); break; case 8: - r = gicd_writell(s, offset, data, attrs); + r = gicd_writeq(s, offset, data, attrs); break; default: - r = MEMTX_ERROR; + r = false; break; } - if (r == MEMTX_ERROR) { + if (!r) { qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid guest write at offset " TARGET_FMT_plx "size %u\n", __func__, offset, size); @@ -871,11 +883,10 @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data, * trigger the guest-error logging but don't return it to * the caller, or we'll cause a spurious guest data abort. */ - r = MEMTX_OK; } else { trace_gicv3_dist_write(offset, data, size, attrs.secure); } - return r; + return MEMTX_OK; } void gicv3_dist_set_irq(GICv3State *s, int irq, int level) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 1e7ddcb94c..13df002ce4 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -2470,172 +2470,6 @@ static const MemoryRegionOps nvic_sysreg_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static MemTxResult nvic_sysreg_ns_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size, - MemTxAttrs attrs) -{ - MemoryRegion *mr = opaque; - - if (attrs.secure) { - /* S accesses to the alias act like NS accesses to the real region */ - attrs.secure = 0; - return memory_region_dispatch_write(mr, addr, value, - size_memop(size) | MO_TE, attrs); - } else { - /* NS attrs are RAZ/WI for privileged, and BusFault for user */ - if (attrs.user) { - return MEMTX_ERROR; - } - return MEMTX_OK; - } -} - -static MemTxResult nvic_sysreg_ns_read(void *opaque, hwaddr addr, - uint64_t *data, unsigned size, - MemTxAttrs attrs) -{ - MemoryRegion *mr = opaque; - - if (attrs.secure) { - /* S accesses to the alias act like NS accesses to the real region */ - attrs.secure = 0; - return memory_region_dispatch_read(mr, addr, data, - size_memop(size) | MO_TE, attrs); - } else { - /* NS attrs are RAZ/WI for privileged, and BusFault for user */ - if (attrs.user) { - return MEMTX_ERROR; - } - *data = 0; - return MEMTX_OK; - } -} - -static const MemoryRegionOps nvic_sysreg_ns_ops = { - .read_with_attrs = nvic_sysreg_ns_read, - .write_with_attrs = nvic_sysreg_ns_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static MemTxResult nvic_systick_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size, - MemTxAttrs attrs) -{ - NVICState *s = opaque; - MemoryRegion *mr; - - /* Direct the access to the correct systick */ - mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systick[attrs.secure]), 0); - return memory_region_dispatch_write(mr, addr, value, - size_memop(size) | MO_TE, attrs); -} - -static MemTxResult nvic_systick_read(void *opaque, hwaddr addr, - uint64_t *data, unsigned size, - MemTxAttrs attrs) -{ - NVICState *s = opaque; - MemoryRegion *mr; - - /* Direct the access to the correct systick */ - mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systick[attrs.secure]), 0); - return memory_region_dispatch_read(mr, addr, data, size_memop(size) | MO_TE, - attrs); -} - -static const MemoryRegionOps nvic_systick_ops = { - .read_with_attrs = nvic_systick_read, - .write_with_attrs = nvic_systick_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - - -static MemTxResult ras_read(void *opaque, hwaddr addr, - uint64_t *data, unsigned size, - MemTxAttrs attrs) -{ - if (attrs.user) { - return MEMTX_ERROR; - } - - switch (addr) { - case 0xe10: /* ERRIIDR */ - /* architect field = Arm; product/variant/revision 0 */ - *data = 0x43b; - break; - case 0xfc8: /* ERRDEVID */ - /* Minimal RAS: we implement 0 error record indexes */ - *data = 0; - break; - default: - qemu_log_mask(LOG_UNIMP, "Read RAS register offset 0x%x\n", - (uint32_t)addr); - *data = 0; - break; - } - return MEMTX_OK; -} - -static MemTxResult ras_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size, - MemTxAttrs attrs) -{ - if (attrs.user) { - return MEMTX_ERROR; - } - - switch (addr) { - default: - qemu_log_mask(LOG_UNIMP, "Write to RAS register offset 0x%x\n", - (uint32_t)addr); - break; - } - return MEMTX_OK; -} - -static const MemoryRegionOps ras_ops = { - .read_with_attrs = ras_read, - .write_with_attrs = ras_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -/* - * Unassigned portions of the PPB space are RAZ/WI for privileged - * accesses, and fault for non-privileged accesses. - */ -static MemTxResult ppb_default_read(void *opaque, hwaddr addr, - uint64_t *data, unsigned size, - MemTxAttrs attrs) -{ - qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n", - (uint32_t)addr); - if (attrs.user) { - return MEMTX_ERROR; - } - *data = 0; - return MEMTX_OK; -} - -static MemTxResult ppb_default_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size, - MemTxAttrs attrs) -{ - qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n", - (uint32_t)addr); - if (attrs.user) { - return MEMTX_ERROR; - } - return MEMTX_OK; -} - -static const MemoryRegionOps ppb_default_ops = { - .read_with_attrs = ppb_default_read, - .write_with_attrs = ppb_default_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid.min_access_size = 1, - .valid.max_access_size = 8, -}; - static int nvic_post_load(void *opaque, int version_id) { NVICState *s = opaque; @@ -2851,108 +2685,14 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp) s->num_prio_bits = arm_feature(&s->cpu->env, ARM_FEATURE_V7) ? 8 : 2; - if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), errp)) { - return; - } - sysbus_connect_irq(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), 0, - qdev_get_gpio_in_named(dev, "systick-trigger", - M_REG_NS)); - - if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY)) { - /* We couldn't init the secure systick device in instance_init - * as we didn't know then if the CPU had the security extensions; - * so we have to do it here. - */ - object_initialize_child(OBJECT(dev), "systick-reg-s", - &s->systick[M_REG_S], TYPE_SYSTICK); - - if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_S]), errp)) { - return; - } - sysbus_connect_irq(SYS_BUS_DEVICE(&s->systick[M_REG_S]), 0, - qdev_get_gpio_in_named(dev, "systick-trigger", - M_REG_S)); - } - /* - * This device provides a single sysbus memory region which - * represents the whole of the "System PPB" space. This is the - * range from 0xe0000000 to 0xe00fffff and includes the NVIC, - * the System Control Space (system registers), the systick timer, - * and for CPUs with the Security extension an NS banked version - * of all of these. - * - * The default behaviour for unimplemented registers/ranges - * (for instance the Data Watchpoint and Trace unit at 0xe0001000) - * is to RAZ/WI for privileged access and BusFault for non-privileged - * access. - * - * The NVIC and System Control Space (SCS) starts at 0xe000e000 - * and looks like this: - * 0x004 - ICTR - * 0x010 - 0xff - systick - * 0x100..0x7ec - NVIC - * 0x7f0..0xcff - Reserved - * 0xd00..0xd3c - SCS registers - * 0xd40..0xeff - Reserved or Not implemented - * 0xf00 - STIR - * - * Some registers within this space are banked between security states. - * In v8M there is a second range 0xe002e000..0xe002efff which is the - * NonSecure alias SCS; secure accesses to this behave like NS accesses - * to the main SCS range, and non-secure accesses (including when - * the security extension is not implemented) are RAZ/WI. - * Note that both the main SCS range and the alias range are defined - * to be exempt from memory attribution (R_BLJT) and so the memory - * transaction attribute always matches the current CPU security - * state (attrs.secure == env->v7m.secure). In the nvic_sysreg_ns_ops - * wrappers we change attrs.secure to indicate the NS access; so - * generally code determining which banked register to use should - * use attrs.secure; code determining actual behaviour of the system - * should use env->v7m.secure. - * - * The container covers the whole PPB space. Within it the priority - * of overlapping regions is: - * - default region (for RAZ/WI and BusFault) : -1 - * - system register regions : 0 - * - systick : 1 - * This is because the systick device is a small block of registers - * in the middle of the other system control registers. + * This device provides a single memory region which covers the + * sysreg/NVIC registers from 0xE000E000 .. 0xE000EFFF, with the + * exception of the systick timer registers 0xE000E010 .. 0xE000E0FF. */ - memory_region_init(&s->container, OBJECT(s), "nvic", 0x100000); - memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s, - "nvic-default", 0x100000); - memory_region_add_subregion_overlap(&s->container, 0, &s->defaultmem, -1); memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s, "nvic_sysregs", 0x1000); - memory_region_add_subregion(&s->container, 0xe000, &s->sysregmem); - - memory_region_init_io(&s->systickmem, OBJECT(s), - &nvic_systick_ops, s, - "nvic_systick", 0xe0); - - memory_region_add_subregion_overlap(&s->container, 0xe010, - &s->systickmem, 1); - - if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) { - memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s), - &nvic_sysreg_ns_ops, &s->sysregmem, - "nvic_sysregs_ns", 0x1000); - memory_region_add_subregion(&s->container, 0x2e000, &s->sysreg_ns_mem); - memory_region_init_io(&s->systick_ns_mem, OBJECT(s), - &nvic_sysreg_ns_ops, &s->systickmem, - "nvic_systick_ns", 0xe0); - memory_region_add_subregion_overlap(&s->container, 0x2e010, - &s->systick_ns_mem, 1); - } - - if (cpu_isar_feature(aa32_ras, s->cpu)) { - memory_region_init_io(&s->ras_mem, OBJECT(s), - &ras_ops, s, "nvic_ras", 0x1000); - memory_region_add_subregion(&s->container, 0x5000, &s->ras_mem); - } - - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->sysregmem); } static void armv7m_nvic_instance_init(Object *obj) @@ -2961,12 +2701,6 @@ static void armv7m_nvic_instance_init(Object *obj) NVICState *nvic = NVIC(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - object_initialize_child(obj, "systick-reg-ns", &nvic->systick[M_REG_NS], - TYPE_SYSTICK); - /* We can't initialize the secure systick here, as we don't know - * yet if we need it. - */ - sysbus_init_irq(sbd, &nvic->excpout); qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1); qdev_init_gpio_in_named(dev, nvic_systick_trigger, "systick-trigger", |