diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index 3cc27a1e44..c4bc3deedf 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -169,16 +169,22 @@ static void sl_nand_init(Object *obj) { SLNANDState *s = SL_NAND(obj); SysBusDevice *dev = SYS_BUS_DEVICE(obj); - DriveInfo *nand; s->ctl = 0; + + memory_region_init_io(&s->iomem, obj, &sl_ops, s, "sl", 0x40); + sysbus_init_mmio(dev, &s->iomem); +} + +static void sl_nand_realize(DeviceState *dev, Error **errp) +{ + SLNANDState *s = SL_NAND(dev); + DriveInfo *nand; + /* FIXME use a qdev drive property instead of drive_get() */ nand = drive_get(IF_MTD, 0, 0); s->nand = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL, s->manf_id, s->chip_id); - - memory_region_init_io(&s->iomem, obj, &sl_ops, s, "sl", 0x40); - sysbus_init_mmio(dev, &s->iomem); } /* Spitz Keyboard */ @@ -1079,6 +1085,7 @@ static void sl_nand_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_sl_nand_info; dc->props = sl_nand_properties; + dc->realize = sl_nand_realize; /* Reason: init() method uses drive_get() */ dc->user_creatable = false; } diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c index b6b00a4f58..69f9c18d73 100644 --- a/hw/intc/exynos4210_gic.c +++ b/hw/intc/exynos4210_gic.c @@ -281,9 +281,9 @@ static void exynos4210_gic_set_irq(void *opaque, int irq, int level) qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); } -static void exynos4210_gic_init(Object *obj) +static void exynos4210_gic_realize(DeviceState *dev, Error **errp) { - DeviceState *dev = DEVICE(obj); + Object *obj = OBJECT(dev); Exynos4210GicState *s = EXYNOS4210_GIC(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj); const char cpu_prefix[] = "exynos4210-gic-alias_cpu"; @@ -347,13 +347,13 @@ static void exynos4210_gic_class_init(ObjectClass *klass, void *data) DeviceClass *dc = DEVICE_CLASS(klass); dc->props = exynos4210_gic_properties; + dc->realize = exynos4210_gic_realize; } static const TypeInfo exynos4210_gic_info = { .name = TYPE_EXYNOS4210_GIC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Exynos4210GicState), - .instance_init = exynos4210_gic_init, .class_init = exynos4210_gic_class_init, }; diff --git a/hw/microblaze/xlnx-zynqmp-pmu.c b/hw/microblaze/xlnx-zynqmp-pmu.c index 999a5657cf..57dc1ccd42 100644 --- a/hw/microblaze/xlnx-zynqmp-pmu.c +++ b/hw/microblaze/xlnx-zynqmp-pmu.c @@ -62,13 +62,11 @@ static void xlnx_zynqmp_pmu_soc_init(Object *obj) { XlnxZynqMPPMUSoCState *s = XLNX_ZYNQMP_PMU_SOC(obj); - object_initialize(&s->cpu, sizeof(s->cpu), - TYPE_MICROBLAZE_CPU); - object_property_add_child(obj, "pmu-cpu", OBJECT(&s->cpu), - &error_abort); + object_initialize_child(obj, "pmu-cpu", &s->cpu, sizeof(s->cpu), + TYPE_MICROBLAZE_CPU, &error_abort, NULL); - object_initialize(&s->intc, sizeof(s->intc), TYPE_XLNX_PMU_IO_INTC); - qdev_set_parent_bus(DEVICE(&s->intc), sysbus_get_default()); + sysbus_init_child_obj(obj, "intc", &s->intc, sizeof(s->intc), + TYPE_XLNX_PMU_IO_INTC); } static void xlnx_zynqmp_pmu_soc_realize(DeviceState *dev, Error **errp) diff --git a/hw/sd/bcm2835_sdhost.c b/hw/sd/bcm2835_sdhost.c index 4df4de7d67..1b760b2a7c 100644 --- a/hw/sd/bcm2835_sdhost.c +++ b/hw/sd/bcm2835_sdhost.c @@ -179,9 +179,11 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s) uint32_t value = 0; int n; int is_read; + int is_write; is_read = (s->cmd & SDCMD_READ_CMD) != 0; - if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus))) { + is_write = (s->cmd & SDCMD_WRITE_CMD) != 0; + if (s->datacnt != 0 && (is_write || sdbus_data_ready(&s->sdbus))) { if (is_read) { n = 0; while (s->datacnt && s->fifo_len < BCM2835_SDHOST_FIFO_LEN) { @@ -201,8 +203,11 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s) if (n != 0) { bcm2835_sdhost_fifo_push(s, value); s->status |= SDHSTS_DATA_FLAG; + if (s->config & SDHCFG_DATA_IRPT_EN) { + s->status |= SDHSTS_SDIO_IRPT; + } } - } else { /* write */ + } else if (is_write) { /* write */ n = 0; while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) { if (n == 0) { @@ -223,11 +228,18 @@ static void bcm2835_sdhost_fifo_run(BCM2835SDHostState *s) s->edm &= ~SDEDM_FSM_MASK; s->edm |= SDEDM_FSM_DATAMODE; trace_bcm2835_sdhost_edm_change("datacnt 0", s->edm); - - if ((s->cmd & SDCMD_WRITE_CMD) && + } + if (is_write) { + /* set block interrupt at end of each block transfer */ + if (s->hbct && s->datacnt % s->hbct == 0 && (s->config & SDHCFG_BLOCK_IRPT_EN)) { s->status |= SDHSTS_BLOCK_IRPT; } + /* set data interrupt after each transfer */ + s->status |= SDHSTS_DATA_FLAG; + if (s->config & SDHCFG_DATA_IRPT_EN) { + s->status |= SDHSTS_SDIO_IRPT; + } } } diff --git a/target/arm/helper.c b/target/arm/helper.c index 0604a0efbe..22d812240a 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -17,6 +17,7 @@ #include "exec/semihost.h" #include "sysemu/kvm.h" #include "fpu/softfloat.h" +#include "qemu/range.h" #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */ @@ -9669,6 +9670,20 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, } if (address < base || address > base + rmask) { + /* + * Address not in this region. We must check whether the + * region covers addresses in the same page as our address. + * In that case we must not report a size that covers the + * whole page for a subsequent hit against a different MPU + * region or the background region, because it would result in + * incorrect TLB hits for subsequent accesses to addresses that + * are in this MPU region. + */ + if (ranges_overlap(base, rmask, + address & TARGET_PAGE_MASK, + TARGET_PAGE_SIZE)) { + *page_size = 1; + } continue; } @@ -9888,6 +9903,22 @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address, sattrs->srvalid = true; sattrs->sregion = r; } + } else { + /* + * Address not in this region. We must check whether the + * region covers addresses in the same page as our address. + * In that case we must not report a size that covers the + * whole page for a subsequent hit against a different MPU + * region or the background region, because it would result + * in incorrect TLB hits for subsequent accesses to + * addresses that are in this MPU region. + */ + if (limit >= base && + ranges_overlap(base, limit - base + 1, + addr_page_base, + TARGET_PAGE_SIZE)) { + sattrs->subpage = true; + } } } } @@ -9963,6 +9994,21 @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, } if (address < base || address > limit) { + /* + * Address not in this region. We must check whether the + * region covers addresses in the same page as our address. + * In that case we must not report a size that covers the + * whole page for a subsequent hit against a different MPU + * region or the background region, because it would result in + * incorrect TLB hits for subsequent accesses to addresses that + * are in this MPU region. + */ + if (limit >= base && + ranges_overlap(base, limit - base + 1, + addr_page_base, + TARGET_PAGE_SIZE)) { + *is_subpage = true; + } continue; }