runtime-rs: Introduce device type of PordDevice in device manager

PortDevice is for handling root ports or switch ports in PCIe
Topology. It will make it easy pass the root ports/switch ports
information during create VM with requirements of PCIe devices.

Fixes #10361

Signed-off-by: alex.lyn <alex.lyn@antgroup.com>
This commit is contained in:
alex.lyn 2025-04-11 16:58:53 +08:00
parent 694a849eaa
commit f08fdd25d8
4 changed files with 136 additions and 5 deletions

View File

@ -13,7 +13,7 @@ use tokio::sync::{Mutex, RwLock};
use crate::{ use crate::{
vhost_user_blk::VhostUserBlkDevice, BlockConfig, BlockDevice, HybridVsockDevice, Hypervisor, vhost_user_blk::VhostUserBlkDevice, BlockConfig, BlockDevice, HybridVsockDevice, Hypervisor,
NetworkDevice, ProtectionDevice, ShareFsDevice, VfioDevice, VhostUserConfig, NetworkDevice, PCIePortDevice, ProtectionDevice, ShareFsDevice, VfioDevice, VhostUserConfig,
VhostUserNetDevice, VsockDevice, KATA_BLK_DEV_TYPE, KATA_CCW_DEV_TYPE, KATA_MMIO_BLK_DEV_TYPE, VhostUserNetDevice, VsockDevice, KATA_BLK_DEV_TYPE, KATA_CCW_DEV_TYPE, KATA_MMIO_BLK_DEV_TYPE,
KATA_NVDIMM_DEV_TYPE, VIRTIO_BLOCK_CCW, VIRTIO_BLOCK_MMIO, VIRTIO_BLOCK_PCI, VIRTIO_PMEM, KATA_NVDIMM_DEV_TYPE, VIRTIO_BLOCK_CCW, VIRTIO_BLOCK_MMIO, VIRTIO_BLOCK_PCI, VIRTIO_PMEM,
}; };
@ -112,6 +112,10 @@ impl DeviceManager {
}) })
} }
pub fn get_pcie_topology(&self) -> Option<PCIeTopology> {
self.pcie_topology.clone()
}
async fn get_block_driver(&self) -> String { async fn get_block_driver(&self) -> String {
self.hypervisor self.hypervisor
.hypervisor_config() .hypervisor_config()
@ -250,7 +254,10 @@ impl DeviceManager {
return Some(device_id.to_string()); return Some(device_id.to_string());
} }
} }
DeviceType::HybridVsock(_) | DeviceType::Vsock(_) | DeviceType::Protection(_) => { DeviceType::HybridVsock(_)
| DeviceType::Vsock(_)
| DeviceType::Protection(_)
| DeviceType::PortDevice(_) => {
continue; continue;
} }
} }
@ -393,6 +400,9 @@ impl DeviceManager {
pconfig, pconfig,
))) )))
} }
DeviceConfig::PortDeviceCfg(config) => {
Arc::new(Mutex::new(PCIePortDevice::new(&device_id, config)))
}
}; };
// register device to devices // register device to devices

View File

@ -4,6 +4,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// //
mod port_device;
mod protection_device; mod protection_device;
mod vfio; mod vfio;
mod vhost_user; mod vhost_user;
@ -14,6 +15,7 @@ mod virtio_fs;
mod virtio_net; mod virtio_net;
mod virtio_vsock; mod virtio_vsock;
pub use port_device::{PCIePortDevice, PortDeviceConfig};
pub use protection_device::{ProtectionDevice, ProtectionDeviceConfig, SevSnpConfig}; pub use protection_device::{ProtectionDevice, ProtectionDeviceConfig, SevSnpConfig};
pub use vfio::{ pub use vfio::{
bind_device_to_host, bind_device_to_vfio, get_vfio_device, HostDevice, VfioBusMode, VfioConfig, bind_device_to_host, bind_device_to_vfio, get_vfio_device, HostDevice, VfioBusMode, VfioConfig,

View File

@ -0,0 +1,117 @@
// Copyright (c) 2024-2025 Ant Group
//
// SPDX-License-Identifier: Apache-2.0
//
//use std::collections::HashMap;
use std::collections::HashMap;
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use crate::device::{
hypervisor,
topology::{PCIePort, PCIeTopology, Strategy, TopologyPortDevice},
Device, DeviceType,
};
#[derive(Debug, Default, Clone)]
pub struct PortDeviceConfig {
pub port_type: PCIePort,
pub total_ports: u32,
pub memsz_reserve: u64,
pub pref64_reserve: u64,
}
impl PortDeviceConfig {
pub fn new(port_type: PCIePort, total_ports: u32) -> Self {
Self {
port_type,
total_ports,
// FIXME:
// A method to automatically determine the maximum memory size
// based on all vfio devices' information on the host is coming soon.
memsz_reserve: 33554432_u64,
pref64_reserve: 536870912_u64,
}
}
}
#[derive(Debug, Default, Clone)]
pub struct PCIePortDevice {
/// device id for sharefs device in device manager
pub device_id: String,
/// config for sharefs device
pub config: PortDeviceConfig,
pub port_devices: HashMap<u32, TopologyPortDevice>,
}
impl PCIePortDevice {
pub fn new(device_id: &str, config: &PortDeviceConfig) -> Self {
Self {
device_id: device_id.to_string(),
config: config.clone(),
port_devices: HashMap::with_capacity(config.total_ports as usize),
}
}
}
#[async_trait]
impl Device for PCIePortDevice {
async fn attach(
&mut self,
pcie_topo: &mut Option<&mut PCIeTopology>,
h: &dyn hypervisor,
) -> Result<()> {
if let Some(topology) = pcie_topo {
match self.config.port_type {
PCIePort::RootPort => {
topology.add_root_ports_on_bus(topology.pcie_root_ports)?;
self.port_devices = topology.pcie_port_devices.clone();
}
PCIePort::SwitchPort => {
topology.add_switch_ports_with_strategy(
topology.pcie_switch_ports,
topology.pcie_switch_ports,
Strategy::SingleRootPort,
)?;
self.port_devices = topology.pcie_port_devices.clone();
}
_ => return Err(anyhow!("unspported pcie port type")),
};
info!(sl!(), "add device for PortDevice: {:?}", self.clone());
h.add_device(DeviceType::PortDevice(self.clone()))
.await
.context("add port devices.")?;
}
Ok(())
}
async fn detach(
&mut self,
_pcie_topo: &mut Option<&mut PCIeTopology>,
_h: &dyn hypervisor,
) -> Result<Option<u64>> {
Ok(None)
}
async fn update(&mut self, _h: &dyn hypervisor) -> Result<()> {
Ok(())
}
async fn get_device_info(&self) -> DeviceType {
DeviceType::PortDevice(self.clone())
}
async fn increase_attach_count(&mut self) -> Result<bool> {
Ok(false)
}
async fn decrease_attach_count(&mut self) -> Result<bool> {
Ok(false)
}
}

View File

@ -9,9 +9,9 @@ use std::fmt;
use crate::device::driver::vhost_user_blk::VhostUserBlkDevice; use crate::device::driver::vhost_user_blk::VhostUserBlkDevice;
use crate::{ use crate::{
BlockConfig, BlockDevice, HybridVsockConfig, HybridVsockDevice, Hypervisor as hypervisor, BlockConfig, BlockDevice, HybridVsockConfig, HybridVsockDevice, Hypervisor as hypervisor,
NetworkConfig, NetworkDevice, ProtectionDevice, ProtectionDeviceConfig, ShareFsConfig, NetworkConfig, NetworkDevice, PCIePortDevice, PortDeviceConfig, ProtectionDevice,
ShareFsDevice, VfioConfig, VfioDevice, VhostUserConfig, VhostUserNetDevice, VsockConfig, ProtectionDeviceConfig, ShareFsConfig, ShareFsDevice, VfioConfig, VfioDevice, VhostUserConfig,
VsockDevice, VhostUserNetDevice, VsockConfig, VsockDevice,
}; };
use anyhow::Result; use anyhow::Result;
use async_trait::async_trait; use async_trait::async_trait;
@ -37,6 +37,7 @@ pub enum DeviceConfig {
VsockCfg(VsockConfig), VsockCfg(VsockConfig),
HybridVsockCfg(HybridVsockConfig), HybridVsockCfg(HybridVsockConfig),
ProtectionDevCfg(ProtectionDeviceConfig), ProtectionDevCfg(ProtectionDeviceConfig),
PortDeviceCfg(PortDeviceConfig),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -50,6 +51,7 @@ pub enum DeviceType {
HybridVsock(HybridVsockDevice), HybridVsock(HybridVsockDevice),
Vsock(VsockDevice), Vsock(VsockDevice),
Protection(ProtectionDevice), Protection(ProtectionDevice),
PortDevice(PCIePortDevice),
} }
impl fmt::Display for DeviceType { impl fmt::Display for DeviceType {