Skip to content
Merged
Show file tree
Hide file tree
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
21 changes: 12 additions & 9 deletions alioth/src/hv/kvm/kvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use std::arch::x86_64::CpuidResult;
use std::collections::HashMap;
use std::fs::File;
use std::mem::{size_of, transmute};
use std::num::NonZero;
use std::os::fd::OwnedFd;
use std::path::Path;
use std::ptr::null_mut;
Expand Down Expand Up @@ -78,8 +79,6 @@ pub enum KvmError {
MmapVcpuFd { error: std::io::Error },
#[snafu(display("Failed to check KVM capability"))]
CheckCap { error: std::io::Error },
#[snafu(display("KVM Capability {ext:?} not supported"))]
NotSupported { ext: KvmCap },
#[snafu(display("Failed to enable capability {cap:?}"))]
EnableCap { cap: KvmCap, error: std::io::Error },
#[snafu(display("Failed to create guest memfd"))]
Expand Down Expand Up @@ -141,13 +140,8 @@ impl Kvm {
})
}

pub fn check_extension(&self, id: KvmCap) -> Result<i32, KvmError> {
let ret = unsafe { kvm_check_extension(&self.fd, id) }.context(kvm_error::CheckCap)?;
if ret == 0 {
kvm_error::NotSupported { ext: id }.fail()
} else {
Ok(ret)
}
pub fn check_extension(&self, id: KvmCap) -> Result<NonZero<i32>> {
check_extension(&self.fd, id)
}
}

Expand All @@ -163,3 +157,12 @@ impl Hypervisor for Kvm {
Kvm::get_supported_cpuids(self)
}
}

fn check_extension(fd: &OwnedFd, id: KvmCap) -> Result<NonZero<i32>> {
let ret = unsafe { kvm_check_extension(fd, id) }.context(kvm_error::CheckCap)?;
if let Some(v) = NonZero::new(ret) {
Ok(v)
} else {
error::Capability { cap: id.name() }.fail()
}
}
11 changes: 5 additions & 6 deletions alioth/src/hv/kvm/kvm_x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,17 @@ impl Kvm {
.map(map_f)
.collect();

// Enable KVM_FEATURE_MSI_EXT_DEST_ID if KVM_CAP_X2APIC_API is supported
let ext = self.check_extension(KvmCap::X2APIC_API)?;
let flag = KvmX2apicApiFlag::from_bits_retain(ext as u64);
let x2apic_flags =
KvmX2apicApiFlag::USE_32BIT_IDS | KvmX2apicApiFlag::DISABLE_BROADCAST_QUIRK;
let leaf_features = CpuidIn {
func: KVM_CPUID_FEATURES,
index: None,
};
if let Some(entry) = cpuids.get_mut(&leaf_features)
&& flag.contains(x2apic_flags)
&& let Ok(ext) = self.check_extension(KvmCap::X2APIC_API)
&& KvmX2apicApiFlag::from_bits_retain(ext.get() as u64).contains(
KvmX2apicApiFlag::USE_32BIT_IDS | KvmX2apicApiFlag::DISABLE_BROADCAST_QUIRK,
)
{
// Enable KVM_FEATURE_MSI_EXT_DEST_ID if KVM_CAP_X2APIC_API is supported
entry.eax |= KvmCpuidFeature::MSI_EXT_DEST_ID.bits();
}

Expand Down
28 changes: 9 additions & 19 deletions alioth/src/hv/kvm/vm/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ mod x86_64;
use std::collections::HashMap;
use std::fmt::{self, Display, Formatter};
use std::io::ErrorKind;
use std::num::NonZero;
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd};
use std::os::unix::thread::JoinHandleExt;
use std::sync::Arc;
Expand All @@ -36,7 +37,7 @@ use snafu::ResultExt;
use crate::arch::sev::{SevPolicy, SnpPageType, SnpPolicy};
use crate::ffi;
use crate::hv::kvm::vcpu::KvmVcpu;
use crate::hv::kvm::{KvmError, kvm_error};
use crate::hv::kvm::{KvmError, check_extension, kvm_error};
use crate::hv::{
Error, IoeventFd, IoeventFdRegistry, IrqFd, IrqSender, Kvm, MemMapOption, MsiSender, Result,
Vm, VmConfig, VmMemory, error,
Expand All @@ -49,11 +50,10 @@ use crate::sys::kvm::{
KVM_IRQ_ROUTING_IRQCHIP, KVM_IRQ_ROUTING_MSI, KvmCap, KvmEnableCap, KvmEncRegion, KvmIoEventFd,
KvmIoEventFdFlag, KvmIrqRouting, KvmIrqRoutingEntry, KvmIrqRoutingIrqchip, KvmIrqRoutingMsi,
KvmIrqfd, KvmIrqfdFlag, KvmMemFlag, KvmMemoryAttribute, KvmMemoryAttributes, KvmMsi,
KvmUserspaceMemoryRegion, KvmUserspaceMemoryRegion2, kvm_check_extension, kvm_create_vm,
kvm_enable_cap, kvm_get_vcpu_mmap_size, kvm_ioeventfd, kvm_irqfd,
kvm_memory_encrypt_reg_region, kvm_memory_encrypt_unreg_region, kvm_set_gsi_routing,
kvm_set_memory_attributes, kvm_set_user_memory_region, kvm_set_user_memory_region2,
kvm_signal_msi,
KvmUserspaceMemoryRegion, KvmUserspaceMemoryRegion2, kvm_create_vm, kvm_enable_cap,
kvm_get_vcpu_mmap_size, kvm_ioeventfd, kvm_irqfd, kvm_memory_encrypt_reg_region,
kvm_memory_encrypt_unreg_region, kvm_set_gsi_routing, kvm_set_memory_attributes,
kvm_set_user_memory_region, kvm_set_user_memory_region2, kvm_signal_msi,
};

#[cfg(target_arch = "aarch64")]
Expand Down Expand Up @@ -124,13 +124,8 @@ impl VmInner {
Ok(())
}

pub fn check_extension(&self, id: KvmCap) -> Result<i32, KvmError> {
let ret = unsafe { kvm_check_extension(&self.fd, id) }.context(kvm_error::CheckCap)?;
if ret == 0 {
kvm_error::NotSupported { ext: id }.fail()
} else {
Ok(ret)
}
pub fn check_extension(&self, id: KvmCap) -> Result<NonZero<i32>> {
check_extension(&self.fd, id)
}

pub fn enable_cap(&self, cap: &KvmEnableCap) -> Result<(), KvmError> {
Expand Down Expand Up @@ -692,12 +687,7 @@ impl Vm for KvmVm {
&self,
#[cfg(target_arch = "aarch64")] devid: u32,
) -> Result<Self::MsiSender> {
if self.vm.check_extension(KvmCap::SIGNAL_MSI)? == 0 {
return error::Capability {
cap: "KVM_CAP_SIGNAL_MSI",
}
.fail();
}
self.vm.check_extension(KvmCap::SIGNAL_MSI)?;
Ok(KvmMsiSender {
vm: self.vm.clone(),
#[cfg(target_arch = "aarch64")]
Expand Down
2 changes: 1 addition & 1 deletion alioth/src/hv/kvm/vm/vm_x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ impl KvmVm {
}
}
Some(Coco::AmdSnp { .. }) => {
let bitmap = self.vm.check_extension(KvmCap::EXIT_HYPERCALL)?;
let bitmap = self.vm.check_extension(KvmCap::EXIT_HYPERCALL)?.get();
let request = KvmEnableCap {
cap: KvmCap::EXIT_HYPERCALL,
args: [bitmap as _, 0, 0, 0],
Expand Down
8 changes: 8 additions & 0 deletions alioth/src/utils/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ macro_rules! c_enum {
pub const fn raw(self) -> $TyName {
self.0
}

#[allow(dead_code)]
pub const fn name(self) -> &'static str {
match self {
$($EnumName::$VARIANT => stringify!($VARIANT),)*
_ => "Unknown"
}
}
}

impl ::core::fmt::Debug for $EnumName {
Expand Down