hypervisor: provide a generic IrqRoutingEntry structure

Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
Wei Liu 2022-07-14 18:59:13 +00:00 committed by Liu Wei
parent 2de7121680
commit d20f647b32
3 changed files with 76 additions and 25 deletions

View File

@ -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<ClockData> for kvm_clock_data {
}
}
impl From<kvm_irq_routing_entry> for IrqRoutingEntry {
fn from(s: kvm_irq_routing_entry) -> Self {
IrqRoutingEntry::Kvm(s)
}
}
impl From<IrqRoutingEntry> 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::<kvm_irq_routing, kvm_irq_routing_entry>(entries.len());
irq_routing[0].nr = entries.len() as u32;
irq_routing[0].flags = 0;
let entries: Vec<kvm_irq_routing_entry> = 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

View File

@ -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),
}

View File

@ -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<CpuState> for VcpuMshvState {
}
}
impl From<mshv_msi_routing_entry> for IrqRoutingEntry {
fn from(s: mshv_msi_routing_entry) -> Self {
IrqRoutingEntry::Mshv(s)
}
}
impl From<IrqRoutingEntry> 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::<mshv_msi_routing, mshv_msi_routing_entry>(entries.len());
msi_routing[0].nr = entries.len() as u32;
let entries: Vec<mshv_msi_routing_entry> = 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