@@ -15,7 +15,7 @@ use legacy::{LegacyDeviceError, PortIODeviceManager};
15
15
use linux_loader:: loader:: Cmdline ;
16
16
use log:: error;
17
17
use mmio:: { MMIODeviceManager , MmioError } ;
18
- use pci_mngr:: { PciDevices , PciManagerError } ;
18
+ use pci_mngr:: { PciDevices , PciDevicesConstructorArgs , PciManagerError } ;
19
19
use persist:: { ACPIDeviceManagerConstructorArgs , MMIODevManagerConstructorArgs } ;
20
20
use resources:: ResourceAllocator ;
21
21
use serde:: { Deserialize , Serialize } ;
@@ -127,30 +127,39 @@ impl DeviceManager {
127
127
Ok ( serial)
128
128
}
129
129
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
+
130
153
#[ cfg_attr( target_arch = "aarch64" , allow( unused) ) ]
131
154
pub fn new (
132
155
event_manager : & mut EventManager ,
133
- vcpu_exit_evt : & EventFd ,
156
+ vcpus_exit_evt : & EventFd ,
134
157
vm : & Vm ,
135
158
) -> Result < Self , DeviceManagerCreateError > {
136
159
let resource_allocator = Arc :: new ( ResourceAllocator :: new ( ) ?) ;
137
160
#[ 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) ?;
154
163
155
164
Ok ( DeviceManager {
156
165
resource_allocator,
@@ -270,6 +279,8 @@ impl DeviceManager {
270
279
#[ derive( Debug , Default , Clone , Serialize , Deserialize ) ]
271
280
/// State of devices in the system
272
281
pub struct DevicesState {
282
+ /// Resource allocator state
283
+ pub resource_allocator_state : resources:: ResourceAllocatorState ,
273
284
/// MMIO devices state
274
285
pub mmio_state : persist:: DeviceStates ,
275
286
/// ACPI devices state
@@ -292,12 +303,15 @@ pub enum DevicePersistError {
292
303
SerialRestore ( #[ from] EmulateSerialInitError ) ,
293
304
/// Error inserting device in bus: {0}
294
305
Bus ( #[ from] vm_device:: BusError ) ,
306
+ /// Error creating DeviceManager: {0}
307
+ DeviceManager ( #[ from] DeviceManagerCreateError ) ,
295
308
}
296
309
297
310
pub struct DeviceRestoreArgs < ' a > {
298
311
pub mem : & ' a GuestMemoryMmap ,
299
312
pub vm : & ' a Vm ,
300
313
pub event_manager : & ' a mut EventManager ,
314
+ pub vcpus_exit_evt : & ' a EventFd ,
301
315
pub vm_resources : & ' a mut VmResources ,
302
316
pub instance_id : & ' a str ,
303
317
pub restored_from_file : bool ,
@@ -315,15 +329,82 @@ impl std::fmt::Debug for DeviceRestoreArgs<'_> {
315
329
}
316
330
}
317
331
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 {
320
338
DevicesState {
339
+ resource_allocator_state : self . resource_allocator . save ( ) ,
321
340
mmio_state : self . mmio_devices . save ( ) ,
322
341
acpi_state : self . acpi_devices . save ( ) ,
323
342
pci_state : self . pci_devices . save ( ) ,
324
343
}
325
344
}
326
345
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 {
327
408
/// Sets RDA bit in serial console
328
409
pub fn emulate_serial_init ( & self ) -> Result < ( ) , EmulateSerialInitError > {
329
410
// When restoring from a previously saved state, there is no serial
@@ -361,43 +442,6 @@ impl DeviceManager {
361
442
Ok ( ( ) )
362
443
}
363
444
}
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
- }
401
445
}
402
446
403
447
#[ cfg( test) ]
0 commit comments