From ed1e7817cc9dbe013fbcaf1da201a6a46ea9e39e Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Wed, 19 Feb 2020 16:10:13 +0000 Subject: [PATCH] vmm: Workaround double reboot triggered by the kernel The kernel does not adhere to the ACPI specification (probably to work around broken hardware) and rather than busy looping after requesting an ACPI reset it will attempt to reset by other mechanisms (such as i8042 reset.) In order to trigger a reset the devices write to an EventFd (called reset_evt.) This is used by the VMM to identify if a reset is requested and make the VM reboot. As the reset_evt is part of the VMM and reused for both the old and new VM it is possible for the newly booted VM to immediately get reset as there is an old event sitting in the EventFd. The simplest solution is to "drain" the reset_evt EventFd on reboot to make sure that there is no spurious events in the EventFd. Fixes: #783 Signed-off-by: Rob Bradford --- vmm/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index bce04caea..28fa28283 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -296,6 +296,12 @@ impl Vmm { let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?; let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?; + // The Linux kernel fires off an i8042 reset after doing the ACPI reset so there may be + // an event sitting in the shared reset_evt. Without doing this we get very early reboots + // during the boot process. + if self.reset_evt.read().is_ok() { + warn!("Spurious second reset event received. Ignoring."); + } self.vm = Some(Vm::new(config, exit_evt, reset_evt, self.vmm_path.clone())?); }