Skip to content

Commit 043098e

Browse files
committed
fix(vcpu): Don't treat KVM_EXIT_{SHUTDOWN,HLT} as successful termination
This is almost a pure revert of commit 3a9a1ac ("exit with success code on certain KVM_EXIT events") which added code that treats KVM_EXIT_SHUTDOWN and KVM_EXIT_HLT as successful VM terminations. KVM_EXIT_SHUTDOWN is an exit code that KVM uses when an x86 CPU triple faults. KVM_EXIT_HLT is the exit code that KVM uses when the guest executes a HALT x86 instruction and KVM doesn't emulate the irqchip. Since we're using the in-kernel irqchip we should never see a KVM_EXIT_HLT exit, as HALT instructions are emulated by KVM and do not cause userspace exits. Do not return Ok(VcpuEmulation::Stopped) for these exit types since that ends up propagating an FcExitCode::Ok code to the main thread, even though these are abnormal terminations (especially the triple-fault one). Remove special handling for these x86-specific exit reasons and treat them as any other unexpected exit reason. Also, replace an incorrect comment that says that vCPUs exit with KVM_EXIT_SHUTDOWN or KVM_EXIT_HLT when the guest issues a reboot. On x86 the guest asks for a CPU reset via the i8042 controller which Firecracker intercepts and kills the VM. On ARM KVM exits to userspace with the reason KVM_EXIT_SYSTEM_EVENT (which we already handle correctly). Fixes: 3a9a1ac ("exit with success code on certain KVM_EXIT events") Signed-off-by: Ilias Stamatis <[email protected]>
1 parent 2c2b2c0 commit 043098e

File tree

1 file changed

+14
-14
lines changed

1 file changed

+14
-14
lines changed

src/vmm/src/vstate/vcpu.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,9 @@ impl Vcpu {
226226
Ok(VcpuEmulation::Handled) => (),
227227
// Emulation was interrupted, check external events.
228228
Ok(VcpuEmulation::Interrupted) => break,
229-
// If the guest was rebooted or halted:
230-
// - vCPU0 will always exit out of `KVM_RUN` with KVM_EXIT_SHUTDOWN or KVM_EXIT_HLT.
231-
// - the other vCPUs won't ever exit out of `KVM_RUN`, but they won't consume CPU.
232-
// So we pause vCPU0 and send a signal to the emulation thread to stop the VMM.
229+
// The guest requested a SHUTDOWN or RESET. This is ARM
230+
// specific. On x86 the i8042 emulation signals the main thread
231+
// directly without calling Vcpu::exit().
233232
Ok(VcpuEmulation::Stopped) => return self.exit(FcExitCode::Ok),
234233
// If the emulation requests a pause lets do this
235234
#[cfg(feature = "gdb")]
@@ -440,14 +439,6 @@ fn handle_kvm_exit(
440439
}
441440
Ok(VcpuEmulation::Handled)
442441
}
443-
VcpuExit::Hlt => {
444-
info!("Received KVM_EXIT_HLT signal");
445-
Ok(VcpuEmulation::Stopped)
446-
}
447-
VcpuExit::Shutdown => {
448-
info!("Received KVM_EXIT_SHUTDOWN signal");
449-
Ok(VcpuEmulation::Stopped)
450-
}
451442
// Documentation specifies that below kvm exits are considered
452443
// errors.
453444
VcpuExit::FailEntry(hardware_entry_failure_reason, cpu) => {
@@ -697,10 +688,19 @@ pub(crate) mod tests {
697688
fn test_handle_kvm_exit() {
698689
let (_, _, mut vcpu) = setup_vcpu(0x1000);
699690
let res = handle_kvm_exit(&mut vcpu.kvm_vcpu.peripherals, Ok(VcpuExit::Hlt));
700-
assert_eq!(res.unwrap(), VcpuEmulation::Stopped);
691+
assert_eq!(
692+
format!("{:?}", res.unwrap_err()),
693+
format!("{:?}", EmulationError::UnhandledKvmExit("Hlt".to_string()))
694+
);
701695

702696
let res = handle_kvm_exit(&mut vcpu.kvm_vcpu.peripherals, Ok(VcpuExit::Shutdown));
703-
assert_eq!(res.unwrap(), VcpuEmulation::Stopped);
697+
assert_eq!(
698+
format!("{:?}", res.unwrap_err()),
699+
format!(
700+
"{:?}",
701+
EmulationError::UnhandledKvmExit("Shutdown".to_string())
702+
)
703+
);
704704

705705
let res = handle_kvm_exit(
706706
&mut vcpu.kvm_vcpu.peripherals,

0 commit comments

Comments
 (0)