From 2ff97dd210ee45d89eb1858f60f441a36daf784c Mon Sep 17 00:00:00 2001 From: Changyuan Lyu Date: Sun, 16 Jun 2024 13:11:26 -0700 Subject: [PATCH 1/5] feat: add macro `c_enum` for C enum bindings Signed-off-by: Changyuan Lyu --- alioth/src/utils/utils.rs | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/alioth/src/utils/utils.rs b/alioth/src/utils/utils.rs index 4fd73b2..b4004e1 100644 --- a/alioth/src/utils/utils.rs +++ b/alioth/src/utils/utils.rs @@ -97,6 +97,54 @@ macro_rules! ffi { }}; } +#[macro_export] +macro_rules! c_enum { + ( + $(#[$attr:meta])* + $vs:vis struct $EnumName:ident($TyName:ty); + { + $($VARIANT:ident = $value:expr;)* + } + ) => { + #[repr(transparent)] + #[derive(PartialEq, Eq, Copy, Clone)] + $(#[$attr])* + $vs struct $EnumName($TyName); + + impl $EnumName { + $(pub const $VARIANT: $EnumName = $EnumName($value);)* + + pub fn raw(&self) -> $TyName { + self.0 + } + } + + impl ::core::fmt::Debug for $EnumName { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.write_str(stringify!($EnumName))?; + match *self { + $($EnumName::$VARIANT => { + f.write_str("::")?; + f.write_str(stringify!($VARIANT)) + })* + _ => { + ::core::fmt::Write::write_char(f, '(')?; + ::core::fmt::Debug::fmt(&self.0, f)?; + ::core::fmt::Write::write_char(f, ')') + } + } + } + } + + + impl From<$EnumName> for $TyName { + fn from(value: $EnumName) -> Self { + value.0 + } + } + } +} + #[macro_export] macro_rules! unsafe_impl_zerocopy { ($ty:ty, $($name:ident), +) => { From ded0d79a973d40960c04e5e21d358eaedd70f1b7 Mon Sep 17 00:00:00 2001 From: Changyuan Lyu Date: Sun, 16 Jun 2024 13:11:55 -0700 Subject: [PATCH 2/5] refactor(blk): use `c_enum` for constants Signed-off-by: Changyuan Lyu --- alioth/src/virtio/dev/blk.rs | 96 ++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/alioth/src/virtio/dev/blk.rs b/alioth/src/virtio/dev/blk.rs index 15f5f91..29fc6ce 100644 --- a/alioth/src/virtio/dev/blk.rs +++ b/alioth/src/virtio/dev/blk.rs @@ -23,25 +23,45 @@ use mio::event::Event; use mio::Registry; use zerocopy::{AsBytes, FromBytes, FromZeroes}; -use crate::impl_mmio_for_zerocopy; use crate::mem::mapped::RamBus; use crate::virtio::dev::{DevParam, Virtio}; use crate::virtio::queue::handlers::handle_desc; use crate::virtio::queue::{Descriptor, Queue, VirtQueue}; use crate::virtio::{DeviceId, IrqSender, Result, FEATURE_BUILT_IN}; +use crate::{c_enum, impl_mmio_for_zerocopy}; -pub const VIRTIO_BLK_T_IN: u32 = 0; -pub const VIRTIO_BLK_T_OUT: u32 = 1; -pub const VIRTIO_BLK_T_FLUSH: u32 = 4; -pub const VIRTIO_BLK_T_GET_ID: u32 = 8; -pub const VIRTIO_BLK_T_GET_LIFETIME: u32 = 10; -pub const VIRTIO_BLK_T_DISCARD: u32 = 11; -pub const VIRTIO_BLK_T_WRITE_ZEROES: u32 = 13; -pub const VIRTIO_BLK_T_SECURE_ERASE: u32 = 14; +c_enum! { + #[derive(FromBytes, FromZeroes)] + pub struct RequestType(u32); + { + IN = 0; + OUT = 1; + FLUSH = 4; + GET_ID = 8; + GET_LIFETIME = 10; + DISCARD = 11; + WRITE_ZEROES = 13; + SECURE_ERASE = 14; + } +} + +c_enum! { + #[derive(FromBytes, FromZeroes)] + pub struct Status(u8); + { + OK = 0; + IOERR = 1; + UNSUPP = 2; + } +} -pub const VIRTIO_BLK_S_OK: u8 = 0; -pub const VIRTIO_BLK_S_IOERR: u8 = 1; -pub const VIRTIO_BLK_S_UNSUPP: u8 = 2; +#[repr(C)] +#[derive(Debug, FromZeroes, FromBytes)] +pub struct Request { + type_: RequestType, + reserved: u32, + sector: u64, +} pub const VIRTIO_BLK_ID_SIZE: usize = 20; @@ -145,29 +165,29 @@ impl Block { let Some(buf0) = desc.readable.first() else { return Err(ErrorKind::InvalidData.into()); }; - let hdr_clone; - let header = match BlockReqHeader::ref_from(buf0) { - Some(h) => h, + let request_clone; + let request = match Request::ref_from(buf0) { + Some(r) => r, None => match FromBytes::read_from(buf0) { - Some(h) => { - hdr_clone = h; - &hdr_clone + Some(r) => { + request_clone = r; + &request_clone } None => return Err(ErrorKind::InvalidData.into()), }, }; - let offset = header.sector * SECTOR_SIZE as u64; - let w_len = match header.type_ { - VIRTIO_BLK_T_IN => { + let offset = request.sector * SECTOR_SIZE as u64; + let w_len = match request.type_ { + RequestType::IN => { let Some(buf1) = desc.writable.first_mut() else { return Err(ErrorKind::InvalidData.into()); }; let l = buf1.len(); let status = match disk.read_exact_at(buf1, offset) { - Ok(()) => VIRTIO_BLK_S_OK, + Ok(()) => Status::OK, Err(e) => { log::error!("{}: read {l} bytes from offset {offset:#x}: {e}", self.name); - VIRTIO_BLK_S_IOERR + Status::IOERR } }; let Some(buf2) = desc.writable.get_mut(1) else { @@ -176,19 +196,19 @@ impl Block { let Some(status_byte) = buf2.first_mut() else { return Err(ErrorKind::InvalidData.into()); }; - *status_byte = status; + *status_byte = status.into(); l + 1 } - VIRTIO_BLK_T_OUT => { + RequestType::OUT => { let Some(buf1) = desc.readable.get(1) else { return Err(ErrorKind::InvalidData.into()); }; let l = buf1.len(); let status = match disk.write_all_at(buf1, offset) { - Ok(()) => VIRTIO_BLK_S_OK, + Ok(()) => Status::OK, Err(e) => { log::error!("{}: write {l} bytes to offset {offset:#x}: {e}", self.name); - VIRTIO_BLK_S_IOERR + Status::IOERR } }; let Some(buf2) = desc.writable.first_mut() else { @@ -197,10 +217,10 @@ impl Block { let Some(status_byte) = buf2.first_mut() else { return Err(ErrorKind::InvalidData.into()); }; - *status_byte = status; + *status_byte = status.into(); 1 } - VIRTIO_BLK_T_FLUSH => { + RequestType::FLUSH => { // TODO flush the file let Some(w_buf) = desc.writable.last_mut() else { return Err(ErrorKind::InvalidData.into()); @@ -208,10 +228,10 @@ impl Block { let Some(status_byte) = w_buf.get_mut(0) else { return Err(ErrorKind::InvalidData.into()); }; - *status_byte = VIRTIO_BLK_S_OK; + *status_byte = Status::OK.into(); 1 } - VIRTIO_BLK_T_GET_ID => { + RequestType::GET_ID => { let Some(buf1) = desc.writable.first_mut() else { return Err(ErrorKind::InvalidData.into()); }; @@ -223,18 +243,18 @@ impl Block { let Some(status_byte) = buf2.first_mut() else { return Err(ErrorKind::InvalidData.into()); }; - *status_byte = VIRTIO_BLK_S_OK; + *status_byte = Status::OK.into(); 1 + len } _ => { - log::error!("unimplemented op: {}", header.type_); + log::error!("unimplemented op: {:#x?}", request.type_); let Some(w_buf) = desc.writable.last_mut() else { return Err(ErrorKind::InvalidData.into()); }; let Some(w_byte) = w_buf.get_mut(0) else { return Err(ErrorKind::InvalidData.into()); }; - *w_byte = VIRTIO_BLK_S_UNSUPP; + *w_byte = Status::UNSUPP.into(); 1 } }; @@ -301,11 +321,3 @@ impl Virtio for Block { }) } } - -#[repr(C)] -#[derive(Debug, FromZeroes, FromBytes)] -pub struct BlockReqHeader { - type_: u32, - reserved: u32, - sector: u64, -} From e338d79da3b3a0e40a1366203620096cfb034b46 Mon Sep 17 00:00:00 2001 From: Changyuan Lyu Date: Sun, 16 Jun 2024 13:12:46 -0700 Subject: [PATCH 3/5] refactor(kvm): use `c_enum` for VM exit constants Signed-off-by: Changyuan Lyu --- alioth/src/hv/kvm/bindings.rs | 44 +++++++++++++++++++++------------- alioth/src/hv/kvm/vcpu/vcpu.rs | 14 +++++------ alioth/src/hv/kvm/vmentry.rs | 10 ++++---- alioth/src/hv/kvm/vmexit.rs | 14 +++++------ 4 files changed, 46 insertions(+), 36 deletions(-) diff --git a/alioth/src/hv/kvm/bindings.rs b/alioth/src/hv/kvm/bindings.rs index 6660004..33c24c5 100644 --- a/alioth/src/hv/kvm/bindings.rs +++ b/alioth/src/hv/kvm/bindings.rs @@ -16,6 +16,8 @@ use std::fmt::{Debug, Formatter, Result}; use bitflags::bitflags; +use crate::c_enum; + pub const KVMIO: u8 = 0xAE; pub const KVM_API_VERSION: i32 = 12; @@ -208,45 +210,63 @@ pub struct KvmSregs2 { pub pdptrs: [u64; 4], } +c_enum! { + pub struct KvmExit(u32); + { + IO = 2; + HYPERCALL = 3; + MMIO = 6; + SHUTDOWN = 8; + } +} + #[repr(C)] #[derive(Copy, Clone)] pub struct KvmRun { pub request_interrupt_window: u8, pub immediate_exit: u8, pub padding1: [u8; 6], - pub exit_reason: u32, + pub exit_reason: KvmExit, pub ready_for_interrupt_injection: u8, pub if_flag: u8, pub flags: u16, pub cr8: u64, pub apic_base: u64, - pub exit: KvmExit, + pub exit: KvmRunExit, pub kvm_valid_regs: u64, pub kvm_dirty_regs: u64, pub s: KvmSyncRegsBlock, } #[repr(C)] #[derive(Copy, Clone)] -pub union KvmExit { - pub mmio: KvmExitMmio, - pub io: KvmExitIo, +pub union KvmRunExit { + pub mmio: KvmRunExitMmio, + pub io: KvmRunExitIo, pub hypercall: KvmRunExitHypercall, pub padding: [u8; 256], } #[repr(C)] #[derive(Debug, Clone, Copy)] -pub struct KvmExitMmio { +pub struct KvmRunExitMmio { pub phys_addr: u64, pub data: [u8; 8], pub len: u32, pub is_write: u8, } +c_enum! { + pub struct KvmExitIo(u8); + { + IN = 0; + OUT = 1; + } +} + #[repr(C)] #[derive(Debug, Clone, Copy)] -pub struct KvmExitIo { - pub direction: u8, +pub struct KvmRunExitIo { + pub direction: KvmExitIo, pub size: u8, pub port: u16, pub count: u32, @@ -268,14 +288,6 @@ pub union KvmSyncRegsBlock { pub padding: [u8; 2048], } -pub const KVM_EXIT_IO: u32 = 2; -pub const KVM_EXIT_HYPERCALL: u32 = 3; -pub const KVM_EXIT_MMIO: u32 = 6; -pub const KVM_EXIT_SHUTDOWN: u32 = 8; - -pub const KVM_EXIT_IO_IN: u8 = 0; -pub const KVM_EXIT_IO_OUT: u8 = 1; - bitflags! { #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct KvmIrqfdFlag: u32 { diff --git a/alioth/src/hv/kvm/vcpu/vcpu.rs b/alioth/src/hv/kvm/vcpu/vcpu.rs index 4a71dad..6c51c18 100644 --- a/alioth/src/hv/kvm/vcpu/vcpu.rs +++ b/alioth/src/hv/kvm/vcpu/vcpu.rs @@ -25,15 +25,13 @@ use snafu::ResultExt; use crate::ffi; use crate::hv::arch::Reg; -use crate::hv::kvm::bindings::{KvmRun, KVM_EXIT_IO, KVM_EXIT_MMIO}; +use crate::hv::kvm::bindings::{KvmExit, KvmRun}; use crate::hv::kvm::ioctls::kvm_run; use crate::hv::kvm::{kvm_error, KvmError}; use crate::hv::{error, Error, Vcpu, VmEntry, VmExit}; #[cfg(target_arch = "x86_64")] use crate::hv::{Cpuid, DtReg, DtRegVal, SReg, SegReg, SegRegVal}; -use super::bindings::{KVM_EXIT_HYPERCALL, KVM_EXIT_SHUTDOWN}; - pub(super) struct KvmRunBlock { addr: usize, size: usize, @@ -146,11 +144,11 @@ impl Vcpu for KvmVcpu { _ => Err(e).context(error::RunVcpu), }, Ok(_) => match self.kvm_run.exit_reason { - KVM_EXIT_IO => self.handle_io(), - KVM_EXIT_HYPERCALL => self.handle_hypercall(), - KVM_EXIT_MMIO => self.handle_mmio(), - KVM_EXIT_SHUTDOWN => Ok(VmExit::Shutdown), - reason => Ok(VmExit::Unknown(format!("unkown kvm exit: {:#x}", reason))), + KvmExit::IO => self.handle_io(), + KvmExit::HYPERCALL => self.handle_hypercall(), + KvmExit::MMIO => self.handle_mmio(), + KvmExit::SHUTDOWN => Ok(VmExit::Shutdown), + reason => Ok(VmExit::Unknown(format!("unkown kvm exit: {:#x?}", reason))), }, } } diff --git a/alioth/src/hv/kvm/vmentry.rs b/alioth/src/hv/kvm/vmentry.rs index fd384dc..44b13e1 100644 --- a/alioth/src/hv/kvm/vmentry.rs +++ b/alioth/src/hv/kvm/vmentry.rs @@ -12,14 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::hv::kvm::bindings::{KVM_EXIT_IO, KVM_EXIT_IO_IN, KVM_EXIT_MMIO}; +use crate::hv::kvm::bindings::{KvmExit, KvmExitIo}; use super::vcpu::KvmVcpu; impl KvmVcpu { #[cfg(target_endian = "little")] pub(super) fn entry_mmio(&mut self, data: u64) { - assert_eq!(self.kvm_run.exit_reason, KVM_EXIT_MMIO); + use crate::hv::kvm::bindings::KvmExit; + + assert_eq!(self.kvm_run.exit_reason, KvmExit::MMIO); let kvm_mmio = unsafe { &mut self.kvm_run.exit.mmio }; assert_eq!(kvm_mmio.is_write, 0); kvm_mmio.data = data.to_ne_bytes(); @@ -30,9 +32,9 @@ impl KvmVcpu { } pub(super) fn entry_io(&mut self, data: u32) { - assert_eq!(self.kvm_run.exit_reason, KVM_EXIT_IO); + assert_eq!(self.kvm_run.exit_reason, KvmExit::IO); let kvm_io = unsafe { &self.kvm_run.exit.io }; - assert_eq!(kvm_io.direction, KVM_EXIT_IO_IN); + assert_eq!(kvm_io.direction, KvmExitIo::IN); let offset = kvm_io.data_offset as usize; let count = kvm_io.count as usize; match kvm_io.size { diff --git a/alioth/src/hv/kvm/vmexit.rs b/alioth/src/hv/kvm/vmexit.rs index bd4dfb1..02b87c6 100644 --- a/alioth/src/hv/kvm/vmexit.rs +++ b/alioth/src/hv/kvm/vmexit.rs @@ -12,9 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::hv::kvm::bindings::{ - KvmMapGpaRangeFlag, KVM_EXIT_IO_IN, KVM_EXIT_IO_OUT, KVM_HC_MAP_GPA_RANGE, -}; +use crate::hv::kvm::bindings::{KvmExitIo, KvmMapGpaRangeFlag, KVM_HC_MAP_GPA_RANGE}; use crate::hv::{Error, VmExit}; use super::vcpu::KvmVcpu; @@ -41,18 +39,18 @@ impl KvmVcpu { let count = kvm_io.count as usize; assert_eq!(count, 1); let write = match (kvm_io.direction, kvm_io.size) { - (KVM_EXIT_IO_IN, _) => None, - (KVM_EXIT_IO_OUT, 1) => { + (KvmExitIo::IN, _) => None, + (KvmExitIo::OUT, 1) => { Some(unsafe { self.kvm_run.data_slice::(offset, count) }[0] as u32) } - (KVM_EXIT_IO_OUT, 2) => { + (KvmExitIo::OUT, 2) => { Some(unsafe { self.kvm_run.data_slice::(offset, count) }[0] as u32) } - (KVM_EXIT_IO_OUT, 4) => { + (KvmExitIo::OUT, 4) => { Some(unsafe { self.kvm_run.data_slice::(offset, count) }[0]) } _ => unreachable!( - "kvm_io.direction = {}, kvm_io.size = {}", + "kvm_io.direction = {:?}, kvm_io.size = {}", kvm_io.direction, kvm_io.size ), }; From feee6416b1bac61a1481a1d84d0ef971f4691690 Mon Sep 17 00:00:00 2001 From: Changyuan Lyu Date: Sun, 16 Jun 2024 13:21:59 -0700 Subject: [PATCH 4/5] refactor(kvm): use `c_enum` for capabilities Signed-off-by: Changyuan Lyu --- alioth/src/hv/kvm/bindings.rs | 19 ++++++++++++------- alioth/src/hv/kvm/ioctls.rs | 8 ++++---- alioth/src/hv/kvm/kvm.rs | 8 ++++---- alioth/src/hv/kvm/vm.rs | 13 ++++++------- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/alioth/src/hv/kvm/bindings.rs b/alioth/src/hv/kvm/bindings.rs index 33c24c5..58e0c57 100644 --- a/alioth/src/hv/kvm/bindings.rs +++ b/alioth/src/hv/kvm/bindings.rs @@ -407,12 +407,17 @@ pub struct KvmMsi { pub pad: [u8; 12usize], } -pub const KVM_CAP_NR_MEMSLOTS: u32 = 10; -pub const KVM_CAP_IRQFD: u32 = 32; -pub const KVM_CAP_SIGNAL_MSI: u32 = 77; -pub const KVM_CAP_EXIT_HYPERCALL: u32 = 201; -// pub const KVM_CAP_GUEST_MEMFD: u32 = 234; -// pub const KVM_CAP_VM_TYPES: u32 = 235; +c_enum! { + pub struct KvmCap(u32); + { + NR_MEMSLOTS = 10; + IRQFD = 32; + SIGNAL_MSI = 77; + EXIT_HYPERCALL = 201; + // GUEST_MEMFD = 234; + // VM_TYPES = 235; + } +} pub const KVM_HC_MAP_GPA_RANGE: u64 = 12; @@ -455,7 +460,7 @@ pub struct KvmEncRegion { #[repr(C)] #[derive(Debug, Clone)] pub struct KvmEnableCap { - pub cap: u32, + pub cap: KvmCap, pub flags: u32, pub args: [u64; 4], pub pad: [u8; 64], diff --git a/alioth/src/hv/kvm/ioctls.rs b/alioth/src/hv/kvm/ioctls.rs index f2e4386..aff6a13 100644 --- a/alioth/src/hv/kvm/ioctls.rs +++ b/alioth/src/hv/kvm/ioctls.rs @@ -13,9 +13,9 @@ // limitations under the License. use crate::hv::kvm::bindings::{ - KvmCpuid2, KvmCreateGuestMemfd, KvmEnableCap, KvmEncRegion, KvmIoEventFd, KvmIrqRouting, - KvmIrqfd, KvmMemoryAttributes, KvmMsi, KvmRegs, KvmSregs, KvmSregs2, KvmUserspaceMemoryRegion, - KvmUserspaceMemoryRegion2, KVMIO, + KvmCap, KvmCpuid2, KvmCreateGuestMemfd, KvmEnableCap, KvmEncRegion, KvmIoEventFd, + KvmIrqRouting, KvmIrqfd, KvmMemoryAttributes, KvmMsi, KvmRegs, KvmSregs, KvmSregs2, + KvmUserspaceMemoryRegion, KvmUserspaceMemoryRegion2, KVMIO, }; use crate::utils::ioctls::{ioctl_io, ioctl_ior, ioctl_iowr}; use crate::{ @@ -25,7 +25,7 @@ use crate::{ ioctl_none!(kvm_get_api_version, KVMIO, 0x00, 0); ioctl_write_val!(kvm_create_vm, ioctl_io(KVMIO, 0x01)); -ioctl_write_val!(kvm_check_extension, ioctl_io(KVMIO, 0x03), u32); +ioctl_write_val!(kvm_check_extension, ioctl_io(KVMIO, 0x03), KvmCap); ioctl_none!(kvm_get_vcpu_mmap_size, KVMIO, 0x04, 0); #[cfg(target_arch = "x86_64")] ioctl_writeread_buf!(kvm_get_supported_cpuid, KVMIO, 0x05, KvmCpuid2); diff --git a/alioth/src/hv/kvm/kvm.rs b/alioth/src/hv/kvm/kvm.rs index 952f762..1066644 100644 --- a/alioth/src/hv/kvm/kvm.rs +++ b/alioth/src/hv/kvm/kvm.rs @@ -43,8 +43,8 @@ use crate::hv::Cpuid; use crate::hv::{error, Coco, Hypervisor, MemMapOption, Result, VmConfig}; use bindings::{ - KvmCpuid2, KvmCpuid2Flag, KvmCpuidEntry2, KvmCreateGuestMemfd, KvmEnableCap, KVM_API_VERSION, - KVM_CAP_EXIT_HYPERCALL, KVM_MAX_CPUID_ENTRIES, KVM_X86_DEFAULT_VM, KVM_X86_SNP_VM, + KvmCap, KvmCpuid2, KvmCpuid2Flag, KvmCpuidEntry2, KvmCreateGuestMemfd, KvmEnableCap, + KVM_API_VERSION, KVM_MAX_CPUID_ENTRIES, KVM_X86_DEFAULT_VM, KVM_X86_SNP_VM, }; use ioctls::{ kvm_check_extension, kvm_create_guest_memfd, kvm_create_irqchip, kvm_create_vm, kvm_enable_cap, @@ -194,13 +194,13 @@ impl Hypervisor for Kvm { } } Coco::AmdSnp { .. } => { - let bitmap = unsafe { kvm_check_extension(&kvm_vm.vm, KVM_CAP_EXIT_HYPERCALL) } + let bitmap = unsafe { kvm_check_extension(&kvm_vm.vm, KvmCap::EXIT_HYPERCALL) } .context(kvm_error::CheckExtension { ext: "KVM_CAP_EXIT_HYPERCALL", })?; if bitmap != 0 { let request = KvmEnableCap { - cap: KVM_CAP_EXIT_HYPERCALL, + cap: KvmCap::EXIT_HYPERCALL, args: [bitmap as _, 0, 0, 0], flags: 0, pad: [0; 64], diff --git a/alioth/src/hv/kvm/vm.rs b/alioth/src/hv/kvm/vm.rs index 4edbd62..15a01d7 100644 --- a/alioth/src/hv/kvm/vm.rs +++ b/alioth/src/hv/kvm/vm.rs @@ -26,11 +26,10 @@ use snafu::ResultExt; use crate::arch::sev::{SnpPageType, SnpPolicy}; use crate::ffi; use crate::hv::kvm::bindings::{ - KvmEncRegion, KvmIoEventFd, KvmIoEventFdFlag, KvmIrqRouting, KvmIrqRoutingEntry, + KvmCap, KvmEncRegion, KvmIoEventFd, KvmIoEventFdFlag, KvmIrqRouting, KvmIrqRoutingEntry, KvmIrqRoutingIrqchip, KvmIrqRoutingMsi, KvmIrqfd, KvmIrqfdFlag, KvmMemFlag, KvmMemoryAttribute, KvmMemoryAttributes, KvmMsi, KvmUserspaceMemoryRegion, KvmUserspaceMemoryRegion2, - KVM_CAP_IRQFD, KVM_CAP_NR_MEMSLOTS, KVM_CAP_SIGNAL_MSI, KVM_IRQCHIP_IOAPIC, - KVM_IRQ_ROUTING_IRQCHIP, KVM_IRQ_ROUTING_MSI, + KVM_IRQCHIP_IOAPIC, KVM_IRQ_ROUTING_IRQCHIP, KVM_IRQ_ROUTING_MSI, }; use crate::hv::kvm::ioctls::{ kvm_check_extension, kvm_create_vcpu, kvm_ioeventfd, kvm_irqfd, kvm_memory_encrypt_op, @@ -109,7 +108,7 @@ impl VmInner { Ok(()) } - fn check_extension(&self, id: u32) -> Result { + fn check_extension(&self, id: KvmCap) -> Result { let ret = unsafe { kvm_check_extension(self, id) }; match ret { Ok(num) => Ok(num), @@ -206,7 +205,7 @@ impl VmMemory for KvmMemory { fn max_mem_slots(&self) -> Result { self.vm - .check_extension(KVM_CAP_NR_MEMSLOTS) + .check_extension(KvmCap::NR_MEMSLOTS) .map(|r| r as u32) } @@ -599,7 +598,7 @@ impl Vm for KvmVm { return Err(std::io::ErrorKind::AlreadyExists.into()) .context(error::CreateIntx { pin }); } - if self.vm.check_extension(KVM_CAP_IRQFD)? == 0 { + if self.vm.check_extension(KvmCap::IRQFD)? == 0 { return error::Capability { cap: "KVM_CAP_IRQFD", } @@ -622,7 +621,7 @@ impl Vm for KvmVm { } fn create_msi_sender(&self) -> Result { - if self.vm.check_extension(KVM_CAP_SIGNAL_MSI)? == 0 { + if self.vm.check_extension(KvmCap::SIGNAL_MSI)? == 0 { return error::Capability { cap: "KVM_CAP_SIGNAL_MSI", } From a0423a8421e8757b81bf77a5f54a20e815efbfcb Mon Sep 17 00:00:00 2001 From: Changyuan Lyu Date: Sun, 16 Jun 2024 17:11:44 -0700 Subject: [PATCH 5/5] refactor(kvm): use `c_enum` for KVM VM types Signed-off-by: Changyuan Lyu --- alioth/src/hv/kvm/bindings.rs | 15 ++++++++++----- alioth/src/hv/kvm/ioctls.rs | 4 ++-- alioth/src/hv/kvm/kvm.rs | 8 ++++---- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/alioth/src/hv/kvm/bindings.rs b/alioth/src/hv/kvm/bindings.rs index 58e0c57..360dfd4 100644 --- a/alioth/src/hv/kvm/bindings.rs +++ b/alioth/src/hv/kvm/bindings.rs @@ -21,11 +21,16 @@ use crate::c_enum; pub const KVMIO: u8 = 0xAE; pub const KVM_API_VERSION: i32 = 12; -pub const KVM_X86_DEFAULT_VM: u64 = 0; -// pub const KVM_X86_SW_PROTECTED_VM: u64 = 1; -// pub const KVM_X86_SEV_VM: u64 = 2; -// pub const KVM_X86_SEV_ES_VM: u64 = 3; -pub const KVM_X86_SNP_VM: u64 = 4; +c_enum! { + pub struct KvmVmType(u64); + { + DEFAULT = 0; + SW_PROTECTED = 1; + SEV = 2; + SEV_ES = 3; + SNP = 4; + } +} pub const KVM_MAX_CPUID_ENTRIES: usize = 256; diff --git a/alioth/src/hv/kvm/ioctls.rs b/alioth/src/hv/kvm/ioctls.rs index aff6a13..a4d5d34 100644 --- a/alioth/src/hv/kvm/ioctls.rs +++ b/alioth/src/hv/kvm/ioctls.rs @@ -15,7 +15,7 @@ use crate::hv::kvm::bindings::{ KvmCap, KvmCpuid2, KvmCreateGuestMemfd, KvmEnableCap, KvmEncRegion, KvmIoEventFd, KvmIrqRouting, KvmIrqfd, KvmMemoryAttributes, KvmMsi, KvmRegs, KvmSregs, KvmSregs2, - KvmUserspaceMemoryRegion, KvmUserspaceMemoryRegion2, KVMIO, + KvmUserspaceMemoryRegion, KvmUserspaceMemoryRegion2, KvmVmType, KVMIO, }; use crate::utils::ioctls::{ioctl_io, ioctl_ior, ioctl_iowr}; use crate::{ @@ -24,7 +24,7 @@ use crate::{ }; ioctl_none!(kvm_get_api_version, KVMIO, 0x00, 0); -ioctl_write_val!(kvm_create_vm, ioctl_io(KVMIO, 0x01)); +ioctl_write_val!(kvm_create_vm, ioctl_io(KVMIO, 0x01), KvmVmType); ioctl_write_val!(kvm_check_extension, ioctl_io(KVMIO, 0x03), KvmCap); ioctl_none!(kvm_get_vcpu_mmap_size, KVMIO, 0x04, 0); #[cfg(target_arch = "x86_64")] diff --git a/alioth/src/hv/kvm/kvm.rs b/alioth/src/hv/kvm/kvm.rs index 1066644..17dd54f 100644 --- a/alioth/src/hv/kvm/kvm.rs +++ b/alioth/src/hv/kvm/kvm.rs @@ -43,8 +43,8 @@ use crate::hv::Cpuid; use crate::hv::{error, Coco, Hypervisor, MemMapOption, Result, VmConfig}; use bindings::{ - KvmCap, KvmCpuid2, KvmCpuid2Flag, KvmCpuidEntry2, KvmCreateGuestMemfd, KvmEnableCap, - KVM_API_VERSION, KVM_MAX_CPUID_ENTRIES, KVM_X86_DEFAULT_VM, KVM_X86_SNP_VM, + KvmCap, KvmCpuid2, KvmCpuid2Flag, KvmCpuidEntry2, KvmCreateGuestMemfd, KvmEnableCap, KvmVmType, + KVM_API_VERSION, KVM_MAX_CPUID_ENTRIES, }; use ioctls::{ kvm_check_extension, kvm_create_guest_memfd, kvm_create_irqchip, kvm_create_vm, kvm_enable_cap, @@ -144,9 +144,9 @@ impl Hypervisor for Kvm { let vcpu_mmap_size = unsafe { kvm_get_vcpu_mmap_size(&self.fd) }.context(error::CreateVm)? as usize; let kvm_vm_type = if let Some(Coco::AmdSnp { .. }) = &config.coco { - KVM_X86_SNP_VM + KvmVmType::SNP } else { - KVM_X86_DEFAULT_VM + KvmVmType::DEFAULT }; let vm_fd = unsafe { kvm_create_vm(&self.fd, kvm_vm_type) }.context(error::CreateVm)?; let fd = unsafe { OwnedFd::from_raw_fd(vm_fd) };