mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 02:55:45 +00:00
hypervisor: Move creation of irq routing struct to hypervisor crate
This removes the requirement to leak as many datastructures from the hypervisor crate into the vmm crate. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
fe82322727
commit
3f9e8d676a
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -356,6 +356,7 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"vm-device",
|
||||||
"vm-memory",
|
"vm-memory",
|
||||||
"vmm-sys-util",
|
"vmm-sys-util",
|
||||||
]
|
]
|
||||||
|
@ -18,11 +18,12 @@ libc = "0.2.125"
|
|||||||
log = "0.4.17"
|
log = "0.4.17"
|
||||||
kvm-ioctls = { version = "0.11.0", optional = true }
|
kvm-ioctls = { version = "0.11.0", optional = true }
|
||||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.0-tdx", features = ["with-serde", "fam-wrappers"], optional = true }
|
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.5.0-tdx", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||||
mshv-bindings = {git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
|
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||||
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
|
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
|
||||||
serde = { version = "1.0.137", features = ["rc"] }
|
serde = { version = "1.0.137", features = ["rc"] }
|
||||||
serde_derive = "1.0.137"
|
serde_derive = "1.0.137"
|
||||||
serde_json = "1.0.81"
|
serde_json = "1.0.81"
|
||||||
|
vm-device = { path = "../vm-device" }
|
||||||
vm-memory = { version = "0.7.0", features = ["backend-mmap", "backend-atomic"] }
|
vm-memory = { version = "0.7.0", features = ["backend-mmap", "backend-atomic"] }
|
||||||
vmm-sys-util = { version = "0.9.0", features = ["with-serde"] }
|
vmm-sys-util = { version = "0.9.0", features = ["with-serde"] }
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ use std::result;
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
use vm_device::interrupt::InterruptSourceConfig;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
// x86_64 dependencies
|
// x86_64 dependencies
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@ -284,6 +285,64 @@ impl vm::Vm for KvmVm {
|
|||||||
.unregister_ioevent(fd, addr, NoDatamatch)
|
.unregister_ioevent(fd, addr, NoDatamatch)
|
||||||
.map_err(|e| vm::HypervisorVmError::UnregisterIoEvent(e.into()))
|
.map_err(|e| vm::HypervisorVmError::UnregisterIoEvent(e.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Constructs a routing entry
|
||||||
|
///
|
||||||
|
fn make_routing_entry(
|
||||||
|
&self,
|
||||||
|
gsi: u32,
|
||||||
|
config: &InterruptSourceConfig,
|
||||||
|
) -> kvm_irq_routing_entry {
|
||||||
|
match &config {
|
||||||
|
InterruptSourceConfig::MsiIrq(cfg) => {
|
||||||
|
let mut kvm_route = kvm_irq_routing_entry {
|
||||||
|
gsi,
|
||||||
|
type_: KVM_IRQ_ROUTING_MSI,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
kvm_route.u.msi.address_lo = cfg.low_addr;
|
||||||
|
kvm_route.u.msi.address_hi = cfg.high_addr;
|
||||||
|
kvm_route.u.msi.data = cfg.data;
|
||||||
|
|
||||||
|
if self.check_extension(crate::Cap::MsiDevid) {
|
||||||
|
// On AArch64, there is limitation on the range of the 'devid',
|
||||||
|
// it can not be greater than 65536 (the max of u16).
|
||||||
|
//
|
||||||
|
// BDF can not be used directly, because 'segment' is in high
|
||||||
|
// 16 bits. The layout of the u32 BDF is:
|
||||||
|
// |---- 16 bits ----|-- 8 bits --|-- 5 bits --|-- 3 bits --|
|
||||||
|
// | segment | bus | device | function |
|
||||||
|
//
|
||||||
|
// Now that we support 1 bus only in a segment, we can build a
|
||||||
|
// 'devid' by replacing the 'bus' bits with the low 8 bits of
|
||||||
|
// 'segment' data.
|
||||||
|
// This way we can resolve the range checking problem and give
|
||||||
|
// different `devid` to all the devices. Limitation is that at
|
||||||
|
// most 256 segments can be supported.
|
||||||
|
//
|
||||||
|
let modified_devid = (cfg.devid & 0x00ff_0000) >> 8 | cfg.devid & 0xff;
|
||||||
|
|
||||||
|
kvm_route.flags = KVM_MSI_VALID_DEVID;
|
||||||
|
kvm_route.u.msi.__bindgen_anon_1.devid = modified_devid;
|
||||||
|
}
|
||||||
|
kvm_route
|
||||||
|
}
|
||||||
|
InterruptSourceConfig::LegacyIrq(cfg) => {
|
||||||
|
let mut kvm_route = kvm_irq_routing_entry {
|
||||||
|
gsi,
|
||||||
|
type_: KVM_IRQ_ROUTING_IRQCHIP,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
kvm_route.u.irqchip.irqchip = cfg.irqchip;
|
||||||
|
kvm_route.u.irqchip.pin = cfg.pin;
|
||||||
|
|
||||||
|
kvm_route
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Sets the GSI routing table entries, overwriting any previously set
|
/// Sets the GSI routing table entries, overwriting any previously set
|
||||||
/// entries, as per the `KVM_SET_GSI_ROUTING` ioctl.
|
/// entries, as per the `KVM_SET_GSI_ROUTING` ioctl.
|
||||||
|
@ -23,6 +23,7 @@ use vm::DataMatch;
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub mod x86_64;
|
pub mod x86_64;
|
||||||
use crate::device;
|
use crate::device;
|
||||||
|
use vm_device::interrupt::InterruptSourceConfig;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub use x86_64::VcpuMshvState as CpuState;
|
pub use x86_64::VcpuMshvState as CpuState;
|
||||||
@ -957,6 +958,27 @@ impl vm::Vm for MshvVm {
|
|||||||
.map_err(|e| vm::HypervisorVmError::CreatePassthroughDevice(e.into()))
|
.map_err(|e| vm::HypervisorVmError::CreatePassthroughDevice(e.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Constructs a routing entry
|
||||||
|
///
|
||||||
|
fn make_routing_entry(
|
||||||
|
&self,
|
||||||
|
gsi: u32,
|
||||||
|
config: &InterruptSourceConfig,
|
||||||
|
) -> mshv_msi_routing_entry {
|
||||||
|
match config {
|
||||||
|
InterruptSourceConfig::MsiIrq(cfg) => mshv_msi_routing_entry {
|
||||||
|
gsi,
|
||||||
|
address_lo: cfg.low_addr,
|
||||||
|
address_hi: cfg.high_addr,
|
||||||
|
data: cfg.data,
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> vm::Result<()> {
|
fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> vm::Result<()> {
|
||||||
let mut msi_routing =
|
let mut msi_routing =
|
||||||
vec_with_array_field::<mshv_msi_routing, mshv_msi_routing_entry>(entries.len());
|
vec_with_array_field::<mshv_msi_routing, mshv_msi_routing_entry>(entries.len());
|
||||||
|
@ -28,6 +28,7 @@ use kvm_ioctls::Cap;
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use vm_device::interrupt::InterruptSourceConfig;
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -245,6 +246,8 @@ pub trait Vm: Send + Sync {
|
|||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
/// Unregister an event from a certain address it has been previously registered to.
|
/// Unregister an event from a certain address it has been previously registered to.
|
||||||
fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> Result<()>;
|
fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> Result<()>;
|
||||||
|
// Construct a routing entry
|
||||||
|
fn make_routing_entry(&self, gsi: u32, config: &InterruptSourceConfig) -> IrqRoutingEntry;
|
||||||
/// Sets the GSI routing table entries, overwriting any previously set
|
/// Sets the GSI routing table entries, overwriting any previously set
|
||||||
fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> Result<()>;
|
fn set_gsi_routing(&self, entries: &[IrqRoutingEntry]) -> Result<()>;
|
||||||
/// Creates a memory region structure that can be used with {create/remove}_user_memory_region
|
/// Creates a memory region structure that can be used with {create/remove}_user_memory_region
|
||||||
|
@ -303,9 +303,7 @@ impl InterruptManager for MsiInterruptManager<IrqRoutingEntry> {
|
|||||||
#[cfg(feature = "kvm")]
|
#[cfg(feature = "kvm")]
|
||||||
pub mod kvm {
|
pub mod kvm {
|
||||||
use super::*;
|
use super::*;
|
||||||
use hypervisor::kvm::KVM_MSI_VALID_DEVID;
|
use hypervisor::kvm::kvm_irq_routing_entry;
|
||||||
use hypervisor::kvm::{kvm_irq_routing_entry, KVM_IRQ_ROUTING_IRQCHIP, KVM_IRQ_ROUTING_MSI};
|
|
||||||
use pci::PciBdf;
|
|
||||||
|
|
||||||
type KvmRoutingEntry = RoutingEntry<kvm_irq_routing_entry>;
|
type KvmRoutingEntry = RoutingEntry<kvm_irq_routing_entry>;
|
||||||
pub type KvmMsiInterruptManager = MsiInterruptManager<kvm_irq_routing_entry>;
|
pub type KvmMsiInterruptManager = MsiInterruptManager<kvm_irq_routing_entry>;
|
||||||
@ -316,66 +314,10 @@ pub mod kvm {
|
|||||||
gsi: u32,
|
gsi: u32,
|
||||||
config: &InterruptSourceConfig,
|
config: &InterruptSourceConfig,
|
||||||
) -> Result<Box<Self>> {
|
) -> Result<Box<Self>> {
|
||||||
if let InterruptSourceConfig::MsiIrq(cfg) = &config {
|
Ok(Box::new(Self {
|
||||||
let mut kvm_route = kvm_irq_routing_entry {
|
masked: false,
|
||||||
gsi,
|
route: vm.make_routing_entry(gsi, config),
|
||||||
type_: KVM_IRQ_ROUTING_MSI,
|
}))
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
kvm_route.u.msi.address_lo = cfg.low_addr;
|
|
||||||
kvm_route.u.msi.address_hi = cfg.high_addr;
|
|
||||||
kvm_route.u.msi.data = cfg.data;
|
|
||||||
|
|
||||||
if vm.check_extension(hypervisor::Cap::MsiDevid) {
|
|
||||||
// On AArch64, there is limitation on the range of the 'devid',
|
|
||||||
// it can not be greater than 65536 (the max of u16).
|
|
||||||
//
|
|
||||||
// BDF can not be used directly, because 'segment' is in high
|
|
||||||
// 16 bits. The layout of the u32 BDF is:
|
|
||||||
// |---- 16 bits ----|-- 8 bits --|-- 5 bits --|-- 3 bits --|
|
|
||||||
// | segment | bus | device | function |
|
|
||||||
//
|
|
||||||
// Now that we support 1 bus only in a segment, we can build a
|
|
||||||
// 'devid' by replacing the 'bus' bits with the low 8 bits of
|
|
||||||
// 'segment' data.
|
|
||||||
// This way we can resolve the range checking problem and give
|
|
||||||
// different `devid` to all the devices. Limitation is that at
|
|
||||||
// most 256 segments can be supported.
|
|
||||||
//
|
|
||||||
let bdf: PciBdf = PciBdf::from(cfg.devid);
|
|
||||||
let modified_bdf: PciBdf =
|
|
||||||
PciBdf::new(0, bdf.segment() as u8, bdf.device(), bdf.function());
|
|
||||||
kvm_route.flags = KVM_MSI_VALID_DEVID;
|
|
||||||
kvm_route.u.msi.__bindgen_anon_1.devid = modified_bdf.into();
|
|
||||||
}
|
|
||||||
|
|
||||||
let kvm_entry = KvmRoutingEntry {
|
|
||||||
route: kvm_route,
|
|
||||||
masked: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(Box::new(kvm_entry));
|
|
||||||
} else if let InterruptSourceConfig::LegacyIrq(cfg) = &config {
|
|
||||||
let mut kvm_route = kvm_irq_routing_entry {
|
|
||||||
gsi,
|
|
||||||
type_: KVM_IRQ_ROUTING_IRQCHIP,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
kvm_route.u.irqchip.irqchip = cfg.irqchip;
|
|
||||||
kvm_route.u.irqchip.pin = cfg.pin;
|
|
||||||
let kvm_entry = KvmRoutingEntry {
|
|
||||||
route: kvm_route,
|
|
||||||
masked: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(Box::new(kvm_entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
"Interrupt config type not supported",
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -383,36 +325,21 @@ pub mod kvm {
|
|||||||
#[cfg(feature = "mshv")]
|
#[cfg(feature = "mshv")]
|
||||||
pub mod mshv {
|
pub mod mshv {
|
||||||
use super::*;
|
use super::*;
|
||||||
use hypervisor::mshv::*;
|
use hypervisor::mshv::mshv_msi_routing_entry;
|
||||||
|
|
||||||
type MshvRoutingEntry = RoutingEntry<mshv_msi_routing_entry>;
|
type MshvRoutingEntry = RoutingEntry<mshv_msi_routing_entry>;
|
||||||
pub type MshvMsiInterruptManager = MsiInterruptManager<mshv_msi_routing_entry>;
|
pub type MshvMsiInterruptManager = MsiInterruptManager<mshv_msi_routing_entry>;
|
||||||
|
|
||||||
impl MshvRoutingEntry {
|
impl MshvRoutingEntry {
|
||||||
pub fn make_entry(
|
pub fn make_entry(
|
||||||
_vm: &Arc<dyn hypervisor::Vm>,
|
vm: &Arc<dyn hypervisor::Vm>,
|
||||||
gsi: u32,
|
gsi: u32,
|
||||||
config: &InterruptSourceConfig,
|
config: &InterruptSourceConfig,
|
||||||
) -> Result<Box<Self>> {
|
) -> Result<Box<Self>> {
|
||||||
if let InterruptSourceConfig::MsiIrq(cfg) = &config {
|
Ok(Box::new(Self {
|
||||||
let route = mshv_msi_routing_entry {
|
masked: false,
|
||||||
gsi,
|
route: vm.make_routing_entry(gsi, config),
|
||||||
address_lo: cfg.low_addr,
|
}))
|
||||||
address_hi: cfg.high_addr,
|
|
||||||
data: cfg.data,
|
|
||||||
};
|
|
||||||
let entry = MshvRoutingEntry {
|
|
||||||
route,
|
|
||||||
masked: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(Box::new(entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
"Interrupt config type not supported",
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user