vmm: support injecting NMI

Inject NMI interrupt when needed, by call ioctl KVM_NMI.

Signed-off-by: Yi Wang <foxywang@tencent.com>
This commit is contained in:
Yi Wang 2023-12-11 17:57:25 +08:00 committed by Rob Bradford
parent f40dd4a993
commit c72bf0b32d
7 changed files with 93 additions and 2 deletions

View file

@ -278,6 +278,11 @@ pub enum HypervisorCpuError {
#[cfg(feature = "sev_snp")]
#[error("Failed to set sev control register: {0}")]
SetSevControlRegister(#[source] anyhow::Error),
/// Error injecting NMI
///
#[error("Failed to inject NMI")]
Nmi(#[source] anyhow::Error),
}
#[derive(Debug)]
@ -505,4 +510,12 @@ pub trait Vcpu: Send + Sync {
fn set_sev_control_register(&self, _reg: u64) -> Result<()> {
unimplemented!()
}
#[cfg(target_arch = "x86_64")]
///
/// Trigger NMI interrupt
///
fn nmi(&self) -> Result<()> {
unimplemented!()
}
}

View file

@ -105,6 +105,15 @@ pub use {
#[cfg(target_arch = "x86_64")]
const KVM_CAP_SGX_ATTRIBUTE: u32 = 196;
#[cfg(target_arch = "x86_64")]
use vmm_sys_util::ioctl_io_nr;
#[cfg(all(not(feature = "tdx"), target_arch = "x86_64"))]
use vmm_sys_util::ioctl_ioc_nr;
#[cfg(target_arch = "x86_64")]
ioctl_io_nr!(KVM_NMI, kvm_bindings::KVMIO, 0x9a);
#[cfg(feature = "tdx")]
const KVM_EXIT_TDX: u32 = 50;
#[cfg(feature = "tdx")]
@ -2312,6 +2321,23 @@ impl cpu::Vcpu for KvmVcpu {
Ok(_) => Ok(()),
}
}
#[cfg(target_arch = "x86_64")]
///
/// Trigger NMI interrupt
///
fn nmi(&self) -> cpu::Result<()> {
match self.fd.nmi() {
Err(e) => {
if e.errno() == libc::EIO {
Ok(())
} else {
Err(cpu::HypervisorCpuError::Nmi(e.into()))
}
}
Ok(_) => Ok(()),
}
}
}
impl KvmVcpu {