qemu-system-x86_64: Reboot loop after Machine->Reset
Host environment
- Operating system: Arch Linux
- OS/kernel version: 5.15.7
- Architecture: amd64
- QEMU flavor: qemu-system-x86_64
- QEMU version: QEMU emulator version 6.1.94 (v6.2.0-rc4)
- QEMU command line:
qemu-system-x86_64 -M q35
Emulated/Virtualized environment
- Operating system: Not needed.
- OS/kernel version:
- Architecture:
Description of problem
When using tcg, the virtual machine goes into a reboot loop after the VM is rebooted through UI->Machine->Reboot menu, or through outb(0xcf9, 0xf). There might be other reboot mechanisms that result in the same loop.
The loop doesn't occur when using kvm: qemu-system-x86_64 -M q35 -enable-kvm
Steps to reproduce
- Run the command. (The one without -enable-kvm.)
- From the UI, click on Machine->Reset.
- See that the VM locks up, instead of resetting.
Additional information
The reboot loop occurs because a variable defined by Seabios cannot be updated, possibly because the memory is read-only.
The variable in question is HaveRunPost. If HaveRunPost is non-zero, the BIOS follows the resume path. When the reset is clicked, the BIOS does indeed gain control and follow the resume path because HaveRunPost is 2. The control ends up at qemu_reboot, which should reset HaveRunPost to 0 and trigger another reset, so that this second time around, the BIOS sees HaveRunPost as 0, and follows the initialization path instead.
But, even though the instruction to update HaveRunPost seems to run, the value remains non-zero (2 to be exact).
// HaveRunPost has value 2 here.
barrier();
HaveRunPost = 0;
barrier();
// If a dprintf(1, "%x\n", HaveRunPost); is placed here, the value printed is 2 and not 0!
// With kvm-enabled, this dprintf prints 0.