Skip to content

skipped unnecessary kvm_immediate_exits #4388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 2, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions src/vmm/src/vstate/vcpu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::{fmt, io, thread};
use kvm_bindings::{KVM_SYSTEM_EVENT_RESET, KVM_SYSTEM_EVENT_SHUTDOWN};
use kvm_ioctls::VcpuExit;
use libc::{c_int, c_void, siginfo_t};
use log::{error, info};
use log::{error, info, warn};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apple pay

use seccompiler::{BpfProgram, BpfProgramRef};
use utils::errno;
use utils::eventfd::EventFd;
Expand Down Expand Up @@ -341,6 +341,13 @@ impl Vcpu {
match self.event_receiver.recv() {
// Paused ---- Resume ----> Running
Ok(VcpuEvent::Resume) => {
if self.kvm_vcpu.fd.get_kvm_run().immediate_exit == 1u8 {
warn!(
"Received a VcpuEvent::Resume message with immediate_exit enabled. \
immediate_exit was disabled before proceeding"
);
self.kvm_vcpu.fd.set_kvm_immediate_exit(0);
}
// Nothing special to do.
self.response_sender
.send(VcpuResponse::Resumed)
Expand Down Expand Up @@ -445,7 +452,12 @@ impl Vcpu {
/// Runs the vCPU in KVM context and handles the kvm exit reason.
///
/// Returns error or enum specifying whether emulation was handled or interrupted.
pub fn run_emulation(&self) -> Result<VcpuEmulation, VcpuError> {
pub fn run_emulation(&mut self) -> Result<VcpuEmulation, VcpuError> {
if self.kvm_vcpu.fd.get_kvm_run().immediate_exit == 1u8 {
warn!("Requested a vCPU run with immediate_exit enabled. The operation was skipped");
self.kvm_vcpu.fd.set_kvm_immediate_exit(0);
return Ok(VcpuEmulation::Interrupted);
}
match self.emulate() {
Ok(run) => match run {
VcpuExit::MmioRead(addr, data) => {
Expand Down Expand Up @@ -1059,6 +1071,32 @@ pub mod tests {
);
}

#[test]
fn test_immediate_exit_shortcircuits_execution() {
let (_vm, mut vcpu, _) = setup_vcpu(0x1000);

vcpu.kvm_vcpu.fd.set_kvm_immediate_exit(1);
// Set a dummy value to be returned by the emulate call
*(vcpu.test_vcpu_exit_reason.lock().unwrap()) = Some(Ok(VcpuExit::Shutdown));
let result = vcpu.run_emulation().expect("Failed to run emulation");
assert_eq!(
result,
VcpuEmulation::Interrupted,
"The Immediate Exit short-circuit should have prevented the execution of emulate"
);

let event_sender = vcpu.event_sender.take().expect("vCPU already started");
let _ = event_sender.send(VcpuEvent::Resume);
vcpu.kvm_vcpu.fd.set_kvm_immediate_exit(1);
// paused is expected to coerce immediate_exit to 0 when receiving a VcpuEvent::Resume
let _ = vcpu.paused();
assert_eq!(
0,
vcpu.kvm_vcpu.fd.get_kvm_run().immediate_exit,
"Immediate Exit should have been disabled by sending Resume to a paused VM"
)
}

#[test]
fn test_vcpu_pause_resume() {
let (vcpu_handle, vcpu_exit_evt) = vcpu_configured_for_boot();
Expand Down