From 0bd910e8b018540d341c2739fa40d597514c6e67 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Fri, 25 Nov 2022 16:44:42 +0100 Subject: [PATCH] devices, vmm: Move Serial to new restore design Signed-off-by: Sebastien Boeuf --- devices/src/legacy/serial.rs | 91 ++++++++++++++++++++++++------------ fuzz/fuzz_targets/serial.rs | 1 + vmm/src/device_manager.rs | 2 + 3 files changed, 64 insertions(+), 30 deletions(-) diff --git a/devices/src/legacy/serial.rs b/devices/src/legacy/serial.rs index 6c870b5b1..8453fbcfe 100644 --- a/devices/src/legacy/serial.rs +++ b/devices/src/legacy/serial.rs @@ -63,7 +63,6 @@ pub struct Serial { id: String, interrupt_enable: u8, interrupt_identification: u8, - interrupt: Arc, line_control: u8, line_status: u8, modem_control: u8, @@ -71,6 +70,7 @@ pub struct Serial { scratch: u8, baud_divisor: u16, in_buffer: VecDeque, + interrupt: Arc, out: Option>, } @@ -93,19 +93,56 @@ impl Serial { id: String, interrupt: Arc, out: Option>, + state: Option, ) -> Serial { + let ( + interrupt_enable, + interrupt_identification, + line_control, + line_status, + modem_control, + modem_status, + scratch, + baud_divisor, + in_buffer, + ) = if let Some(state) = state { + ( + state.interrupt_enable, + state.interrupt_identification, + state.line_control, + state.line_status, + state.modem_control, + state.modem_status, + state.scratch, + state.baud_divisor, + state.in_buffer.into(), + ) + } else { + ( + 0, + DEFAULT_INTERRUPT_IDENTIFICATION, + DEFAULT_LINE_CONTROL, + DEFAULT_LINE_STATUS, + DEFAULT_MODEM_CONTROL, + DEFAULT_MODEM_STATUS, + 0, + DEFAULT_BAUD_DIVISOR, + VecDeque::new(), + ) + }; + Serial { id, - interrupt_enable: 0, - interrupt_identification: DEFAULT_INTERRUPT_IDENTIFICATION, + interrupt_enable, + interrupt_identification, + line_control, + line_status, + modem_control, + modem_status, + scratch, + baud_divisor, + in_buffer, interrupt, - line_control: DEFAULT_LINE_CONTROL, - line_status: DEFAULT_LINE_STATUS, - modem_control: DEFAULT_MODEM_CONTROL, - modem_status: DEFAULT_MODEM_STATUS, - scratch: 0, - baud_divisor: DEFAULT_BAUD_DIVISOR, - in_buffer: VecDeque::new(), out, } } @@ -115,13 +152,18 @@ impl Serial { id: String, interrupt: Arc, out: Box, + state: Option, ) -> Serial { - Self::new(id, interrupt, Some(out)) + Self::new(id, interrupt, Some(out), state) } /// Constructs a Serial port with no connected output. - pub fn new_sink(id: String, interrupt: Arc) -> Serial { - Self::new(id, interrupt, None) + pub fn new_sink( + id: String, + interrupt: Arc, + state: Option, + ) -> Serial { + Self::new(id, interrupt, None, state) } pub fn set_out(&mut self, out: Box) { @@ -242,18 +284,6 @@ impl Serial { in_buffer: self.in_buffer.clone().into(), } } - - fn set_state(&mut self, state: &SerialState) { - self.interrupt_enable = state.interrupt_enable; - self.interrupt_identification = state.interrupt_identification; - self.line_control = state.line_control; - self.line_status = state.line_status; - self.modem_control = state.modem_control; - self.modem_status = state.modem_status; - self.scratch = state.scratch; - self.baud_divisor = state.baud_divisor; - self.in_buffer = state.in_buffer.clone().into(); - } } impl BusDevice for Serial { @@ -306,11 +336,6 @@ impl Snapshottable for Serial { fn snapshot(&mut self) -> std::result::Result { Snapshot::new_from_versioned_state(&self.id, &self.state()) } - - fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> { - self.set_state(&snapshot.to_versioned_state(&self.id)?); - Ok(()) - } } impl Pausable for Serial {} @@ -384,6 +409,7 @@ mod tests { String::from(SERIAL_NAME), Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), Box::new(serial_out.clone()), + None, ); serial.write(0, DATA as u64, &[b'x', b'y']); @@ -404,6 +430,7 @@ mod tests { String::from(SERIAL_NAME), Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), Box::new(serial_out), + None, ); // write 1 to the interrupt event fd, so that read doesn't block in case the event fd @@ -440,6 +467,7 @@ mod tests { let mut serial = Serial::new_sink( String::from(SERIAL_NAME), Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), + None, ); // write 1 to the interrupt event fd, so that read doesn't block in case the event fd @@ -462,6 +490,7 @@ mod tests { let mut serial = Serial::new_sink( String::from(SERIAL_NAME), Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), + None, ); serial.write(0, LCR as u64, &[LCR_DLAB_BIT]); @@ -483,6 +512,7 @@ mod tests { let mut serial = Serial::new_sink( String::from(SERIAL_NAME), Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), + None, ); serial.write(0, MCR as u64, &[MCR_LOOP_BIT]); @@ -509,6 +539,7 @@ mod tests { let mut serial = Serial::new_sink( String::from(SERIAL_NAME), Arc::new(TestInterrupt::new(intr_evt.try_clone().unwrap())), + None, ); serial.write(0, SCR as u64, &[0x12]); diff --git a/fuzz/fuzz_targets/serial.rs b/fuzz/fuzz_targets/serial.rs index 1648c26c3..b8a17ad80 100644 --- a/fuzz/fuzz_targets/serial.rs +++ b/fuzz/fuzz_targets/serial.rs @@ -15,6 +15,7 @@ fuzz_target!(|bytes| { let mut serial = Serial::new_sink( "serial".into(), Arc::new(TestInterrupt::new(EventFd::new(EFD_NONBLOCK).unwrap())), + None, ); let mut i = 0; diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index d6e64c0d0..9507f281d 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -1716,6 +1716,8 @@ impl DeviceManager { id.clone(), interrupt_group, serial_writer, + versioned_state_from_id(self.snapshot.as_ref(), id.as_str()) + .map_err(DeviceManagerError::RestoreGetState)?, ))); self.bus_devices