@@ -21,15 +21,16 @@ use pci_mngr::{PciDevices, PciDevicesConstructorArgs, PciManagerError};
2121use persist:: MMIODevManagerConstructorArgs ;
2222use serde:: { Deserialize , Serialize } ;
2323use utils:: time:: TimestampUs ;
24+ use vm_superio:: serial;
2425use vmm_sys_util:: eventfd:: EventFd ;
2526
2627use crate :: device_manager:: acpi:: ACPIDeviceError ;
2728#[ cfg( target_arch = "x86_64" ) ]
2829use crate :: devices:: legacy:: I8042Device ;
2930#[ cfg( target_arch = "aarch64" ) ]
3031use crate :: devices:: legacy:: RTCDevice ;
32+ use crate :: devices:: legacy:: SerialDevice ;
3133use crate :: devices:: legacy:: serial:: SerialOut ;
32- use crate :: devices:: legacy:: { IER_RDA_BIT , IER_RDA_OFFSET , SerialDevice } ;
3334use crate :: devices:: pseudo:: BootTimer ;
3435use crate :: devices:: virtio:: ActivateError ;
3536use crate :: devices:: virtio:: balloon:: BalloonError ;
@@ -47,7 +48,7 @@ use crate::utils::open_file_nonblock;
4748use crate :: vmm_config:: mmds:: MmdsConfigError ;
4849use crate :: vstate:: bus:: BusError ;
4950use crate :: vstate:: memory:: GuestMemoryMmap ;
50- use crate :: { EmulateSerialInitError , EventManager , Vm } ;
51+ use crate :: { EventManager , Vm } ;
5152
5253/// ACPI device manager.
5354pub mod acpi;
@@ -132,6 +133,7 @@ impl DeviceManager {
132133 fn setup_serial_device (
133134 event_manager : & mut EventManager ,
134135 output : Option < & PathBuf > ,
136+ state : Option < & serial:: SerialState > ,
135137 ) -> Result < Arc < Mutex < SerialDevice > > , std:: io:: Error > {
136138 let ( serial_in, serial_out) = match output {
137139 Some ( path) => ( None , open_file_nonblock ( path) . map ( SerialOut :: File ) ?) ,
@@ -142,20 +144,44 @@ impl DeviceManager {
142144 }
143145 } ;
144146
145- let serial = Arc :: new ( Mutex :: new ( SerialDevice :: new ( serial_in, serial_out) ?) ) ;
147+ let serial = Arc :: new ( Mutex :: new ( SerialDevice :: new ( serial_in, serial_out, state ) ?) ) ;
146148 event_manager. add_subscriber ( serial. clone ( ) ) ;
147149 Ok ( serial)
148150 }
149151
152+ fn serial_state ( & self ) -> Option < persist:: SerialState > {
153+ #[ cfg( target_arch = "aarch64" ) ]
154+ {
155+ self . mmio_devices . serial . as_ref ( ) . map ( |device| {
156+ let locked = device. inner . lock ( ) . expect ( "Poisoned lock" ) ;
157+ locked. serial . state ( ) . into ( )
158+ } )
159+ }
160+
161+ #[ cfg( target_arch = "x86_64" ) ]
162+ {
163+ Some (
164+ self . legacy_devices
165+ . stdio_serial
166+ . lock ( )
167+ . expect ( "Poisoned lock" )
168+ . serial
169+ . state ( )
170+ . into ( ) ,
171+ )
172+ }
173+ }
174+
150175 #[ cfg( target_arch = "x86_64" ) ]
151176 fn create_legacy_devices (
152177 event_manager : & mut EventManager ,
153178 vcpus_exit_evt : & EventFd ,
154179 vm : & Vm ,
155180 serial_output : Option < & PathBuf > ,
181+ serial_state : Option < & serial:: SerialState > ,
156182 ) -> Result < PortIODeviceManager , DeviceManagerCreateError > {
157183 // Create serial device
158- let serial = Self :: setup_serial_device ( event_manager, serial_output) ?;
184+ let serial = Self :: setup_serial_device ( event_manager, serial_output, serial_state ) ?;
159185 let reset_evt = vcpus_exit_evt
160186 . try_clone ( )
161187 . map_err ( DeviceManagerCreateError :: EventFd ) ?;
@@ -180,7 +206,7 @@ impl DeviceManager {
180206 ) -> Result < Self , DeviceManagerCreateError > {
181207 #[ cfg( target_arch = "x86_64" ) ]
182208 let legacy_devices =
183- Self :: create_legacy_devices ( event_manager, vcpus_exit_evt, vm, serial_output) ?;
209+ Self :: create_legacy_devices ( event_manager, vcpus_exit_evt, vm, serial_output, None ) ?;
184210
185211 Ok ( DeviceManager {
186212 mmio_devices : MMIODeviceManager :: new ( ) ,
@@ -276,7 +302,7 @@ impl DeviceManager {
276302 . contains ( "console=" ) ;
277303
278304 if cmdline_contains_console {
279- let serial = Self :: setup_serial_device ( event_manager, serial_out_path) ?;
305+ let serial = Self :: setup_serial_device ( event_manager, serial_out_path, None ) ?;
280306 self . mmio_devices . register_mmio_serial ( vm, serial, None ) ?;
281307 self . mmio_devices . add_mmio_serial_to_cmdline ( cmdline) ?;
282308 }
@@ -419,6 +445,8 @@ pub struct DevicesState {
419445 pub acpi_state : persist:: ACPIDeviceManagerState ,
420446 /// PCI devices state
421447 pub pci_state : pci_mngr:: PciDevicesState ,
448+ /// Serial device state
449+ pub serial_state : Option < persist:: SerialState > ,
422450}
423451
424452/// Errors for (de)serialization of the devices.
@@ -466,8 +494,6 @@ pub enum DeviceManagerPersistError {
466494 AcpiRestore ( #[ from] ACPIDeviceError ) ,
467495 /// Error restoring PCI devices: {0}
468496 PciRestore ( DevicePersistError ) ,
469- /// Error resetting serial console: {0}
470- SerialRestore ( #[ from] EmulateSerialInitError ) ,
471497 /// Error inserting device in bus: {0}
472498 Bus ( #[ from] BusError ) ,
473499 /// Error creating DeviceManager: {0}
@@ -504,6 +530,7 @@ impl<'a> Persist<'a> for DeviceManager {
504530 mmio_state : self . mmio_devices . save ( ) ,
505531 acpi_state : self . acpi_devices . save ( ) ,
506532 pci_state : self . pci_devices . save ( ) ,
533+ serial_state : self . serial_state ( ) ,
507534 }
508535 }
509536
@@ -513,11 +540,15 @@ impl<'a> Persist<'a> for DeviceManager {
513540 ) -> Result < Self , Self :: Error > {
514541 // Setup legacy devices in case of x86
515542 #[ cfg( target_arch = "x86_64" ) ]
543+ let serial_state: Option < vm_superio:: serial:: SerialState > =
544+ state. serial_state . as_ref ( ) . map ( Into :: into) ;
545+ #[ cfg( target_arch = "x86_64" ) ]
516546 let legacy_devices = Self :: create_legacy_devices (
517547 constructor_args. event_manager ,
518548 constructor_args. vcpus_exit_evt ,
519549 constructor_args. vm ,
520550 constructor_args. vm_resources . serial_out_path . as_ref ( ) ,
551+ serial_state. as_ref ( ) ,
521552 ) ?;
522553
523554 // Restore MMIO devices
@@ -527,6 +558,7 @@ impl<'a> Persist<'a> for DeviceManager {
527558 event_manager : constructor_args. event_manager ,
528559 vm_resources : constructor_args. vm_resources ,
529560 instance_id : constructor_args. instance_id ,
561+ serial_state : state. serial_state . as_ref ( ) ,
530562 } ;
531563 let mmio_devices = MMIODeviceManager :: restore ( mmio_ctor_args, & state. mmio_state )
532564 . map_err ( DeviceManagerPersistError :: MmioRestore ) ?;
@@ -545,59 +577,13 @@ impl<'a> Persist<'a> for DeviceManager {
545577 let pci_devices = PciDevices :: restore ( pci_ctor_args, & state. pci_state )
546578 . map_err ( DeviceManagerPersistError :: PciRestore ) ?;
547579
548- let device_manager = DeviceManager {
580+ Ok ( DeviceManager {
549581 mmio_devices,
550582 #[ cfg( target_arch = "x86_64" ) ]
551583 legacy_devices,
552584 acpi_devices,
553585 pci_devices,
554- } ;
555-
556- // Restore serial.
557- // We need to do that after we restore mmio devices, otherwise it won't succeed in Aarch64
558- device_manager. emulate_serial_init ( ) ?;
559-
560- Ok ( device_manager)
561- }
562- }
563-
564- impl DeviceManager {
565- /// Sets RDA bit in serial console
566- pub fn emulate_serial_init ( & self ) -> Result < ( ) , EmulateSerialInitError > {
567- // When restoring from a previously saved state, there is no serial
568- // driver initialization, therefore the RDA (Received Data Available)
569- // interrupt is not enabled. Because of that, the driver won't get
570- // notified of any bytes that we send to the guest. The clean solution
571- // would be to save the whole serial device state when we do the vm
572- // serialization. For now we set that bit manually
573-
574- #[ cfg( target_arch = "aarch64" ) ]
575- {
576- if let Some ( device) = & self . mmio_devices . serial {
577- let mut device_locked = device. inner . lock ( ) . expect ( "Poisoned lock" ) ;
578-
579- device_locked
580- . serial
581- . write ( IER_RDA_OFFSET , IER_RDA_BIT )
582- . map_err ( |_| EmulateSerialInitError ( std:: io:: Error :: last_os_error ( ) ) ) ?;
583- }
584- Ok ( ( ) )
585- }
586-
587- #[ cfg( target_arch = "x86_64" ) ]
588- {
589- let mut serial = self
590- . legacy_devices
591- . stdio_serial
592- . lock ( )
593- . expect ( "Poisoned lock" ) ;
594-
595- serial
596- . serial
597- . write ( IER_RDA_OFFSET , IER_RDA_BIT )
598- . map_err ( |_| EmulateSerialInitError ( std:: io:: Error :: last_os_error ( ) ) ) ?;
599- Ok ( ( ) )
600- }
586+ } )
601587 }
602588}
603589
@@ -622,7 +608,7 @@ pub(crate) mod tests {
622608 #[ cfg( target_arch = "x86_64" ) ]
623609 let legacy_devices = PortIODeviceManager {
624610 stdio_serial : Arc :: new ( Mutex :: new (
625- SerialDevice :: new ( None , SerialOut :: Sink ) . unwrap ( ) ,
611+ SerialDevice :: new ( None , SerialOut :: Sink , None ) . unwrap ( ) ,
626612 ) ) ,
627613 i8042 : Arc :: new ( Mutex :: new (
628614 I8042Device :: new ( EventFd :: new ( libc:: EFD_NONBLOCK ) . unwrap ( ) ) . unwrap ( ) ,
0 commit comments