unit-testingarmqemubare-metal

How to cleanly exit QEMU after executing bare metal program without user intervention?


I am assembling a cross compiling unit testing rig for an ARM system and running the tests on a host machine with qemu-system-arm. Specifically, I'm using qemu to emulate the Stellaris LM3S6965 eval board as it contains a Cortex M3 processor like my target environment. The binary run in qemu is built with GNU Tools for ARM.

There is no OS involved. The test suite is run as a bare metal application with qemu in -nographic mode. The toolchain and the test rig itself are working fine. And the tests successfully run to completion and produce test results within qemu just fine as well.

The problem is in wrapping up qemu in an automated build tool (Rake in this case). Other than keyboard commands I have not yet found a good way to cause qemu to exit after the test suite runs and spits out its results. This causes the build environment to hang / rely on user intervention.

I have looked high and low and have found no good sources on how to accomplish a simple exit after program termination. I did find a couple suggestions of running qemu with the -no-reboot option and then triggering a system reset from the program running in the emulator. I have tried this. It works… kinda. I write the appropriate values to the emulated processor's reset vector after main() executes, and this does trigger a reset. After running the test suite qemu reports catching a system reset. However, it reports this as a hardware error, dumps register contents, and then exits angry (error message below). While this does accomplish exiting after the test suite runs, it then breaks the automated build script due to qemu exiting with an error condition.

qemu: hardware error: System reset

I'd like to avoid hacking the insertion of keyboard commands into the build to simulate user intervention. I'd also like to avoid relying on qemu exiting in an error state.

It seems I'm close to a clean exit but not quite there. Searching for the qemu error message (above) has produced no relevant documentation other than tangentially related bug reports.

Is there a mechanism for causing qemu to exit after main() returns in a bare metal program that I'm missing? Will this -no-reboot + system reset strategy work? If so, what else is necessary to allow qemu to exit cleanly?


Solution

  • The cleanest option for me was to grab the source for a stable version of Qemu close to the one we were already using. The following refers to version 1.1.2 of the Qemu source.

    I modified the emulation of the reset vector handling for the Cortex M3 + Stellaris LM3S6965 eval board in armv7m_nvic.c. I replaced the hw_error() call with a call to qemu_system_reset_request(). This internal system call will reset a virtual machine but also responds to the -no-reboot command line option for a clean shutdown as discussed in my original question.

    These build instructions worked for me after grabbing a snapshot of Qemu 1.1.2. I encountered several build errors, but web searches quickly resolved each issue.