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

谁都会走 提交于 2019-11-30 19:42:05

I recommend to use Angel interface for ARM processores. It is very helpful for debugging. You can read something about it on ARM Info Center. Especially look at operation angel_SWIreason_ReportException (0x18) and parameter ADP_Stopped_ApplicationExit to which QEMU will understand that your application has ended.

Don't forget to run QEMU with -semihosting argument, like this:

qemu-system-arm -nographic -semihosting -kernel your_binary

Here is the code to tell QEMU to stop (you have to use some assembler):

register int reg0 asm("r0");
register int reg1 asm("r1");

reg0 = 0x18;    // angel_SWIreason_ReportException
reg1 = 0x20026; // ADP_Stopped_ApplicationExit

asm("svc 0x00123456");  // make semihosting call

You can also look at my project at github where I used it.

Typically you need to do whatever on the hardware would cause a system shutdown (power off); QEMU will make that do an 'exit QEMU'. Unfortunately not all of the hardware we emulate implements a power-off mechanism (and sometimes it's not wired up in the QEMU model, though that's generally an easy bug to fix).

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.

aarch64 semihosting exit

https://stackoverflow.com/a/40957928/895245 gave A32, here is A64:

.global main
main:
    /* 0x20026 == ADP_Stopped_ApplicationExit */
    mov x1, #0x26
    movk x1, #2, lsl #16
    str x1, [sp,#0]

    /* Exit status code. Host QEMU process exits with that status. */
    mov x0, #0
    str x0, [sp,#8]

    /* x1 contains the address of parameter block.
     * Any memory address could be used. */
    mov x1, sp

    /* SYS_EXIT */
    mov w0, #0x18

    /* Do the semihosting call on A64. */
    hlt 0xf000

Here is an example on GitHub:

Documentation has moved to: https://developer.arm.com/docs/100863/latest

The current ARMv7M qEmu (based on TI Stellaris LM3S6965 Microcontroller) supports reset from AICRCR register (Application Interrupt and Reset Control Register). Writing to the SYSRESETREQ bit of this register asserts a signal to the outer system that requests a reset.

Writing to AICRCR requires to write 0x5FA to the VECTKEY field, otherwise the processor ignores the write.

This line makes ARMv7M qEmu resets.

SCB->AIRCR = (0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk;

To prevent qEmu to indefinitly reboot, you can add the qEmu argument -no-reboot.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!