@@ -15,7 +15,7 @@ use legacy::{LegacyDeviceError, PortIODeviceManager};
1515use linux_loader:: loader:: Cmdline ;
1616use log:: error;
1717use mmio:: { MMIODeviceManager , MmioError } ;
18- use pci_mngr:: { PciDevices , PciManagerError } ;
18+ use pci_mngr:: { PciDevices , PciDevicesConstructorArgs , PciManagerError } ;
1919use persist:: { ACPIDeviceManagerConstructorArgs , MMIODevManagerConstructorArgs } ;
2020use resources:: ResourceAllocator ;
2121use serde:: { Deserialize , Serialize } ;
@@ -127,30 +127,39 @@ impl DeviceManager {
127127 Ok ( serial)
128128 }
129129
130+ #[ cfg( target_arch = "x86_64" ) ]
131+ fn create_legacy_devices (
132+ event_manager : & mut EventManager ,
133+ vcpus_exit_evt : & EventFd ,
134+ vm : & Vm ,
135+ resource_allocator : & ResourceAllocator ,
136+ ) -> Result < PortIODeviceManager , DeviceManagerCreateError > {
137+ Self :: set_stdout_nonblocking ( ) ;
138+
139+ // Create serial device
140+ let serial = Self :: setup_serial_device ( event_manager) ?;
141+ let reset_evt = vcpus_exit_evt
142+ . try_clone ( )
143+ . map_err ( DeviceManagerCreateError :: EventFd ) ?;
144+ // Create keyboard emulator for reset event
145+ let i8042 = Arc :: new ( Mutex :: new ( I8042Device :: new ( reset_evt) ?) ) ;
146+
147+ // create pio dev manager with legacy devices
148+ let mut legacy_devices = PortIODeviceManager :: new ( serial, i8042) ?;
149+ legacy_devices. register_devices ( & resource_allocator. pio_bus , vm) ?;
150+ Ok ( legacy_devices)
151+ }
152+
130153 #[ cfg_attr( target_arch = "aarch64" , allow( unused) ) ]
131154 pub fn new (
132155 event_manager : & mut EventManager ,
133- vcpu_exit_evt : & EventFd ,
156+ vcpus_exit_evt : & EventFd ,
134157 vm : & Vm ,
135158 ) -> Result < Self , DeviceManagerCreateError > {
136159 let resource_allocator = Arc :: new ( ResourceAllocator :: new ( ) ?) ;
137160 #[ cfg( target_arch = "x86_64" ) ]
138- let legacy_devices = {
139- Self :: set_stdout_nonblocking ( ) ;
140-
141- // Create serial device
142- let serial = Self :: setup_serial_device ( event_manager) ?;
143- let reset_evt = vcpu_exit_evt
144- . try_clone ( )
145- . map_err ( DeviceManagerCreateError :: EventFd ) ?;
146- // Create keyboard emulator for reset event
147- let i8042 = Arc :: new ( Mutex :: new ( I8042Device :: new ( reset_evt) ?) ) ;
148-
149- // create pio dev manager with legacy devices
150- let mut legacy_devices = PortIODeviceManager :: new ( serial, i8042) ?;
151- legacy_devices. register_devices ( & resource_allocator. pio_bus , vm) ?;
152- legacy_devices
153- } ;
161+ let legacy_devices =
162+ Self :: create_legacy_devices ( event_manager, vcpus_exit_evt, vm, & resource_allocator) ?;
154163
155164 Ok ( DeviceManager {
156165 resource_allocator,
@@ -270,6 +279,8 @@ impl DeviceManager {
270279#[ derive( Debug , Default , Clone , Serialize , Deserialize ) ]
271280/// State of devices in the system
272281pub struct DevicesState {
282+ /// Resource allocator state
283+ pub resource_allocator_state : resources:: ResourceAllocatorState ,
273284 /// MMIO devices state
274285 pub mmio_state : persist:: DeviceStates ,
275286 /// ACPI devices state
@@ -292,12 +303,15 @@ pub enum DevicePersistError {
292303 SerialRestore ( #[ from] EmulateSerialInitError ) ,
293304 /// Error inserting device in bus: {0}
294305 Bus ( #[ from] vm_device:: BusError ) ,
306+ /// Error creating DeviceManager: {0}
307+ DeviceManager ( #[ from] DeviceManagerCreateError ) ,
295308}
296309
297310pub struct DeviceRestoreArgs < ' a > {
298311 pub mem : & ' a GuestMemoryMmap ,
299312 pub vm : & ' a Vm ,
300313 pub event_manager : & ' a mut EventManager ,
314+ pub vcpus_exit_evt : & ' a EventFd ,
301315 pub vm_resources : & ' a mut VmResources ,
302316 pub instance_id : & ' a str ,
303317 pub restored_from_file : bool ,
@@ -315,15 +329,82 @@ impl std::fmt::Debug for DeviceRestoreArgs<'_> {
315329 }
316330}
317331
318- impl DeviceManager {
319- pub fn save ( & self ) -> DevicesState {
332+ impl < ' a > Persist < ' a > for DeviceManager {
333+ type State = DevicesState ;
334+ type ConstructorArgs = DeviceRestoreArgs < ' a > ;
335+ type Error = DevicePersistError ;
336+
337+ fn save ( & self ) -> Self :: State {
320338 DevicesState {
339+ resource_allocator_state : self . resource_allocator . save ( ) ,
321340 mmio_state : self . mmio_devices . save ( ) ,
322341 acpi_state : self . acpi_devices . save ( ) ,
323342 pci_state : self . pci_devices . save ( ) ,
324343 }
325344 }
326345
346+ fn restore (
347+ constructor_args : Self :: ConstructorArgs ,
348+ state : & Self :: State ,
349+ ) -> std:: result:: Result < Self , Self :: Error > {
350+ // Safe to unwrap here. ResourceAllocator restoring cannot fail.
351+ let resource_allocator =
352+ Arc :: new ( ResourceAllocator :: restore ( ( ) , & state. resource_allocator_state ) . unwrap ( ) ) ;
353+
354+ // Restore MMIO devices
355+ let mmio_ctor_args = MMIODevManagerConstructorArgs {
356+ mem : constructor_args. mem ,
357+ vm : constructor_args. vm ,
358+ event_manager : constructor_args. event_manager ,
359+ resource_allocator : & resource_allocator,
360+ vm_resources : constructor_args. vm_resources ,
361+ instance_id : constructor_args. instance_id ,
362+ restored_from_file : constructor_args. restored_from_file ,
363+ } ;
364+ let mmio_devices = MMIODeviceManager :: restore ( mmio_ctor_args, & state. mmio_state ) ?;
365+
366+ // Restore ACPI devices
367+ let acpi_ctor_args = ACPIDeviceManagerConstructorArgs {
368+ mem : constructor_args. mem ,
369+ resource_allocator : & resource_allocator,
370+ vm : constructor_args. vm ,
371+ } ;
372+ let mut acpi_devices = ACPIDeviceManager :: restore ( acpi_ctor_args, & state. acpi_state ) ?;
373+ acpi_devices. notify_vmgenid ( ) ?;
374+
375+ // Restore PCI devices
376+ let pci_ctor_args = PciDevicesConstructorArgs {
377+ resource_allocator : & resource_allocator,
378+ } ;
379+ let pci_devices = PciDevices :: restore ( pci_ctor_args, & state. pci_state ) ?;
380+
381+ // Setup legacy devices in case of x86
382+ #[ cfg( target_arch = "x86_64" ) ]
383+ let legacy_devices = Self :: create_legacy_devices (
384+ constructor_args. event_manager ,
385+ constructor_args. vcpus_exit_evt ,
386+ constructor_args. vm ,
387+ & resource_allocator,
388+ ) ?;
389+
390+ let device_manager = DeviceManager {
391+ resource_allocator,
392+ mmio_devices,
393+ #[ cfg( target_arch = "x86_64" ) ]
394+ legacy_devices,
395+ acpi_devices,
396+ pci_devices,
397+ } ;
398+
399+ // Restore serial.
400+ // We need to do that after we restore mmio devices, otherwise it won't succeed in Aarch64
401+ device_manager. emulate_serial_init ( ) ?;
402+
403+ Ok ( device_manager)
404+ }
405+ }
406+
407+ impl DeviceManager {
327408 /// Sets RDA bit in serial console
328409 pub fn emulate_serial_init ( & self ) -> Result < ( ) , EmulateSerialInitError > {
329410 // When restoring from a previously saved state, there is no serial
@@ -361,43 +442,6 @@ impl DeviceManager {
361442 Ok ( ( ) )
362443 }
363444 }
364-
365- pub fn restore (
366- & mut self ,
367- state : & DevicesState ,
368- restore_args : DeviceRestoreArgs ,
369- ) -> Result < ( ) , DevicePersistError > {
370- // Restore MMIO devices
371- let mmio_ctor_args = MMIODevManagerConstructorArgs {
372- mem : restore_args. mem ,
373- vm : restore_args. vm ,
374- event_manager : restore_args. event_manager ,
375- resource_allocator : & self . resource_allocator ,
376- vm_resources : restore_args. vm_resources ,
377- instance_id : restore_args. instance_id ,
378- restored_from_file : restore_args. restored_from_file ,
379- } ;
380- self . mmio_devices = MMIODeviceManager :: restore ( mmio_ctor_args, & state. mmio_state ) ?;
381-
382- // Restore serial.
383- // We need to do that after we restore mmio devices, otherwise it won't succeed in Aarch64
384- self . emulate_serial_init ( ) ?;
385-
386- // Restore ACPI devices
387- let acpi_ctor_args = ACPIDeviceManagerConstructorArgs {
388- mem : restore_args. mem ,
389- resource_allocator : & self . resource_allocator ,
390- vm : restore_args. vm ,
391- } ;
392- self . acpi_devices = ACPIDeviceManager :: restore ( acpi_ctor_args, & state. acpi_state ) ?;
393- self . acpi_devices . notify_vmgenid ( ) ?;
394-
395- // Restore PCI devices
396- self . pci_devices
397- . restore ( & state. pci_state , & self . resource_allocator ) ?;
398-
399- Ok ( ( ) )
400- }
401445}
402446
403447#[ cfg( test) ]
0 commit comments