From a52b614a61171745dcbb748491d8d7fbed9c58f9 Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Thu, 30 Jul 2020 13:02:43 +0000 Subject: [PATCH] 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 --- vmm/src/device_manager.rs | 52 ++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 5186ccd17..873f28344 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -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>>, virtio_console_input: Option>, - input_enabled: bool, + input: Option, } 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, })) }