From d20f647b3201b9fea0ab5ee9cc81af3d92940b1e Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Thu, 14 Jul 2022 18:59:13 +0000 Subject: [PATCH] hypervisor: provide a generic IrqRoutingEntry structure Signed-off-by: Wei Liu --- hypervisor/src/kvm/mod.rs | 45 ++++++++++++++++++++++++++++---------- hypervisor/src/lib.rs | 12 ++++++++-- hypervisor/src/mshv/mod.rs | 44 +++++++++++++++++++++++++++---------- 3 files changed, 76 insertions(+), 25 deletions(-) diff --git a/hypervisor/src/kvm/mod.rs b/hypervisor/src/kvm/mod.rs index 481a5bf33..ef0f8a8e8 100644 --- a/hypervisor/src/kvm/mod.rs +++ b/hypervisor/src/kvm/mod.rs @@ -50,8 +50,8 @@ use crate::arch::x86::NUM_IOAPIC_PINS; #[cfg(target_arch = "x86_64")] use crate::ClockData; use crate::{ - CpuState, IoEventAddress, MpState, UserMemoryRegion, USER_MEMORY_REGION_LOG_DIRTY, - USER_MEMORY_REGION_READ, USER_MEMORY_REGION_WRITE, + CpuState, IoEventAddress, IrqRoutingEntry, MpState, UserMemoryRegion, + USER_MEMORY_REGION_LOG_DIRTY, USER_MEMORY_REGION_READ, USER_MEMORY_REGION_WRITE, }; #[cfg(target_arch = "aarch64")] use aarch64::{RegList, Register, StandardRegisters}; @@ -95,8 +95,8 @@ use vmm_sys_util::{ioctl::ioctl_with_val, ioctl_expr, ioctl_ioc_nr, ioctl_iowr_n /// pub use { kvm_bindings::kvm_create_device as CreateDevice, kvm_bindings::kvm_device_attr as DeviceAttr, - kvm_bindings::kvm_irq_routing_entry as IrqRoutingEntry, kvm_bindings::kvm_run, - kvm_bindings::kvm_vcpu_events as VcpuEvents, kvm_ioctls::DeviceFd, kvm_ioctls::VcpuExit, + kvm_bindings::kvm_run, kvm_bindings::kvm_vcpu_events as VcpuEvents, kvm_ioctls::DeviceFd, + kvm_ioctls::VcpuExit, }; #[cfg(target_arch = "x86_64")] @@ -282,6 +282,23 @@ impl From for kvm_clock_data { } } +impl From for IrqRoutingEntry { + fn from(s: kvm_irq_routing_entry) -> Self { + IrqRoutingEntry::Kvm(s) + } +} + +impl From for kvm_irq_routing_entry { + fn from(e: IrqRoutingEntry) -> Self { + match e { + IrqRoutingEntry::Kvm(e) => e, + /* Needed in case other hypervisors are enabled */ + #[allow(unreachable_patterns)] + _ => panic!("IrqRoutingEntry is not valid"), + } + } +} + struct KvmDirtyLogSlot { slot: u32, guest_phys_addr: u64, @@ -437,11 +454,7 @@ impl vm::Vm for KvmVm { /// /// Constructs a routing entry /// - fn make_routing_entry( - &self, - gsi: u32, - config: &InterruptSourceConfig, - ) -> kvm_irq_routing_entry { + fn make_routing_entry(&self, gsi: u32, config: &InterruptSourceConfig) -> IrqRoutingEntry { match &config { InterruptSourceConfig::MsiIrq(cfg) => { let mut kvm_route = kvm_irq_routing_entry { @@ -475,7 +488,7 @@ impl vm::Vm for KvmVm { kvm_route.flags = KVM_MSI_VALID_DEVID; kvm_route.u.msi.__bindgen_anon_1.devid = modified_devid; } - kvm_route + kvm_route.into() } InterruptSourceConfig::LegacyIrq(cfg) => { let mut kvm_route = kvm_irq_routing_entry { @@ -486,7 +499,7 @@ impl vm::Vm for KvmVm { kvm_route.u.irqchip.irqchip = cfg.irqchip; kvm_route.u.irqchip.pin = cfg.pin; - kvm_route + kvm_route.into() } } } @@ -500,6 +513,14 @@ impl vm::Vm for KvmVm { vec_with_array_field::(entries.len()); irq_routing[0].nr = entries.len() as u32; irq_routing[0].flags = 0; + let entries: Vec = entries + .iter() + .map(|entry| match entry { + IrqRoutingEntry::Kvm(e) => *e, + #[allow(unreachable_patterns)] + _ => panic!("IrqRoutingEntry type is wrong"), + }) + .collect(); // SAFETY: irq_routing initialized with entries.len() and now it is being turned into // entries_slice with entries.len() again. It is guaranteed to be large enough to hold @@ -507,7 +528,7 @@ impl vm::Vm for KvmVm { unsafe { let entries_slice: &mut [kvm_irq_routing_entry] = irq_routing[0].entries.as_mut_slice(entries.len()); - entries_slice.copy_from_slice(entries); + entries_slice.copy_from_slice(&entries); } self.fd diff --git a/hypervisor/src/lib.rs b/hypervisor/src/lib.rs index cec0990fc..c227231bb 100644 --- a/hypervisor/src/lib.rs +++ b/hypervisor/src/lib.rs @@ -59,12 +59,12 @@ pub use kvm::x86_64; pub use kvm::{aarch64, GicState}; // Aliased types exposed from both hypervisors #[cfg(feature = "kvm")] -pub use kvm::{CreateDevice, DeviceAttr, DeviceFd, IrqRoutingEntry}; +pub use kvm::{CreateDevice, DeviceAttr, DeviceFd}; #[cfg(all(feature = "mshv", target_arch = "x86_64"))] pub use mshv::x86_64; // Aliased types exposed from both hypervisors #[cfg(all(feature = "mshv", target_arch = "x86_64"))] -pub use mshv::{CreateDevice, DeviceAttr, DeviceFd, IrqRoutingEntry}; +pub use mshv::{CreateDevice, DeviceAttr, DeviceFd}; use std::sync::Arc; pub use vm::{ DataMatch, HypervisorVmError, InterruptSourceConfig, LegacyIrqSourceConfig, MsiIrqSourceConfig, @@ -173,3 +173,11 @@ impl ClockData { } } } + +#[derive(Copy, Clone)] +pub enum IrqRoutingEntry { + #[cfg(feature = "kvm")] + Kvm(kvm_bindings::kvm_irq_routing_entry), + #[cfg(feature = "mshv")] + Mshv(mshv_bindings::mshv_msi_routing_entry), +} diff --git a/hypervisor/src/mshv/mod.rs b/hypervisor/src/mshv/mod.rs index 178e1bca6..14e4a3414 100644 --- a/hypervisor/src/mshv/mod.rs +++ b/hypervisor/src/mshv/mod.rs @@ -23,8 +23,8 @@ use vm::DataMatch; pub mod x86_64; use crate::device; use crate::{ - ClockData, CpuState, IoEventAddress, MpState, UserMemoryRegion, USER_MEMORY_REGION_EXECUTE, - USER_MEMORY_REGION_READ, USER_MEMORY_REGION_WRITE, + ClockData, CpuState, IoEventAddress, IrqRoutingEntry, MpState, UserMemoryRegion, + USER_MEMORY_REGION_EXECUTE, USER_MEMORY_REGION_READ, USER_MEMORY_REGION_WRITE, }; use vmm_sys_util::eventfd::EventFd; #[cfg(target_arch = "x86_64")] @@ -44,8 +44,7 @@ const DIRTY_BITMAP_SET_DIRTY: u64 = 0x8; /// pub use { mshv_bindings::mshv_create_device as CreateDevice, - mshv_bindings::mshv_device_attr as DeviceAttr, - mshv_bindings::mshv_msi_routing_entry as IrqRoutingEntry, mshv_ioctls::DeviceFd, + mshv_bindings::mshv_device_attr as DeviceAttr, mshv_ioctls::DeviceFd, }; pub const PAGE_SHIFT: usize = 12; @@ -131,6 +130,23 @@ impl From for VcpuMshvState { } } +impl From for IrqRoutingEntry { + fn from(s: mshv_msi_routing_entry) -> Self { + IrqRoutingEntry::Mshv(s) + } +} + +impl From for mshv_msi_routing_entry { + fn from(e: IrqRoutingEntry) -> Self { + match e { + IrqRoutingEntry::Mshv(e) => e, + /* Needed in case other hypervisors are enabled */ + #[allow(unreachable_patterns)] + _ => panic!("IrqRoutingEntry is not valid"), + } + } +} + struct MshvDirtyLogSlot { guest_pfn: u64, memory_size: u64, @@ -1074,18 +1090,15 @@ impl vm::Vm for MshvVm { /// /// Constructs a routing entry /// - fn make_routing_entry( - &self, - gsi: u32, - config: &InterruptSourceConfig, - ) -> mshv_msi_routing_entry { + fn make_routing_entry(&self, gsi: u32, config: &InterruptSourceConfig) -> IrqRoutingEntry { match config { InterruptSourceConfig::MsiIrq(cfg) => mshv_msi_routing_entry { gsi, address_lo: cfg.low_addr, address_hi: cfg.high_addr, data: cfg.data, - }, + } + .into(), _ => { unreachable!() } @@ -1097,13 +1110,22 @@ impl vm::Vm for MshvVm { vec_with_array_field::(entries.len()); msi_routing[0].nr = entries.len() as u32; + let entries: Vec = entries + .iter() + .map(|entry| match entry { + IrqRoutingEntry::Mshv(e) => *e, + #[allow(unreachable_patterns)] + _ => panic!("IrqRoutingEntry type is wrong"), + }) + .collect(); + // SAFETY: msi_routing initialized with entries.len() and now it is being turned into // entries_slice with entries.len() again. It is guaranteed to be large enough to hold // everything from entries. unsafe { let entries_slice: &mut [mshv_msi_routing_entry] = msi_routing[0].entries.as_mut_slice(entries.len()); - entries_slice.copy_from_slice(entries); + entries_slice.copy_from_slice(&entries); } self.fd