vmm: device_manager: console input should be only consumed by one device

Cloud Hypervisor allows either the serial or virtio console to output to
TTY, but TTY input is pushed to both.

This is not correct. When Linux guest is configured to spawn TTYs on
both ttyS0 and hvc0, the user effectively issues the same commands twice
in different TTYs.

Fix this by only direct input to the one choice that is using host side
TTY.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
Wei Liu 2020-07-30 13:02:43 +00:00 committed by Sebastien Boeuf
parent 5ed794a44c
commit a52b614a61

View File

@ -399,30 +399,41 @@ pub fn get_win_size() -> (u16, u16) {
(ws.cols, ws.rows)
}
enum ConsoleInput {
Serial,
VirtioConsole,
}
#[derive(Default)]
pub struct Console {
// Serial port on 0x3f8
serial: Option<Arc<Mutex<Serial>>>,
virtio_console_input: Option<Arc<virtio_devices::ConsoleInput>>,
input_enabled: bool,
input: Option<ConsoleInput>,
}
impl Console {
pub fn queue_input_bytes(&self, out: &[u8]) -> vmm_sys_util::errno::Result<()> {
if self.serial.is_some() {
self.serial
.as_ref()
.unwrap()
.lock()
.expect("Failed to process stdin event due to poisoned lock")
.queue_input_bytes(out)?;
}
match self.input {
Some(ConsoleInput::Serial) => {
if self.serial.is_some() {
self.serial
.as_ref()
.unwrap()
.lock()
.expect("Failed to process stdin event due to poisoned lock")
.queue_input_bytes(out)?;
}
}
if self.virtio_console_input.is_some() {
self.virtio_console_input
.as_ref()
.unwrap()
.queue_input_bytes(out);
Some(ConsoleInput::VirtioConsole) => {
if self.virtio_console_input.is_some() {
self.virtio_console_input
.as_ref()
.unwrap()
.queue_input_bytes(out);
}
}
None => {}
}
Ok(())
@ -438,7 +449,7 @@ impl Console {
}
pub fn input_enabled(&self) -> bool {
self.input_enabled
self.input.is_some()
}
}
@ -1519,11 +1530,18 @@ impl DeviceManager {
None
};
let input = if serial_config.mode.input_enabled() {
Some(ConsoleInput::Serial)
} else if console_config.mode.input_enabled() {
Some(ConsoleInput::VirtioConsole)
} else {
None
};
Ok(Arc::new(Console {
serial,
virtio_console_input,
input_enabled: serial_config.mode.input_enabled()
|| console_config.mode.input_enabled(),
input,
}))
}