aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-07-23 16:15:24 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-07-23 16:15:24 +0100
commite596be90393389405c96a5c9534c4c4e2e0b5675 (patch)
tree0c77502f86cbfc16e3fbd15ea47f0c73f7b4b397
parent9ba7dd14355bb7957680d5ef764471ab102df099 (diff)
parent1ddc9b98c3cb89fe23a55ba924000fd645253e87 (diff)
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180723' into staging
target-arm queue: * spitz, exynos: fix bugs when introspecting some devices * hw/microblaze/xlnx-zynqmp-pmu: Fix introspection problem in 'xlnx, zynqmp-pmu-soc' * target/arm: Correctly handle overlapping small MPU regions * hw/sd/bcm2835_sdhost: Fix PIO mode writes # gpg: Signature made Mon 23 Jul 2018 15:40:09 BST # gpg: using RSA key 3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20180723: hw/intc/exynos4210_gic: Turn instance_init into realize function hw/arm/spitz: Move problematic nand_init() code to realize function target/arm: Correctly handle overlapping small MPU regions hw/sd/bcm2835_sdhost: Fix PIO mode writes hw/microblaze/xlnx-zynqmp-pmu: Fix introspection problem in 'xlnx, zynqmp-pmu-soc' Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/arm/spitz.c15
-rw-r--r--hw/intc/exynos4210_gic.c6
-rw-r--r--hw/microblaze/xlnx-zynqmp-pmu.c10
-rw-r--r--hw/sd/bcm2835_sdhost.c20
-rw-r--r--target/arm/helper.c46
5 files changed, 80 insertions, 17 deletions
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;
}