On Sun, 4 Oct 2026 at 10:05, Bin Meng <[email protected]> wrote:
>
> 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]>

In the interests of un-stalling this, let's trust the in-practice
observed by u-boot behaviour over the TRMs. I have some code
review comments below on the specifics.

> +#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)
> +{
> +}

We should make these read and write functions do a
qemu_log_mask(LOG_GUEST_ERROR, ...) since guests accessing
the region is a bug.

> +
> +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;
> +}

Defining a whole new class is overkill; just init the memory region
in the a15mp_priv_initfn() (it doesn't need to be a sysbus MR).

>  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
>       */

We should extend this comment to mention why we model the reserved area
the way we do, e.g.

  The Cortex-A15 and A7 TRMs suggest that the reserved region at offset 0
  either will (A15) or "can" (A7) trigger a bus error; the TRM for the
  related GIC-400 documents RAZ/WI behaviour. In practice, u-boot for the
  A7-based i.MX6 boards tries to access this space, and does not fall over
  on the real hardware. So we model them as RAZ/WI.

thanks
-- PMM

Reply via email to