Hello,

I've been trying to make sparc-rtems5 demo programs work on the latest QEMU/Leon3 model, and I've finally succeeded.

Currently, if you run a demo program like ticker.exe on the upstream QEMU master branch using the leon3_generic model, the program exits very early on because it cannot find the interrupt controller by parsing the AMBA APB entries, leading to `bsp_fatal()` in bsps/sparc/leon3/start/amba.c:98 .

I tracked this down to the memcpy failing to copy the APB struct from the AMBA PNP table when it makes its local copy in bsps/shared/grlib/amba/ambapp.c, roughly around line 253. Using a debugger, the result in apb_buf after the memfunc() call is always:

{ id = 0x01010101, iobase = 0x0. }

..regardless of what is actually supposed to be there, for example here's the output from gdb of the two values, which should be identical:

28: (struct ambapp_pnp_apb)(*apb) = {id = 0x100c023, iobar = 0x10fff1}
29: apb_buf = {id = 0x1010101, iobar = 0x0}

However, since the values in the apb pointer in the same code are accurate, you can replace the memfunc() call with something silly like:

unsigned int dummy[2] = { apb->id, apb->iobar };

.. and then use `dummy` instead of apb_buf where needed later in that code block and have everything work as intended.

I suspect this has to do with QEMU's memory read functions for the AHB and APB regions being declared as word (4-byte) access only, while I suspect the memcpy() function uses byte access. Notice how the corrupted values appear to be the first byte of the correct value repeated 4 times. QEMU's memory area functions are (from hw/misc/grlib_ahv_apb_pnp.c):

static uint64_t grlib_apb_pnp_read(void *opaque, hwaddr offset, unsigned size)
{
    APBPnp *apb_pnp = GRLIB_APB_PNP(opaque);
    uint32_t val;

    val = apb_pnp->regs[offset >> 2];
    trace_grlib_apb_pnp_read(offset, val);

    return val;
}

static const MemoryRegionOps grlib_apb_pnp_ops = {
    .read       = grlib_apb_pnp_read,
    .write      = grlib_apb_pnp_write,
    .endianness = DEVICE_BIG_ENDIAN,
    .impl = {
        .min_access_size = 4,
        .max_access_size = 4,
    },
};

... so the access is limited to word accesses, and it looks like the read function would need to be tweaked to allow byte access.

So this leads to some questions:

- Is my breakdown correct?
- Why is RTEMS copying this table into ram before parsing, why not just
  parse it directly?
- Are there real systems that limit the memory that the PNP tables are
  stored in to word access only? Or is this a quirk of QEMU?
- Why does there not *appear* to be an issue when parsing the AHB
  entries, when they use the same access pattern? (perhaps there is and
  I've just been lucky so far)
- On real leon3 hardware, which behavior is more correct? the QEMU model
  or the one RTEMS expects?

I suspect this is a case where QEMU needs to be updated to allow byte access, but would appreciate any clarification the RTEMS team can give.

Thanks for any insight,
john.c

--
John Clemens <john.clem...@jhuapl.edu>
_______________________________________________
users mailing list
users@rtems.org
http://lists.rtems.org/mailman/listinfo/users

Reply via email to