Skip to content

Commit fba9c99

Browse files
AlexandruCihodaruluminitavoicu
authored andcommitted
[snapshot]: Kick pio serial after restore
After resuming from snapshot, the console is unresponsive. This issue is caused by the fact that we are not saving the serial console state. After restore Received Data Available interrupt was not set thus driver did not accept any input. Signed-off-by: AlexandruCihodaru <[email protected]> Suggested-by: Laura Loghin <[email protected]> Signed-off-by: AlexandruCihodaru <[email protected]>
1 parent 302851d commit fba9c99

File tree

3 files changed

+31
-0
lines changed

3 files changed

+31
-0
lines changed

src/devices/src/legacy/serial.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ use utils::epoll::EventSet;
2929
/// Trait that composes the `std::io::Read` and `std::os::unix::io::AsRawFd` traits.
3030
pub trait ReadableFd: io::Read + AsRawFd {}
3131

32+
// Received Data Available interrupt - for letting the driver know that
33+
// there is some pending data to be processed.
34+
pub const IER_RDA_BIT: u8 = 0b0000_0001;
35+
// Received Data Available interrupt offset
36+
pub const IER_RDA_OFFSET: u8 = 1;
37+
3238
#[derive(Debug)]
3339
pub enum RawIOError {
3440
Serial(SerialError<io::Error>),

src/vmm/src/builder.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,8 @@ pub fn build_microvm_from_snapshot(
528528
MMIODeviceManager::restore(mmio_ctor_args, &microvm_state.device_states)
529529
.map_err(MicrovmStateError::RestoreDevices)
530530
.map_err(RestoreMicrovmState)?;
531+
vmm.emulate_serial_init()
532+
.map_err(StartMicrovmError::Internal)?;
531533

532534
// Move vcpus to their own threads and start their state machine in the 'Paused' state.
533535
vmm.start_vcpus(

src/vmm/src/lib.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use crate::vstate::{
5252
vm::Vm,
5353
};
5454
use arch::DeviceType;
55+
use devices::legacy::serial::{IER_RDA_BIT, IER_RDA_OFFSET};
5556
use devices::virtio::balloon::Error as BalloonError;
5657
use devices::virtio::{
5758
Balloon, BalloonConfig, BalloonStats, Block, MmioTransport, Net, BALLOON_DEV_ID, TYPE_BALLOON,
@@ -351,6 +352,28 @@ impl Vmm {
351352
&self.guest_memory
352353
}
353354

355+
/// Sets RDA bit in serial console
356+
pub fn emulate_serial_init(&self) -> Result<()> {
357+
#[cfg(target_arch = "x86_64")]
358+
let mut serial = self
359+
.pio_device_manager
360+
.stdio_serial
361+
.lock()
362+
.expect("Poisoned lock");
363+
364+
// When restoring from a previously saved state, there is no serial
365+
// driver initialization, therefore the RDA (Received Data Available)
366+
// interrupt is not enabled. Because of that, the driver won't get
367+
// notified of any bytes that we send to the guest. The clean solution
368+
// would be to save the whole serial device state when we do the vm
369+
// serialization. For now we set that bit manually
370+
serial
371+
.serial
372+
.write(IER_RDA_OFFSET, IER_RDA_BIT)
373+
.map_err(|_| Error::Serial(std::io::Error::last_os_error()))?;
374+
Ok(())
375+
}
376+
354377
/// Injects CTRL+ALT+DEL keystroke combo in the i8042 device.
355378
#[cfg(target_arch = "x86_64")]
356379
pub fn send_ctrl_alt_del(&mut self) -> Result<()> {

0 commit comments

Comments
 (0)