mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-07-31 23:36:12 +00:00
Merge pull request #8724 from openanolis/chao/add_vfio
dragonball: introduce vfio support
This commit is contained in:
commit
8895cb82df
@ -11,14 +11,21 @@ keywords = ["dragonball", "secure-sandbox", "devices", "pci"]
|
||||
readme = "README.md"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.14"
|
||||
thiserror = "1"
|
||||
dbs-allocator = { path = "../dbs_allocator" }
|
||||
dbs-boot = { path = "../dbs_boot" }
|
||||
dbs-device = { path = "../dbs_device" }
|
||||
dbs-interrupt = { path = "../dbs_interrupt", features = ["kvm-irq", "kvm-legacy-irq", "kvm-msi-irq"] }
|
||||
dbs-allocator = { path = "../dbs_allocator" }
|
||||
log = "0.4.14"
|
||||
downcast-rs = "1.2.0"
|
||||
byteorder = "1.4.3"
|
||||
thiserror = "1"
|
||||
vm-memory = "0.10.0"
|
||||
kvm-ioctls = "0.12.0"
|
||||
kvm-bindings = "0.6.0"
|
||||
vfio-ioctls = "0.1.0"
|
||||
vfio-bindings = "0.3.0"
|
||||
libc = "0.2.39"
|
||||
|
||||
[dev-dependencies]
|
||||
dbs-arch = { path = "../dbs_arch" }
|
||||
kvm-ioctls = "0.12.0"
|
@ -18,4 +18,10 @@ There are several components in `dbs-pci` crate building together to emulate PCI
|
||||
|
||||
6. `msi` mod: struct to maintain information for PCI Message Signalled Interrupt Capability. It will be initialized when parsing PCI configuration space and used when getting interrupt capabilities.
|
||||
|
||||
7. `msix` mod: struct to maintain information for PCI Message Signalled Interrupt Extended Capability. It will be initialized when parsing PCI configuration space and used when getting interrupt capabilities.
|
||||
7. `msix` mod: struct to maintain information for PCI Message Signalled Interrupt Extended Capability. It will be initialized when parsing PCI configuration space and used when getting interrupt capabilities.
|
||||
|
||||
8. `vfio` mod: `vfio` mod collects lots of information related to the `vfio` operations.
|
||||
a. `vfio` `msi` and `msix` capability and state
|
||||
b. `vfio` interrupt information
|
||||
c. PCI region information
|
||||
d. `vfio` PCI device information and state
|
@ -212,7 +212,7 @@ pub trait PciProgrammingInterface {
|
||||
/// Types of PCI capabilities.
|
||||
#[repr(u8)]
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum PciCapabilityID {
|
||||
pub enum PciCapabilityId {
|
||||
ListID = 0,
|
||||
PowerManagement = 0x01,
|
||||
AcceleratedGraphicsPort = 0x02,
|
||||
@ -238,33 +238,33 @@ pub enum PciCapabilityID {
|
||||
Test = 0xFF,
|
||||
}
|
||||
|
||||
impl From<u8> for PciCapabilityID {
|
||||
impl From<u8> for PciCapabilityId {
|
||||
fn from(c: u8) -> Self {
|
||||
match c {
|
||||
0 => PciCapabilityID::ListID,
|
||||
0x01 => PciCapabilityID::PowerManagement,
|
||||
0x02 => PciCapabilityID::AcceleratedGraphicsPort,
|
||||
0x03 => PciCapabilityID::VitalProductData,
|
||||
0x04 => PciCapabilityID::SlotIdentification,
|
||||
0x05 => PciCapabilityID::MessageSignalledInterrupts,
|
||||
0x06 => PciCapabilityID::CompactPCIHotSwap,
|
||||
0x07 => PciCapabilityID::PCIX,
|
||||
0x08 => PciCapabilityID::HyperTransport,
|
||||
0x09 => PciCapabilityID::VendorSpecific,
|
||||
0x0A => PciCapabilityID::Debugport,
|
||||
0x0B => PciCapabilityID::CompactPCICentralResourceControl,
|
||||
0x0C => PciCapabilityID::PCIStandardHotPlugController,
|
||||
0x0D => PciCapabilityID::BridgeSubsystemVendorDeviceID,
|
||||
0x0E => PciCapabilityID::AGPTargetPCIPCIbridge,
|
||||
0x0F => PciCapabilityID::SecureDevice,
|
||||
0x10 => PciCapabilityID::PCIExpress,
|
||||
0x11 => PciCapabilityID::MSIX,
|
||||
0x12 => PciCapabilityID::SATADataIndexConf,
|
||||
0x13 => PciCapabilityID::PCIAdvancedFeatures,
|
||||
0x14 => PciCapabilityID::PCIEnhancedAllocation,
|
||||
0 => PciCapabilityId::ListID,
|
||||
0x01 => PciCapabilityId::PowerManagement,
|
||||
0x02 => PciCapabilityId::AcceleratedGraphicsPort,
|
||||
0x03 => PciCapabilityId::VitalProductData,
|
||||
0x04 => PciCapabilityId::SlotIdentification,
|
||||
0x05 => PciCapabilityId::MessageSignalledInterrupts,
|
||||
0x06 => PciCapabilityId::CompactPCIHotSwap,
|
||||
0x07 => PciCapabilityId::PCIX,
|
||||
0x08 => PciCapabilityId::HyperTransport,
|
||||
0x09 => PciCapabilityId::VendorSpecific,
|
||||
0x0A => PciCapabilityId::Debugport,
|
||||
0x0B => PciCapabilityId::CompactPCICentralResourceControl,
|
||||
0x0C => PciCapabilityId::PCIStandardHotPlugController,
|
||||
0x0D => PciCapabilityId::BridgeSubsystemVendorDeviceID,
|
||||
0x0E => PciCapabilityId::AGPTargetPCIPCIbridge,
|
||||
0x0F => PciCapabilityId::SecureDevice,
|
||||
0x10 => PciCapabilityId::PCIExpress,
|
||||
0x11 => PciCapabilityId::MSIX,
|
||||
0x12 => PciCapabilityId::SATADataIndexConf,
|
||||
0x13 => PciCapabilityId::PCIAdvancedFeatures,
|
||||
0x14 => PciCapabilityId::PCIEnhancedAllocation,
|
||||
#[cfg(test)]
|
||||
0xFF => PciCapabilityID::Test,
|
||||
_ => PciCapabilityID::ListID,
|
||||
0xFF => PciCapabilityId::Test,
|
||||
_ => PciCapabilityId::ListID,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -309,7 +309,7 @@ pub trait PciCapability: Send + Sync {
|
||||
}
|
||||
|
||||
/// The type of PCI Interrupt
|
||||
fn pci_capability_type(&self) -> PciCapabilityID;
|
||||
fn pci_capability_type(&self) -> PciCapabilityId;
|
||||
}
|
||||
|
||||
/// PCI device has four interrupt pins A->D.
|
||||
@ -334,7 +334,7 @@ pub enum PciBarRegionType {
|
||||
/// 32-bit MMIO Bar.
|
||||
Memory32BitRegion = 0,
|
||||
/// IO port Bar.
|
||||
IORegion = 0x01,
|
||||
IoRegion = 0x01,
|
||||
/// 64-bit MMIO Bar.
|
||||
Memory64BitRegion = 0x04,
|
||||
/// Fake type for the upper Bar of 64-bit MMIO Bar.
|
||||
@ -469,7 +469,7 @@ impl BarProgrammingParams {
|
||||
|
||||
let mut resources = DeviceResources::new();
|
||||
match self.bar_type {
|
||||
PciBarRegionType::IORegion => resources.append(Resource::PioAddressRange {
|
||||
PciBarRegionType::IoRegion => resources.append(Resource::PioAddressRange {
|
||||
base: base as u16,
|
||||
size: self.len as u16,
|
||||
}),
|
||||
@ -504,7 +504,7 @@ impl PciBarState {
|
||||
fn mask(&self) -> u32 {
|
||||
match self.type_ {
|
||||
None => 0,
|
||||
Some(PciBarRegionType::IORegion) => !(self.size - 1),
|
||||
Some(PciBarRegionType::IoRegion) => !(self.size - 1),
|
||||
Some(PciBarRegionType::Memory32BitRegion) => !(self.size - 1),
|
||||
Some(PciBarRegionType::Memory64BitRegion) => {
|
||||
if self.size == 0 {
|
||||
@ -548,7 +548,7 @@ pub struct Vp2pCap {
|
||||
impl Vp2pCap {
|
||||
fn new(clique_id: u8) -> Self {
|
||||
Vp2pCap {
|
||||
id: PciCapabilityID::VendorSpecific as u8,
|
||||
id: PciCapabilityId::VendorSpecific as u8,
|
||||
next: 0,
|
||||
length: 8,
|
||||
sig_1: 0x50,
|
||||
@ -583,8 +583,8 @@ impl PciCapability for Vp2pCap {
|
||||
|
||||
fn write_u8(&mut self, _offset: usize, _value: u8) {}
|
||||
|
||||
fn pci_capability_type(&self) -> PciCapabilityID {
|
||||
PciCapabilityID::VendorSpecific
|
||||
fn pci_capability_type(&self) -> PciCapabilityId {
|
||||
PciCapabilityId::VendorSpecific
|
||||
}
|
||||
}
|
||||
|
||||
@ -999,7 +999,7 @@ impl PciConfiguration {
|
||||
.checked_add(config.size - 1)
|
||||
.ok_or(Error::BarAddressInvalid(config.addr, config.size))?;
|
||||
match config.bar_type {
|
||||
PciBarRegionType::IORegion => {
|
||||
PciBarRegionType::IoRegion => {
|
||||
if config.size < 0x4 || config.size > u64::from(u32::max_value()) {
|
||||
return Err(Error::BarSizeInvalid(config.size));
|
||||
}
|
||||
@ -1045,7 +1045,7 @@ impl PciConfiguration {
|
||||
BAR_MEM_ADDR_MASK,
|
||||
config.prefetchable as u32 | config.bar_type as u32,
|
||||
),
|
||||
PciBarRegionType::IORegion => (BAR_IO_ADDR_MASK, config.bar_type as u32),
|
||||
PciBarRegionType::IoRegion => (BAR_IO_ADDR_MASK, config.bar_type as u32),
|
||||
PciBarRegionType::Memory64BitRegionUpper => {
|
||||
panic!("Invalid PCI Bar type");
|
||||
}
|
||||
@ -1167,7 +1167,7 @@ impl PciConfiguration {
|
||||
let value = self.registers[reg_idx] & mask;
|
||||
if let Some(bar_type) = self.bar_type(bar_idx) {
|
||||
match bar_type {
|
||||
PciBarRegionType::Memory32BitRegion | PciBarRegionType::IORegion => {
|
||||
PciBarRegionType::Memory32BitRegion | PciBarRegionType::IoRegion => {
|
||||
if (value & mask) != self.bar_addr(bar_idx) {
|
||||
debug!(
|
||||
"DETECT BAR REPROG: current 0x{:x}, new 0x{:x}",
|
||||
@ -1264,7 +1264,7 @@ impl PciConfiguration {
|
||||
|
||||
assert!(!self.bar_allocated(param.bar_idx));
|
||||
let constraint = match param.bar_type {
|
||||
PciBarRegionType::IORegion => {
|
||||
PciBarRegionType::IoRegion => {
|
||||
let range = (
|
||||
param.new_base as u16,
|
||||
(param.new_base + param.len - 1) as u16,
|
||||
@ -1299,7 +1299,7 @@ impl PciConfiguration {
|
||||
size: param.len,
|
||||
}
|
||||
}
|
||||
PciBarRegionType::IORegion => Resource::PioAddressRange {
|
||||
PciBarRegionType::IoRegion => Resource::PioAddressRange {
|
||||
base: param.old_base as u16,
|
||||
size: param.len as u16,
|
||||
},
|
||||
@ -1448,8 +1448,8 @@ pub(crate) mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn pci_capability_type(&self) -> PciCapabilityID {
|
||||
PciCapabilityID::Test
|
||||
fn pci_capability_type(&self) -> PciCapabilityId {
|
||||
PciCapabilityId::Test
|
||||
}
|
||||
}
|
||||
|
||||
@ -1460,7 +1460,7 @@ pub(crate) mod tests {
|
||||
|
||||
// Add two capabilities with different contents.
|
||||
let cap1 = Box::new(TestCap {
|
||||
id: PciCapabilityID::VendorSpecific as u8,
|
||||
id: PciCapabilityId::VendorSpecific as u8,
|
||||
next: 0,
|
||||
len: 4,
|
||||
foo: 0xAA,
|
||||
@ -1472,7 +1472,7 @@ pub(crate) mod tests {
|
||||
assert_eq!(cap1_offset % 4, 0);
|
||||
|
||||
let cap2 = Box::new(TestCap {
|
||||
id: PciCapabilityID::VendorSpecific as u8,
|
||||
id: PciCapabilityId::VendorSpecific as u8,
|
||||
next: 0,
|
||||
len: 8,
|
||||
foo: 0xBB,
|
||||
@ -1556,8 +1556,8 @@ pub(crate) mod tests {
|
||||
assert_eq!(config.size(), 0);
|
||||
assert_eq!(config.addr, 0);
|
||||
|
||||
config = config.set_bar_type(PciBarRegionType::IORegion);
|
||||
assert_eq!(config.bar_type(), PciBarRegionType::IORegion);
|
||||
config = config.set_bar_type(PciBarRegionType::IoRegion);
|
||||
assert_eq!(config.bar_type(), PciBarRegionType::IoRegion);
|
||||
config = config.set_address(0x1000);
|
||||
assert_eq!(config.address(), 0x1000);
|
||||
config = config.set_size(0x2000);
|
||||
@ -1744,7 +1744,7 @@ pub(crate) mod tests {
|
||||
// Allocate BAR5
|
||||
let bar = PciBarConfiguration {
|
||||
bar_idx: 5,
|
||||
bar_type: PciBarRegionType::IORegion,
|
||||
bar_type: PciBarRegionType::IoRegion,
|
||||
prefetchable: PciBarPrefetchable::NotPrefetchable,
|
||||
addr: 0x2000,
|
||||
size: 0x1000,
|
||||
|
@ -32,7 +32,7 @@ pub use bus::PciBus;
|
||||
mod configuration;
|
||||
pub use configuration::{
|
||||
BarProgrammingParams, PciBarConfiguration, PciBarPrefetchable, PciBarRegionType,
|
||||
PciBridgeSubclass, PciCapability, PciCapabilityID, PciClassCode, PciConfiguration,
|
||||
PciBridgeSubclass, PciCapability, PciCapabilityId, PciClassCode, PciConfiguration,
|
||||
PciHeaderType, PciInterruptPin, PciMassStorageSubclass, PciMultimediaSubclass,
|
||||
PciNetworkControllerSubclass, PciProgrammingInterface, PciSerialBusSubClass, PciSubclass,
|
||||
NUM_BAR_REGS, NUM_CONFIGURATION_REGISTERS,
|
||||
@ -48,7 +48,12 @@ mod root_device;
|
||||
pub use root_device::PciRootDevice;
|
||||
|
||||
mod msi;
|
||||
pub use msi::{MsiCap, MsiState};
|
||||
|
||||
mod msix;
|
||||
pub use msix::{MsixCap, MsixState, MSIX_TABLE_ENTRY_SIZE};
|
||||
|
||||
mod vfio;
|
||||
|
||||
/// Error codes related to PCI root/bus/device operations.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
|
@ -12,7 +12,7 @@ use dbs_interrupt::{
|
||||
};
|
||||
use log::{debug, error, warn};
|
||||
|
||||
use crate::configuration::{PciCapability, PciCapabilityID};
|
||||
use crate::configuration::{PciCapability, PciCapabilityId};
|
||||
use crate::fill_config_data;
|
||||
|
||||
// MSI control masks
|
||||
@ -114,7 +114,7 @@ pub struct MsiCap {
|
||||
impl MsiCap {
|
||||
/// Create a new PCI MSI capability structure.
|
||||
pub fn new(next: u8, mut msg_ctl: u16) -> Self {
|
||||
let cap_id_next = (next as u16) << 8 | PciCapabilityID::MessageSignalledInterrupts as u16;
|
||||
let cap_id_next = (next as u16) << 8 | PciCapabilityId::MessageSignalledInterrupts as u16;
|
||||
|
||||
// By default MSI capability is disabled, and driver needs to explicitly turn it on.
|
||||
msg_ctl &= !MSI_CTL_ENABLE;
|
||||
@ -457,8 +457,8 @@ impl PciCapability for MsiCap {
|
||||
}
|
||||
}
|
||||
|
||||
fn pci_capability_type(&self) -> PciCapabilityID {
|
||||
PciCapabilityID::MessageSignalledInterrupts
|
||||
fn pci_capability_type(&self) -> PciCapabilityId {
|
||||
PciCapabilityId::MessageSignalledInterrupts
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ use dbs_interrupt::{
|
||||
use log::debug;
|
||||
use vm_memory::ByteValued;
|
||||
|
||||
use crate::configuration::{PciCapability, PciCapabilityID};
|
||||
use crate::configuration::{PciCapability, PciCapabilityId};
|
||||
|
||||
const MAX_MSIX_VECTORS_PER_DEVICE: u16 = 2048;
|
||||
const FUNCTION_MASK_BIT: u8 = 14;
|
||||
@ -72,7 +72,7 @@ impl MsixCap {
|
||||
let msg_ctl: u16 = table_size - 1;
|
||||
|
||||
MsixCap {
|
||||
cap_id: PciCapabilityID::MSIX as u8,
|
||||
cap_id: PciCapabilityId::MSIX as u8,
|
||||
cap_next: 0,
|
||||
msg_ctl,
|
||||
table: (table_off & MSIX_TABLE_OFFSET_MASK)
|
||||
@ -140,8 +140,8 @@ impl PciCapability for MsixCap {
|
||||
}
|
||||
}
|
||||
|
||||
fn pci_capability_type(&self) -> PciCapabilityID {
|
||||
PciCapabilityID::MSIX
|
||||
fn pci_capability_type(&self) -> PciCapabilityId {
|
||||
PciCapabilityId::MSIX
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,7 +495,7 @@ mod tests {
|
||||
assert_eq!(msix.table_size(), 0x100);
|
||||
|
||||
assert_eq!(msix.cap_next, 0);
|
||||
assert_eq!(msix.cap_id, PciCapabilityID::MSIX as u8);
|
||||
assert_eq!(msix.cap_id, PciCapabilityId::MSIX as u8);
|
||||
let msg_ctl = msix.msg_ctl;
|
||||
assert_eq!(msix.read_u16(0x2), msg_ctl);
|
||||
msix.write_u16(0x2, MSIX_ENABLE_MASK);
|
||||
|
1968
src/dragonball/src/dbs_pci/src/vfio.rs
Normal file
1968
src/dragonball/src/dbs_pci/src/vfio.rs
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user