Skip to content

设备管理:device_manager.rs

概述

device_manager.rs 是虚拟机设备管理的核心模块,负责所有设备的创建、配置、挂载和生命周期管理。本文深入分析其设计和实现。

核心结构

DeviceManager

rust
// vmm/src/device_manager.rs (5036 行)
pub struct DeviceManager {
    // 设备列表
    devices: Vec<Arc<Mutex<dyn PciDevice>>>,
    
    // PCI 设备映射
    pci_devices: HashMap<u32, Arc<Mutex<dyn PciDevice>>>,
    
    // MMIO 设备
    mmio_devices: Vec<Arc<Mutex<dyn MmioDevice>>>,
    
    // 中断控制器
    interrupt_controller: Option<Arc<Mutex<dyn InterruptController>>>,
    
    // 控制台设备
    console_devices: Vec<Arc<Mutex<virtio_devices::Console>>>,
    
    // 网络设备
    net_devices: Vec<Arc<Mutex<virtio_devices::Net>>>,
    
    // 块设备
    block_devices: Vec<Arc<Mutex<virtio_devices::Block>>>,
    
    // 文件系统设备
    fs_devices: Vec<Arc<Mutex<virtio_devices::Fs>>>,
    
    // 串口设备
    serial_devices: Vec<Arc<Mutex<serial::Serial>>>,
    
    // 配置
    config: DeviceConfig,
    vm_config: VmConfig,
    
    // 中断管理
    interrupt_sources: Vec<Arc<Mutex<InterruptSourceGroup>>>,
    
    // ACPI
    acpi_table: Arc<Mutex<AcpiTable>>,
    
    // 快照
    bus_devices: Vec<BusDevice>,
}

DeviceConfig

rust
// vmm/src/config.rs
pub struct DeviceConfig {
    pub console: ConsoleConfig,
    pub serial: SerialConfig,
    pub net: Vec<NetConfig>,
    pub disk: Vec<DiskConfig>,
    pub fs: Vec<FSConfig>,
    pub pmem: Vec<PmemConfig>,
    pub devices: Vec<DeviceConfig>,
    pub iommu: bool,
}

设备初始化流程

初始化时序

实现代码

rust
// vmm/src/device_manager.rs
impl DeviceManager {
    pub fn new(
        config: DeviceConfig,
        vm_config: VmConfig,
        guest_memory: GuestMemoryMmap,
        interrupt_controller: Option<Arc<Mutex<dyn InterruptController>>>,
        msi_device_manager: &MsiDeviceManager,
        mmio_bus: Arc<Bus>,
        io_bus: Arc<Bus>,
    ) -> Result<Self> {
        // 1. 创建中断控制器
        let interrupt_controller = interrupt_controller
            .or_else(|| Some(Arc::new(Mutex::new(IoApic::new()?))))
            .ok_or(Error::InterruptControllerCreation)?;
        
        // 2. 创建 PCI Root
        let pci_root = PciRoot::new()?;
        
        // 3. 创建 Virtio 设备
        let mut devices = Vec::new();
        
        // 块设备
        for disk_config in &config.disk {
            let block = Self::create_block_device(disk_config, &guest_memory)?;
            devices.push(Arc::new(Mutex::new(block)) as Arc<Mutex<dyn PciDevice>>);
        }
        
        // 网络设备
        for net_config in &config.net {
            let net = Self::create_net_device(net_config)?;
            devices.push(Arc::new(Mutex::new(net)) as Arc<Mutex<dyn PciDevice>>);
        }
        
        // 文件系统设备
        for fs_config in &config.fs {
            let fs = Self::create_fs_device(fs_config)?;
            devices.push(Arc::new(Mutex::new(fs)) as Arc<Mutex<dyn PciDevice>>);
        }
        
        // 控制台设备
        let console = Self::create_console_device(&config.console)?;
        devices.push(Arc::new(Mutex::new(console)) as Arc<Mutex<dyn PciDevice>>);
        
        // 串口设备
        let serial = Self::create_serial_device(&config.serial)?;
        devices.push(Arc::new(Mutex::new(serial)) as Arc<Mutex<dyn PciDevice>>);
        
        // Balloon 设备
        let balloon = Self::create_balloon_device()?;
        devices.push(Arc::new(Mutex::new(balloon)) as Arc<Mutex<dyn PciDevice>>);
        
        // 4. 创建 MMIO 设备
        let mut mmio_devices = Vec::new();
        
        // 5. 创建传统设备
        let mut serial_devices = Vec::new();
        
        Ok(Self {
            devices,
            pci_devices: HashMap::new(),
            mmio_devices,
            interrupt_controller: Some(interrupt_controller),
            console_devices: Vec::new(),
            net_devices: Vec::new(),
            block_devices: Vec::new(),
            fs_devices: Vec::new(),
            serial_devices,
            config,
            vm_config,
            interrupt_sources: Vec::new(),
            acpi_table: Arc::new(Mutex::new(AcpiTable::new())),
            bus_devices: Vec::new(),
        })
    }
}

Virtio 设备创建

块设备

rust
// vmm/src/device_manager.rs
impl DeviceManager {
    fn create_block_device(
        config: &DiskConfig,
        guest_memory: &GuestMemoryMmap,
    ) -> Result<virtio_devices::Block> {
        // 打开磁盘文件
        let disk_file = OpenOptions::new()
            .read(true)
            .write(!config.readonly)
            .open(&config.path)?;
        
        // 创建 Virtio-blk 设备
        let block = virtio_devices::Block::new(
            disk_file,
            config.readonly,
            config.direct,
            config.iommu,
            config.num_queues,
            config.queue_size,
        )?;
        
        // 配置中断
        block.set_irq(PciInterruptLine::IntX);
        
        Ok(block)
    }
}

网络设备

rust
// vmm/src/device_manager.rs
impl DeviceManager {
    fn create_net_device(
        config: &NetConfig,
    ) -> Result<virtio_devices::Net> {
        // 打开网络设备
        let net_dev = virtio_devices::Net::new(
            &config.tap,
            config.mac,
            config.mtu,
            config.iommu,
            config.num_queues,
            config.queue_size,
        )?;
        
        // 配置中断
        net_dev.set_irq(PciInterruptLine::IntX);
        
        Ok(net_dev)
    }
}

文件系统设备

rust
// vmm/src/device_manager.rs
impl DeviceManager {
    fn create_fs_device(
        config: &FSConfig,
    ) -> Result<virtio_devices::Fs> {
        // 创建 Virtio-fs 设备
        let fs = virtio_devices::Fs::new(
            &config.tag,
            &config.sock,
            config.num_queues,
            config.queue_size,
            config.queue_size_worker,
        )?;
        
        // 配置中断
        fs.set_irq(PciInterruptLine::IntX);
        
        Ok(fs)
    }
}

控制台设备

rust
// vmm/src/device_manager.rs
impl DeviceManager {
    fn create_console_device(
        config: &ConsoleConfig,
    ) -> Result<virtio_devices::Console> {
        // 创建控制台设备
        let console = virtio_devices::Console::new(
            config.stdin,
            config.stdout,
            config.iommu,
        )?;
        
        // 配置输入输出
        if config.stdin {
            console.set_input(BufReader::new(io::stdin()));
        }
        if config.stdout {
            console.set_output(BufWriter::new(io::stdout()));
        }
        
        // 配置中断
        console.set_irq(PciInterruptLine::IntX);
        
        Ok(console)
    }
}

设备挂载

PCI 挂载

rust
// vmm/src/device_manager.rs
impl DeviceManager {
    pub fn attach_pci_device(
        &mut self,
        device: Arc<Mutex<dyn PciDevice>>,
    ) -> Result<u32> {
        // 1. 分配 PCI 地址
        let pci_address = self.pci_root.allocate_address()?;
        
        // 2. 挂载到 PCI Root
        self.pci_root.attach_device(
            device.clone(),
            pci_address,
        )?;
        
        // 3. 存储设备映射
        self.pci_devices.insert(pci_address, device.clone());
        
        // 4. 配置 BAR
        self.configure_pci_bar(device, pci_address)?;
        
        // 5. 映射 MMIO
        self.map_pci_mmio(device, pci_address)?;
        
        Ok(pci_address)
    }
}

MMIO 挂载

rust
// vmm/src/device_manager.rs
impl DeviceManager {
    pub fn attach_mmio_device(
        &mut self,
        device: Arc<Mutex<dyn MmioDevice>>,
        base_address: u64,
    ) -> Result<()> {
        // 1. 获取设备信息
        let size = device.lock().unwrap().size();
        
        // 2. 映射到 MMIO 总线
        self.mmio_bus.insert_device(
            device.clone(),
            base_address,
            size,
        )?;
        
        // 3. 存储设备列表
        self.mmio_devices.push(device);
        
        Ok(())
    }
}

中断管理

中断配置

rust
// vmm/src/device_manager.rs
impl DeviceManager {
    pub fn configure_interrupts(
        &mut self,
        device: &Arc<Mutex<dyn PciDevice>>,
        interrupt_line: PciInterruptLine,
    ) -> Result<()> {
        // 1. 创建中断源
        let interrupt_source = self.create_interrupt_source(
            interrupt_line,
        )?;
        
        // 2. 配置中断控制器
        self.interrupt_controller.lock().unwrap()
            .configure_interrupt(
                interrupt_line,
                interrupt_source.clone(),
            )?;
        
        // 3. 存储中断源
        self.interrupt_sources.push(interrupt_source);
        
        Ok(())
    }
    
    fn create_interrupt_source(
        &self,
        interrupt_line: PciInterruptLine,
    ) -> Result<Arc<Mutex<InterruptSourceGroup>>> {
        // 根据中断类型创建
        match interrupt_line {
            PciInterruptLine::IntX => {
                // INTx 中断
                Ok(Arc::new(Mutex::new(IntxInterruptGroup::new()?)))
            }
            PciInterruptLine::Msi => {
                // MSI 中断
                Ok(Arc::new(Mutex::new(MsiInterruptGroup::new()?)))
            }
            PciInterruptLine::MsiX => {
                // MSI-X 中断
                Ok(Arc::new(Mutex::new(MsixInterruptGroup::new()?)))
            }
        }
    }
}

中断触发

rust
// vmm/src/device_manager.rs
impl DeviceManager {
    pub fn trigger_interrupt(
        &self,
        device_id: u32,
        interrupt_index: usize,
    ) -> Result<()> {
        // 1. 获取中断源
        let interrupt_source = self.get_interrupt_source(device_id)?;
        
        // 2. 触发中断
        interrupt_source.lock().unwrap()
            .trigger_interrupt(interrupt_index)?;
        
        // 3. 通知中断控制器
        self.interrupt_controller.lock().unwrap()
            .trigger_interrupt(device_id, interrupt_index)?;
        
        Ok(())
    }
}

设备热插拔

热插拔流程

rust
// vmm/src/device_manager.rs
impl DeviceManager {
    pub fn hotplug_device(
        &mut self,
        device_config: DeviceConfig,
    ) -> Result<()> {
        // 1. 创建设备
        let device = match device_config {
            DeviceConfig::Disk(config) => {
                Arc::new(Mutex::new(Self::create_block_device(&config, &self.guest_memory)?))
            }
            DeviceConfig::Net(config) => {
                Arc::new(Mutex::new(Self::create_net_device(&config)?))
            }
            // ...
        };
        
        // 2. 挂载设备
        let pci_address = self.attach_pci_device(device.clone())?;
        
        // 3. 通知 Guest
        self.notify_hotplug_acpi(pci_address)?;
        
        Ok(())
    }
    
    pub fn hotremove_device(
        &mut self,
        pci_address: u32,
    ) -> Result<()> {
        // 1. 获取设备
        let device = self.pci_devices.get(&pci_address)
            .ok_or(Error::DeviceNotFound)?;
        
        // 2. 通知 Guest
        self.notify_hotremove_acpi(pci_address)?;
        
        // 3. 断开设备
        self.pci_root.detach_device(pci_address)?;
        
        // 4. 移除设备
        self.pci_devices.remove(&pci_address);
        
        Ok(())
    }
}

快照

设备快照

rust
// vmm/src/device_manager.rs
impl DeviceManager {
    pub fn snapshot(&self) -> Result<DeviceManagerSnapshotData> {
        let mut snapshot = Snapshot::new(DEVICE_MANAGER_SNAPSHOT_ID);
        
        // 保存每个设备的状态
        for (pci_address, device) in &self.pci_devices {
            let device_snapshot = device.lock().unwrap().snapshot()?;
            snapshot.add_data_section(
                SnapshotDataSection::new_from_state(&device_snapshot)?
            );
        }
        
        // 保存 MMIO 设备状态
        for device in &self.mmio_devices {
            let device_snapshot = device.lock().unwrap().snapshot()?;
            snapshot.add_data_section(
                SnapshotDataSection::new_from_state(&device_snapshot)?
            );
        }
        
        // 保存中断控制器状态
        if let Some(interrupt_controller) = &self.interrupt_controller {
            let controller_snapshot = interrupt_controller.lock().unwrap().snapshot()?;
            snapshot.add_data_section(
                SnapshotDataSection::new_from_state(&controller_snapshot)?
            );
        }
        
        Ok(snapshot)
    }
}

错误处理

错误类型

rust
// vmm/src/device_manager.rs
#[derive(Debug, Error)]
pub enum Error {
    #[error("Failed to create device: {0}")]
    CreateDevice(#[source] io::Error),
    
    #[error("Failed to attach device to PCI: {0}")]
    AttachPciDevice(#[source] PciRootError),
    
    #[error("Failed to map device MMIO: {0}")]
    MapMmio(#[source] io::Error),
    
    #[error("Failed to configure interrupts: {0}")]
    ConfigureInterrupts(#[source] InterruptControllerError),
    
    #[error("Device not found: {0}")]
    DeviceNotFound(u32),
    
    #[error("Failed to hotplug device: {0}")]
    HotplugDevice(#[source] io::Error),
    
    // ...
}

下一步