diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index da91435f2..53acc7df1 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -609,7 +609,6 @@ pub struct DeviceManager { pci_bus: Option>>, // MSI Interrupt Manager - #[cfg(feature = "pci_support")] msi_interrupt_manager: Arc>, // VFIO KVM device @@ -639,10 +638,15 @@ pub struct DeviceManager { // Tree of devices, representing the dependencies between devices. // Useful for introspection, snapshot and restore. device_tree: HashMap, + + // Exit event + #[cfg(feature = "acpi")] + exit_evt: EventFd, + // Reset event + reset_evt: EventFd, } impl DeviceManager { - #[allow(clippy::too_many_arguments)] pub fn new( vm_fd: Arc, config: Arc>, @@ -651,13 +655,6 @@ impl DeviceManager { reset_evt: &EventFd, vmm_path: PathBuf, ) -> DeviceManagerResult>> { - let mut virtio_devices: Vec<(VirtioDeviceArc, bool, String)> = Vec::new(); - let mut bus_devices: Vec>> = Vec::new(); - let mut device_tree = HashMap::new(); - - #[allow(unused_mut)] - let mut cmdline_additions = Vec::new(); - let address_manager = Arc::new(AddressManager { allocator: memory_manager.lock().unwrap().allocator(), io_bus: Arc::new(devices::Bus::new()), @@ -685,53 +682,24 @@ impl DeviceManager { Arc::clone(&kvm_gsi_msi_routes), )); - let ioapic = DeviceManager::add_ioapic( - &address_manager, - Arc::clone(&msi_interrupt_manager), - &mut device_tree, - )?; - let ioapic_migratable = Arc::clone(&ioapic) as Arc>; - bus_devices.push(Arc::clone(&ioapic) as Arc>); - - // Now we can create the legacy interrupt manager, which needs the freshly - // formed IOAPIC device. - let legacy_interrupt_manager: Arc< - dyn InterruptManager, - > = Arc::new(KvmLegacyUserspaceInterruptManager::new(ioapic.clone())); - - #[cfg(feature = "acpi")] - address_manager - .allocator - .lock() - .unwrap() - .allocate_io_addresses(Some(GuestAddress(0x0a00)), 0x18, None) - .ok_or(DeviceManagerError::AllocateIOPort)?; - - #[cfg(feature = "acpi")] - address_manager - .io_bus - .insert(memory_manager.clone(), 0xa00, 0x18) - .map_err(DeviceManagerError::BusError)?; - - let mut device_manager = DeviceManager { + let device_manager = DeviceManager { address_manager: Arc::clone(&address_manager), console: Arc::new(Console::default()), - ioapic: Some(ioapic), - cmdline_additions, + ioapic: None, + cmdline_additions: Vec::new(), #[cfg(feature = "acpi")] ged_notification_device: None, config, migratable_devices: HashMap::new(), memory_manager, virtio_devices: Vec::new(), - bus_devices, + bus_devices: Vec::new(), vmm_path, vhost_user_backends: Vec::new(), device_id_cnt: Wrapping(0), #[cfg(feature = "pci_support")] pci_bus: None, - #[cfg(feature = "pci_support")] - msi_interrupt_manager: Arc::clone(&msi_interrupt_manager), + msi_interrupt_manager, #[cfg(feature = "pci_support")] kvm_device_fd: None, #[cfg(feature = "pci_support")] @@ -744,39 +712,12 @@ impl DeviceManager { pci_id_list: HashMap::new(), #[cfg(feature = "pci_support")] pci_devices: HashMap::new(), - device_tree, + device_tree: HashMap::new(), + #[cfg(feature = "acpi")] + exit_evt: _exit_evt.try_clone().map_err(DeviceManagerError::EventFd)?, + reset_evt: reset_evt.try_clone().map_err(DeviceManagerError::EventFd)?, }; - device_manager - .add_legacy_devices(reset_evt.try_clone().map_err(DeviceManagerError::EventFd)?)?; - - device_manager.add_migratable_device(ioapic_migratable); - - #[cfg(feature = "acpi")] - { - device_manager.ged_notification_device = device_manager.add_acpi_devices( - &legacy_interrupt_manager, - reset_evt.try_clone().map_err(DeviceManagerError::EventFd)?, - _exit_evt.try_clone().map_err(DeviceManagerError::EventFd)?, - )?; - } - - device_manager.console = - device_manager.add_console_device(&legacy_interrupt_manager, &mut virtio_devices)?; - - #[cfg(any(feature = "pci_support", feature = "mmio_support"))] - virtio_devices.append(&mut device_manager.make_virtio_devices()?); - - if cfg!(feature = "pci_support") { - device_manager.add_pci_devices(virtio_devices.clone())?; - } else if cfg!(feature = "mmio_support") { - device_manager.add_mmio_devices(virtio_devices.clone(), &legacy_interrupt_manager)?; - } - - device_manager.virtio_devices = virtio_devices; - - let device_manager = Arc::new(Mutex::new(device_manager)); - #[cfg(feature = "acpi")] address_manager .allocator @@ -785,6 +726,8 @@ impl DeviceManager { .allocate_io_addresses(Some(GuestAddress(0xae00)), 0x10, None) .ok_or(DeviceManagerError::AllocateIOPort)?; + let device_manager = Arc::new(Mutex::new(device_manager)); + #[cfg(feature = "acpi")] address_manager .io_bus @@ -798,6 +741,70 @@ impl DeviceManager { Ok(device_manager) } + pub fn create_devices(&mut self) -> DeviceManagerResult<()> { + let mut virtio_devices: Vec<(VirtioDeviceArc, bool, String)> = Vec::new(); + + let ioapic = self.add_ioapic()?; + + // Now we can create the legacy interrupt manager, which needs the freshly + // formed IOAPIC device. + let legacy_interrupt_manager: Arc< + dyn InterruptManager, + > = Arc::new(KvmLegacyUserspaceInterruptManager::new(ioapic)); + + #[cfg(feature = "acpi")] + self.address_manager + .allocator + .lock() + .unwrap() + .allocate_io_addresses(Some(GuestAddress(0x0a00)), 0x18, None) + .ok_or(DeviceManagerError::AllocateIOPort)?; + + #[cfg(feature = "acpi")] + self.address_manager + .io_bus + .insert( + Arc::clone(&self.memory_manager) as Arc>, + 0xa00, + 0x18, + ) + .map_err(DeviceManagerError::BusError)?; + + self.add_legacy_devices( + self.reset_evt + .try_clone() + .map_err(DeviceManagerError::EventFd)?, + )?; + + #[cfg(feature = "acpi")] + { + self.ged_notification_device = self.add_acpi_devices( + &legacy_interrupt_manager, + self.reset_evt + .try_clone() + .map_err(DeviceManagerError::EventFd)?, + self.exit_evt + .try_clone() + .map_err(DeviceManagerError::EventFd)?, + )?; + } + + self.console = self.add_console_device(&legacy_interrupt_manager, &mut virtio_devices)?; + + #[cfg(any(feature = "pci_support", feature = "mmio_support"))] + virtio_devices.append(&mut self.make_virtio_devices()?); + + if cfg!(feature = "pci_support") { + self.add_pci_devices(virtio_devices.clone())?; + } else if cfg!(feature = "mmio_support") { + self.add_mmio_devices(virtio_devices.clone(), &legacy_interrupt_manager)?; + } + + self.virtio_devices = virtio_devices; + + Ok(()) + } + fn state(&self) -> DeviceManagerState { DeviceManagerState { device_tree: self.device_tree.clone(), @@ -943,26 +950,29 @@ impl DeviceManager { Ok(()) } - fn add_ioapic( - address_manager: &Arc, - interrupt_manager: Arc>, - device_tree: &mut HashMap, - ) -> DeviceManagerResult>> { + fn add_ioapic(&mut self) -> DeviceManagerResult>> { let id = String::from(IOAPIC_DEVICE_NAME); - device_tree.insert(id.clone(), Node::default()); + self.device_tree.insert(id.clone(), Node::default()); // Create IOAPIC let ioapic = Arc::new(Mutex::new( - ioapic::Ioapic::new(id, APIC_START, interrupt_manager) + ioapic::Ioapic::new(id, APIC_START, Arc::clone(&self.msi_interrupt_manager)) .map_err(DeviceManagerError::CreateIoapic)?, )); - address_manager + self.ioapic = Some(ioapic.clone()); + + self.address_manager .mmio_bus .insert(ioapic.clone(), IOAPIC_START.0, IOAPIC_SIZE) .map_err(DeviceManagerError::BusError)?; + self.bus_devices + .push(Arc::clone(&ioapic) as Arc>); + + self.add_migratable_device(Arc::clone(&ioapic) as Arc>); + Ok(ioapic) } diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index a4d2f898f..6e1ce9e13 100755 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -334,6 +334,12 @@ impl Vm { ) .map_err(Error::DeviceManager)?; + device_manager + .lock() + .unwrap() + .create_devices() + .map_err(Error::DeviceManager)?; + let cpu_manager = cpu::CpuManager::new( &config.lock().unwrap().cpus.clone(), &device_manager,