U-Boot's shared i.MX6 identification code reads PERIPHBASE + 0x4 on MCIMX6UL-EVK. The first private peripheral page is currently unmapped, so that access causes a data abort before the console is ready.
The GIC-400 register map reserves offsets 0x0000 through 0x0fff and specifies read-as-zero, write-ignored accesses to reserved locations. Model that page in the private peripheral device. Reference: GIC-400 TRM (ARM DDI 0471B), sections 3.1 and 3.2 https://documentation-service.arm.com/static/5e8f15e27100066a414f7424 Signed-off-by: Bin Meng <[email protected]> --- Changes in v3: - New include/hw/cpu/a15mpcore.h | 6 +++++ hw/cpu/a15mpcore.c | 53 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/include/hw/cpu/a15mpcore.h b/include/hw/cpu/a15mpcore.h index 138f491c22..581bd147fb 100644 --- a/include/hw/cpu/a15mpcore.h +++ b/include/hw/cpu/a15mpcore.h @@ -29,6 +29,11 @@ #define TYPE_A15MPCORE_PRIV "a15mpcore_priv" OBJECT_DECLARE_SIMPLE_TYPE(A15MPPrivState, A15MPCORE_PRIV) +typedef struct A15MPReservedState { + SysBusDevice parent_obj; + MemoryRegion iomem; +} A15MPReservedState; + struct A15MPPrivState { /*< private >*/ SysBusDevice parent_obj; @@ -38,6 +43,7 @@ struct A15MPPrivState { uint32_t num_irq; MemoryRegion container; + A15MPReservedState reserved; GICState gic; }; diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c index 28cda55ccf..0c379e58af 100644 --- a/hw/cpu/a15mpcore.c +++ b/hw/cpu/a15mpcore.c @@ -28,6 +28,44 @@ #include "system/kvm.h" #include "target/arm/gtimer.h" +#define TYPE_A15MPCORE_RESERVED "a15mpcore-reserved" +DECLARE_INSTANCE_CHECKER(A15MPReservedState, A15MPCORE_RESERVED, + TYPE_A15MPCORE_RESERVED) + +static uint64_t a15mp_reserved_read(void *opaque, hwaddr offset, unsigned size) +{ + return 0; +} + +static void a15mp_reserved_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ +} + +static const MemoryRegionOps a15mp_reserved_ops = { + .read = a15mp_reserved_read, + .write = a15mp_reserved_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + +static void a15mp_reserved_initfn(Object *obj) +{ + A15MPReservedState *s = A15MPCORE_RESERVED(obj); + + memory_region_init_io(&s->iomem, obj, &a15mp_reserved_ops, s, + "a15mp-reserved", 0x1000); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem); +} + +static void a15mp_reserved_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "Reserved private peripheral page"; + /* This device is an internal child of a15mpcore_priv */ + dc->user_creatable = false; +} + static void a15mp_priv_set_irq(void *opaque, int irq, int level) { A15MPPrivState *s = (A15MPPrivState *)opaque; @@ -43,6 +81,8 @@ static void a15mp_priv_initfn(Object *obj) memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000); sysbus_init_mmio(sbd, &s->container); + object_initialize_child(obj, "reserved", &s->reserved, + TYPE_A15MPCORE_RESERVED); object_initialize_child(obj, "gic", &s->gic, gic_class_name()); qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2); } @@ -131,6 +171,12 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp) * 0x5600-0x57ff -- GIC virtual interface control for CPU 3 * 0x6000-0x7fff -- GIC virtual CPU interface */ + if (!sysbus_realize(SYS_BUS_DEVICE(&s->reserved), errp)) { + return; + } + memory_region_add_subregion(&s->container, 0, + sysbus_mmio_get_region( + SYS_BUS_DEVICE(&s->reserved), 0)); memory_region_add_subregion(&s->container, 0x1000, sysbus_mmio_get_region(busdev, 0)); memory_region_add_subregion(&s->container, 0x2000, @@ -171,6 +217,13 @@ static void a15mp_priv_class_init(ObjectClass *klass, const void *data) } static const TypeInfo a15mp_types[] = { + { + .name = TYPE_A15MPCORE_RESERVED, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(A15MPReservedState), + .instance_init = a15mp_reserved_initfn, + .class_init = a15mp_reserved_class_init, + }, { .name = TYPE_A15MPCORE_PRIV, .parent = TYPE_SYS_BUS_DEVICE, -- 2.53.0
