diff --git a/src/runtime-rs/crates/hypervisor/src/device/device_manager.rs b/src/runtime-rs/crates/hypervisor/src/device/device_manager.rs index 2427beabc..6ab6bfea3 100644 --- a/src/runtime-rs/crates/hypervisor/src/device/device_manager.rs +++ b/src/runtime-rs/crates/hypervisor/src/device/device_manager.rs @@ -13,7 +13,7 @@ use tokio::sync::{Mutex, RwLock}; use crate::{ 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, 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 { + self.pcie_topology.clone() + } + async fn get_block_driver(&self) -> String { self.hypervisor .hypervisor_config() @@ -250,7 +254,10 @@ impl DeviceManager { return Some(device_id.to_string()); } } - DeviceType::HybridVsock(_) | DeviceType::Vsock(_) | DeviceType::Protection(_) => { + DeviceType::HybridVsock(_) + | DeviceType::Vsock(_) + | DeviceType::Protection(_) + | DeviceType::PortDevice(_) => { continue; } } @@ -393,6 +400,9 @@ impl DeviceManager { pconfig, ))) } + DeviceConfig::PortDeviceCfg(config) => { + Arc::new(Mutex::new(PCIePortDevice::new(&device_id, config))) + } }; // register device to devices diff --git a/src/runtime-rs/crates/hypervisor/src/device/driver/mod.rs b/src/runtime-rs/crates/hypervisor/src/device/driver/mod.rs index 34e2022b9..e10d66c00 100644 --- a/src/runtime-rs/crates/hypervisor/src/device/driver/mod.rs +++ b/src/runtime-rs/crates/hypervisor/src/device/driver/mod.rs @@ -4,6 +4,7 @@ // SPDX-License-Identifier: Apache-2.0 // +mod port_device; mod protection_device; mod vfio; mod vhost_user; @@ -14,6 +15,7 @@ mod virtio_fs; mod virtio_net; mod virtio_vsock; +pub use port_device::{PCIePortDevice, PortDeviceConfig}; pub use protection_device::{ProtectionDevice, ProtectionDeviceConfig, SevSnpConfig}; pub use vfio::{ bind_device_to_host, bind_device_to_vfio, get_vfio_device, HostDevice, VfioBusMode, VfioConfig, diff --git a/src/runtime-rs/crates/hypervisor/src/device/driver/port_device.rs b/src/runtime-rs/crates/hypervisor/src/device/driver/port_device.rs new file mode 100644 index 000000000..48ef0ab44 --- /dev/null +++ b/src/runtime-rs/crates/hypervisor/src/device/driver/port_device.rs @@ -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, +} + +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> { + 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 { + Ok(false) + } + + async fn decrease_attach_count(&mut self) -> Result { + Ok(false) + } +} diff --git a/src/runtime-rs/crates/hypervisor/src/device/mod.rs b/src/runtime-rs/crates/hypervisor/src/device/mod.rs index dc4c31926..a63b07f5b 100644 --- a/src/runtime-rs/crates/hypervisor/src/device/mod.rs +++ b/src/runtime-rs/crates/hypervisor/src/device/mod.rs @@ -9,9 +9,9 @@ use std::fmt; use crate::device::driver::vhost_user_blk::VhostUserBlkDevice; use crate::{ BlockConfig, BlockDevice, HybridVsockConfig, HybridVsockDevice, Hypervisor as hypervisor, - NetworkConfig, NetworkDevice, ProtectionDevice, ProtectionDeviceConfig, ShareFsConfig, - ShareFsDevice, VfioConfig, VfioDevice, VhostUserConfig, VhostUserNetDevice, VsockConfig, - VsockDevice, + NetworkConfig, NetworkDevice, PCIePortDevice, PortDeviceConfig, ProtectionDevice, + ProtectionDeviceConfig, ShareFsConfig, ShareFsDevice, VfioConfig, VfioDevice, VhostUserConfig, + VhostUserNetDevice, VsockConfig, VsockDevice, }; use anyhow::Result; use async_trait::async_trait; @@ -37,6 +37,7 @@ pub enum DeviceConfig { VsockCfg(VsockConfig), HybridVsockCfg(HybridVsockConfig), ProtectionDevCfg(ProtectionDeviceConfig), + PortDeviceCfg(PortDeviceConfig), } #[derive(Debug, Clone)] @@ -50,6 +51,7 @@ pub enum DeviceType { HybridVsock(HybridVsockDevice), Vsock(VsockDevice), Protection(ProtectionDevice), + PortDevice(PCIePortDevice), } impl fmt::Display for DeviceType {