RISC-V QEMU - Debug an emulated bare metal program

3,254 views
Skip to first unread message

Sandeep Vijayakumar

unread,
Oct 12, 2017, 6:38:12 AM10/12/17
to RISC-V SW Dev
Hi all, 

I would like to debug a bare metal program using RISCV QEMU and GDB. RISCV QEMU shows that it can emulate both spike as well as SiFive U500.

1. To build a bare metal program, I need to know the memory layout of spike and U500. Does anyone have this information or a sample linker file? Also I would like to have the peripheral base addresses so that I can emulate UART using U500.

2. Do you have a startup.s file for these platforms?

I could not find a sample in the git repository. 

Thanks
Sandeep
Message has been deleted

evan...@maximintegrated.com

unread,
Oct 16, 2017, 11:53:32 AM10/16/17
to RISC-V SW Dev
Edit: Mistakes in the first post, reposting. Sorry


So far, this code from Martin Schoeberl is the best example I've found of running bare metal on spike. Maybe you will have success with this on risc-v qemu too, I haven't tried that yet. Here's the original topic on this: https://groups.google.com/a/groups.riscv.org/forum/#!topic/sw-dev/xZ4V-RUydTA


Also, this is the best documentation I've been able to find on Spike: https://github.com/poweihuang17/Documentation_Spike


Unfortunately, nothing about the low-level plumbing of spike, including its memory map, appears to be documented. This week I have been trying to load my own bare metal program into spike's starting PC, 0x200, only to discover that spike places its own, undocumented boot/debug ROM here. Loading the elf into this space fails because this part of the memory map is read only, causing a trap_store_access_fault. I'm going through the code adn documenting how it boots up and initializes the memory map. I will share that when complete.

Notice that Martin's example has an entry point at spike's default DRAM location, 0x8000_0000.

Sandeep Vijayakumar

unread,
Oct 20, 2017, 6:26:38 AM10/20/17
to RISC-V SW Dev
Thanks a lot for the pointer. I modified my linker file and startup file. Now I can debug my sample baremetal using Qemu and GDB.

Eva Chen

unread,
Apr 18, 2018, 7:51:31 AM4/18/18
to RISC-V SW Dev
Hi,

I want to run a bare metal program on riscv-qemu too.
I use the test binary which comes from this website this code from Martin Schoeberl 
However, I meet some error when I use the test binary file for qemu-system-riscv64
 

 
$ qemu-system-riscv64 -kernel test -nographic
 
Trying to execute code outside RAM or ROM at 0x0000000000000000
This usually means one of the following happened:

(1) You told QEMU to execute a kernel for the wrong machine type, and it crashed on startup (eg trying to run a raspberry pi kernel on a versatilepb QEMU machine)
(2) You didn't give QEMU a kernel or BIOS filename at all, and QEMU executed a ROM full of no-op instructions until it fell off the end
(3) Your guest kernel has a bug and crashed by jumping off into nowhere

This is almost always one of the first two, so check your command line and that you are using the right type of kernel for this machine.
If you think option (3) is likely then you can try debugging your guest with the -d debug options; in particular -d guest_errors will cause the log to include a dump of the guest register state at this point.

Execution cannot continue; stopping here.



Have you faced this kind of error? 
I am new here, I will be grateful for any suggestion, thanks. 
 

Sandeep Vijayakumar於 2017年10月20日星期五 UTC+8下午6時26分38秒寫道:

Tommy Murphy

unread,
Apr 18, 2018, 10:12:33 AM4/18/18
to RISC-V SW Dev
I don't think that qemu simulates ram at 0x00000000_00000000 I think it's at some other address but can't remember which. Perhaps 0x00000000_01000000?
If that's the problem then you'll need a linker script suitable for the qemu memory map.
I'm sure that such exists already but again not sure where.

Hope this helps.

Foivos Zakkak

unread,
Apr 19, 2018, 8:48:34 AM4/19/18
to RISC-V SW Dev
Hello,

This is normal. What actually happens is that the program gets executed but since there is no proper handling for termination it just continues executing code after the last instruction, which results in the exception you observe.
Try running qemu as follows:
qemu-system-riscv64 -s -S -kernel test

This will block execution right at the beginning of the bare-metal program and will allow you to attach gdb on it.
Now start gdb:
riscv64-unknown-linux-gnu-gdb
and attach to qemu:
(gdb) target remote localhost:1234
Now you can inspect the memory and the program execution.

Good luck,
Foivos

Eva Chen

unread,
Apr 20, 2018, 11:20:19 PM4/20/18
to RISC-V SW Dev
Thanks for your replies!!

Now I understand the error is after finishing the execution of test binary file.
Is there any way to avoid this error?
 
What if I want to conduct a hello word binary file which crosses compiled by riscv64-unknown-elf-gcc
How to link this hello.c file to linker.ld? Is there any method to run it on the bare metal version of RISCV QEMU (qemu-riscv64)?


Sincerely,
Eva

Foivos Zakkak於 2018年4月19日星期四 UTC+8下午8時48分34秒寫道:

Michael Clark

unread,
Apr 21, 2018, 5:06:35 AM4/21/18
to Eva Chen, RISC-V SW Dev


> On 21/04/2018, at 3:20 PM, Eva Chen <debby...@gmail.com> wrote:
>
> Thanks for your replies!!
>
> Now I understand the error is after finishing the execution of test binary file.
> Is there any way to avoid this error?
>
> What if I want to conduct a hello word binary file which crosses compiled by riscv64-unknown-elf-gcc
> How to link this hello.c file to linker.ld? Is there any method to run it on the bare metal version of RISCV QEMU (qemu-riscv64)?

Here is an example program that runs in the spike_v1.9.1 or spike_v1.10 machines.

- https://github.com/michaeljclark/riscv-probe

riscv-probe is a minimal bare-metal example derived from riscv-pk/bbl but does not include S-mode support and includes a much smaller library for console via HTIF (Host Target Interface). You could easily add uart support by using uart.c from riscv-pk. Take a look at the Makefile and linker script. You can run it as follows (it compiles and runs on riscv32 and riscv64 assuming you have the toolchains installed).

$ qemu-system-riscv32 -nographic -machine spike_v1.10 -kernel bin/riscv32/probe-htif
$ qemu-system-riscv64 -nographic -machine spike_v1.10 -kernel bin/riscv64/probe-htif

The HTIF interface in the spike machine has a shutdown method so that writing a command to a specific IO address, tells qemu to exit.

The virt machine on the other hand implements a SiFive Test device in device-tree which is used for finishing verification tests in simulators. riscv-linux can already detect this in device-tree and uses this for shutdown support in the ‘virt’ machine. The ‘virt’ machine does not use HTIF and instead has a NS16550A UART console. This is why we needed a different mechanism to “power off” the simulation. See the memory map here:

- https://github.com/riscv/riscv-qemu/blob/riscv-all/hw/riscv/virt.c#L46-L55

We have plans to add generic GPIO shutdown and reset support to some of the boards which is already supported by Linux. This is essentially a special MMIO address that in real life would be connected to the reset line or power/sleep function of the device. The reality is that each board usually has its own GPIO device and you need to know while GPIO lines are wired to reset and to the power management unit for power off or sleep.

There are also bare metal examples in the freedom-e-sdk that target the ’sifive_e’ machine which emulates parts of the HiFive1. The e31 examples run on the ’sifive_e’ machine.

- https://github.com/sifive/freedom-e-sdk

The ’sifive_e’ machine in QEMU and HiFive1 has no shutdown mechanism so after performing IOs and printing results to the console, at the end of the program one simply enters a busy loop. e.g.

loop: wfi
j loop

You may also like to look at ZephrOS. It is a bare metal realtime OS. It requires you download an SDK with an older version of QEMU. The the arty_fe310 examples run unmodified in the latest version of QEMU sing the ’sifive_e’ machine which models the E31/E51 Series processors, which includes SiFive’s FE310G000. The emulation is not complete but it is enough to run the ‘bsp’ (board support package) and several of the examples:

- https://github.com/fractalclone/zephyr-riscv

Each machine has its own memory map. QEMU tries to emulate the distinct memory map of each system. i.e. spike binaries will run in the ‘spike’ machine, HiFive1 binaries run in the ’sifive_e’ machine and we are working towards getting the HiFive Unleashed binaries to run in the ’sifive_u’ machine (currently folk are using the ‘virt’ machine to run Linux)

- https://github.com/riscv/riscv-qemu/blob/riscv-all/hw/riscv/spike.c#L48-L52
- https://github.com/riscv/riscv-qemu/blob/riscv-all/hw/riscv/virt.c#L46-L55
- https://github.com/riscv/riscv-qemu/blob/riscv-all/hw/riscv/sifive_e.c#L55-L75

Some notes:

- You can inspect the reset vector code and linker scripts to see where the board ROM jumps to after reset. Look for reset_vec in the files above.
- The ROMs in the current boards are at 0x1000.
- The Spike board and virt boards jump to 0x80000000 which is the base address of the RAM.
- The SiFive E Series board jumps to 0x20400000 which is a location in XIP EEPROM non volatile memory. The E Series only has a small scratchpad at 0x80000000
- The SiFive U Series board needs more work, i.e. we need to add an emulated Cadence Ethernet controller and various other devices

The wiki has a high level overview of the 5 machines that are there now:

- https://github.com/riscv/riscv-qemu/wiki
> --
> You received this message because you are subscribed to the Google Groups "RISC-V SW Dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sw-dev+un...@groups.riscv.org.
> To post to this group, send email to sw-...@groups.riscv.org.
> Visit this group at https://groups.google.com/a/groups.riscv.org/group/sw-dev/.
> To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/sw-dev/f1cd2867-4abe-46da-975d-f803cd445445%40groups.riscv.org.

Reply all
Reply to author
Forward
0 new messages