RTEMS5, QEMU, Leon3, and AMBA PnP tables

John Clemens john.clemens at jhuapl.edu
Tue Feb 22 14:43:20 UTC 2022


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 
     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 Clemens <john.clemens at jhuapl.edu>

More information about the users mailing list