4

I'm trying to add Qemu to my continuous integration pipeline to test various initrd artifacts. I've already discovered that I can run Qemu like this:

qemu-system-x86_64 \
    -machine q35 \
    -drive if=pflash,format=raw,file=OVMF_CODE.fd,readonly \
    -drive if=pflash,format=raw,file=OVMF_VARS.fd \
    -kernel vmlinuz-4.4.0-121-generic \
    -initrd my-initramfs.cpio.xz \
    -nographic

...and cause qemu-system-x86_64 to exit with status 0 if I do this in my init script:

# poweroff -f

This is works because the init script doesn't exit -- it invokes poweroff -f and sleeps "forever" or until Qemu does a "Power Down":

ACPI: Preparing to enter system sleep state S5
reboot: Power down

I would like to be able to detect problems in the init script by forcing an exit on error via set -eu. Exiting the init script (correctly) causes a kernel panic but the qemu-system-x86_64 process hangs forever.

How can I keep it from hanging forever? How do I get the Qemu host to detect a kernel panic in the Qemu guest?

Further clarification:

The nature of my application is security-sensitive; i.e., configuring/compiling the linux kernel is "allowed", but passing kernel parameters is not. To put a fine point on it, CMDLINE_OVERRIDE is enabled.

3

I've got something that's working:

  • Configure (and build) the kernel with CONFIG_PVPANIC=y; this produces a kernel with compiled-in support for the pvpanic device.
  • Invoke qemu-system-x86_64 with the -device pvpanic option; this instructs Qemu to catch (and exit on) a kernel panic.

A kernel panic causes qemu-system-x86_64 to exit successfully (return status 0), but at least it's not hanging anymore.

Many thanks to @dsstorefile1 for pointing me in the right direction.

References:

3

-no-reboot + kernel.panic=-1

It also returns 0 like pvpanic, but has the following advantages:

  • no need to recompile anything, just a boot parameter
  • works on arm and aarch64 -M virt as well as x86, while pvpanic seems x86-specific since it is under arch/x86

Tested with this setup.

Track the panic symbol with GDB

Another way to go about this might be to detect when the address of the panic function is reached, and then try to make QEMU quit.

You can definitely break GDB on panic as explained at: https://stackoverflow.com/questions/11408041/how-to-debug-the-linux-kernel-with-gdb-and-qemu/33203642#33203642

But then TODO: how to make QEMU exit with status 1? Using monitor quit, from inside GDB, which forwards quit to the QEMU monitor from GDB, gets really close, but not quite since it does not exit with status 0.

gem5 does this tracking by default natively, which is pretty awesome.

This happens at: https://github.com/gem5/gem5/blob/1da285dfcc31b904afc27e440544d006aae25b38/src/arch/arm/linux/system.cc#L73

Maybe QEMU devs can take some inspiration from this technique and implement something similar.

  • 1
    this is a great answer and I've upvoted you accordingly. The only reason I'm not denoting yours as THE answer is because of the security-sensitive caveats that were not part of my original question. I've updated the question to that effect; I do apologize for omitting that detail initially. – rubicks Aug 13 '18 at 14:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.