mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-22 11:22:26 +00:00
vm-virtio: Implement console size config feature
One of the features of the virtio console device is its size can be configured and updated. Our first iteration of the console device implementation is lack of this feature. As a result, it had a default fixed size which could not be changed. This commit implements the console config feature and lets us change the console size from the vmm side. During the activation of the device, vmm reads the current terminal size, sets the console configuration accordinly, and lets the driver know about this configuration by sending an interrupt. Later, if someone changes the terminal size, the vmm detects the corresponding event, updates the configuration, and sends interrupt as before. As a result, the console device driver, in the guest, updates the console size. Signed-off-by: A K M Fazla Mehrab <fazla.mehrab.akm@intel.com>
This commit is contained in:
parent
d9a355f85a
commit
df5058ec0a
35
Cargo.lock
generated
35
Cargo.lock
generated
@ -16,6 +16,11 @@ dependencies = [
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "arch"
|
||||
version = "0.1.0"
|
||||
@ -723,12 +728,12 @@ name = "rand_core"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.4.0"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -755,7 +760,7 @@ dependencies = [
|
||||
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -890,6 +895,24 @@ dependencies = [
|
||||
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arc-swap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "0.6.10"
|
||||
@ -1150,6 +1173,7 @@ dependencies = [
|
||||
"net_util 0.1.0",
|
||||
"pci 0.1.0",
|
||||
"qcow 0.1.0",
|
||||
"signal-hook 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vfio 0.0.1",
|
||||
"vm-allocator 0.1.0",
|
||||
"vm-memory 0.1.0 (git+https://github.com/rust-vmm/vm-memory)",
|
||||
@ -1206,6 +1230,7 @@ dependencies = [
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5"
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum arc-swap 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1507f9b80b3ef096751728cf3f43bb0111ec906e44f5d8587e02c10643b9a2cd"
|
||||
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
|
||||
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
|
||||
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
|
||||
@ -1279,7 +1304,7 @@ dependencies = [
|
||||
"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c"
|
||||
"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853"
|
||||
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
|
||||
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca"
|
||||
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||
@ -1301,6 +1326,8 @@ dependencies = [
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113"
|
||||
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
|
||||
"checksum signal-hook 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4f61c4d59f3aaa9f61bba6450a9b80ba48362fd7d651689e7a10c453b1f6dc68"
|
||||
"checksum signal-hook-registry 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1797d48f38f91643908bb14e35e79928f9f4b3cefb2420a564dde0991b4358dc"
|
||||
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
|
||||
"checksum ssh2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dee822d619a700f98c4de3b5931f272ecc7cf2e924ceb2df47b61df4ae033a0c"
|
||||
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
||||
|
@ -19,7 +19,8 @@ use super::{
|
||||
VirtioInterruptType, VIRTIO_F_VERSION_1,
|
||||
};
|
||||
use crate::VirtioInterrupt;
|
||||
use vm_memory::{Bytes, GuestMemoryMmap};
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use vm_memory::{ByteValued, Bytes, GuestMemoryMmap};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
const QUEUE_SIZE: u16 = 256;
|
||||
@ -33,6 +34,23 @@ const OUTPUT_QUEUE_EVENT: DeviceEventT = 1;
|
||||
const INPUT_EVENT: DeviceEventT = 2;
|
||||
// The device has been dropped.
|
||||
const KILL_EVENT: DeviceEventT = 3;
|
||||
// Console configuration change event is triggered.
|
||||
const CONFIG_EVENT: DeviceEventT = 4;
|
||||
|
||||
//Console size feature bit
|
||||
const VIRTIO_CONSOLE_F_SIZE: u64 = 0;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct VirtioConsoleConfig {
|
||||
cols: u16,
|
||||
rows: u16,
|
||||
max_nr_ports: u32,
|
||||
emerg_wr: u32,
|
||||
}
|
||||
|
||||
// Safe because it only has data and has no implicit padding.
|
||||
unsafe impl ByteValued for VirtioConsoleConfig {}
|
||||
|
||||
struct ConsoleEpollHandler {
|
||||
queues: Vec<Queue>,
|
||||
@ -43,6 +61,7 @@ struct ConsoleEpollHandler {
|
||||
input_queue_evt: EventFd,
|
||||
output_queue_evt: EventFd,
|
||||
input_evt: EventFd,
|
||||
config_evt: EventFd,
|
||||
kill_evt: EventFd,
|
||||
}
|
||||
|
||||
@ -158,6 +177,14 @@ impl ConsoleEpollHandler {
|
||||
epoll::Event::new(epoll::Events::EPOLLIN, u64::from(INPUT_EVENT)),
|
||||
)
|
||||
.map_err(DeviceError::EpollCtl)?;
|
||||
epoll::ctl(
|
||||
epoll_fd,
|
||||
epoll::ControlOptions::EPOLL_CTL_ADD,
|
||||
self.config_evt.as_raw_fd(),
|
||||
epoll::Event::new(epoll::Events::EPOLLIN, u64::from(CONFIG_EVENT)),
|
||||
)
|
||||
.map_err(DeviceError::EpollCtl)?;
|
||||
|
||||
epoll::ctl(
|
||||
epoll_fd,
|
||||
epoll::ControlOptions::EPOLL_CTL_ADD,
|
||||
@ -216,6 +243,17 @@ impl ConsoleEpollHandler {
|
||||
}
|
||||
}
|
||||
}
|
||||
CONFIG_EVENT => {
|
||||
if let Err(e) = self.config_evt.read() {
|
||||
error!("Failed to get config event: {:?}", e);
|
||||
break 'epoll;
|
||||
} else if let Err(e) =
|
||||
(self.interrupt_cb)(&VirtioInterruptType::Config, None)
|
||||
{
|
||||
error!("Failed to signal console driver: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
KILL_EVENT => {
|
||||
debug!("KILL_EVENT received, stopping epoll loop");
|
||||
break 'epoll;
|
||||
@ -231,19 +269,13 @@ impl ConsoleEpollHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/// Virtio device for exposing console to the guest OS through virtio.
|
||||
pub struct Console {
|
||||
kill_evt: Option<EventFd>,
|
||||
avail_features: u64,
|
||||
acked_features: u64,
|
||||
input: Arc<ConsoleInput>,
|
||||
out: Option<Box<io::Write + Send>>,
|
||||
}
|
||||
|
||||
/// Input device.
|
||||
pub struct ConsoleInput {
|
||||
input_evt: EventFd,
|
||||
config_evt: EventFd,
|
||||
in_buffer: Arc<Mutex<VecDeque<u8>>>,
|
||||
config: Arc<Mutex<VirtioConsoleConfig>>,
|
||||
acked_features: AtomicU64,
|
||||
}
|
||||
|
||||
impl ConsoleInput {
|
||||
@ -252,18 +284,64 @@ impl ConsoleInput {
|
||||
in_buffer.extend(input);
|
||||
let _ = self.input_evt.write(1);
|
||||
}
|
||||
|
||||
pub fn update_console_size(&self, cols: u16, rows: u16) {
|
||||
if self
|
||||
.acked_features
|
||||
.fetch_and(1u64 << VIRTIO_CONSOLE_F_SIZE, Ordering::SeqCst)
|
||||
!= 0
|
||||
{
|
||||
self.config.lock().unwrap().update_console_size(cols, rows);
|
||||
//Send the interrupt to the driver
|
||||
let _ = self.config_evt.write(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtioConsoleConfig {
|
||||
pub fn new(cols: u16, rows: u16) -> Self {
|
||||
VirtioConsoleConfig {
|
||||
cols,
|
||||
rows,
|
||||
max_nr_ports: 1u32,
|
||||
emerg_wr: 0u32,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_console_size(&mut self, cols: u16, rows: u16) {
|
||||
self.cols = cols;
|
||||
self.rows = rows;
|
||||
}
|
||||
}
|
||||
|
||||
/// Virtio device for exposing console to the guest OS through virtio.
|
||||
pub struct Console {
|
||||
kill_evt: Option<EventFd>,
|
||||
avail_features: u64,
|
||||
acked_features: u64,
|
||||
config: Arc<Mutex<VirtioConsoleConfig>>,
|
||||
input: Arc<ConsoleInput>,
|
||||
out: Option<Box<io::Write + Send>>,
|
||||
}
|
||||
|
||||
impl Console {
|
||||
/// Create a new virtio console device that gets random data from /dev/urandom.
|
||||
pub fn new(out: Option<Box<io::Write + Send>>) -> io::Result<(Console, Arc<ConsoleInput>)> {
|
||||
let avail_features = 1u64 << VIRTIO_F_VERSION_1;
|
||||
pub fn new(
|
||||
out: Option<Box<io::Write + Send>>,
|
||||
cols: u16,
|
||||
rows: u16,
|
||||
) -> io::Result<(Console, Arc<ConsoleInput>)> {
|
||||
let avail_features = 1u64 << VIRTIO_F_VERSION_1 | 1u64 << VIRTIO_CONSOLE_F_SIZE;
|
||||
|
||||
let input_evt = EventFd::new(EFD_NONBLOCK).unwrap();
|
||||
|
||||
let config_evt = EventFd::new(EFD_NONBLOCK).unwrap();
|
||||
let console_config = Arc::new(Mutex::new(VirtioConsoleConfig::new(cols, rows)));
|
||||
let console_input = Arc::new(ConsoleInput {
|
||||
input_evt,
|
||||
config_evt,
|
||||
in_buffer: Arc::new(Mutex::new(VecDeque::new())),
|
||||
config: console_config.clone(),
|
||||
acked_features: AtomicU64::new(0),
|
||||
});
|
||||
|
||||
Ok((
|
||||
@ -271,6 +349,7 @@ impl Console {
|
||||
kill_evt: None,
|
||||
avail_features,
|
||||
acked_features: 0u64,
|
||||
config: console_config,
|
||||
input: console_input.clone(),
|
||||
out,
|
||||
},
|
||||
@ -331,12 +410,24 @@ impl VirtioDevice for Console {
|
||||
self.acked_features |= v;
|
||||
}
|
||||
|
||||
fn read_config(&self, _offset: u64, _data: &mut [u8]) {
|
||||
warn!("Device specific configuration is not defined yet");
|
||||
fn read_config(&self, offset: u64, mut data: &mut [u8]) {
|
||||
let config = self.config.lock().unwrap();
|
||||
let config_slice = config.as_slice();
|
||||
let config_len = config_slice.len() as u64;
|
||||
if offset >= config_len {
|
||||
error!("Failed to read config space");
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(end) = offset.checked_add(data.len() as u64) {
|
||||
// This write can't fail, offset and end are checked against config_len.
|
||||
data.write_all(&config_slice[offset as usize..cmp::min(end, config_len) as usize])
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn write_config(&mut self, _offset: u64, _data: &[u8]) {
|
||||
warn!("Device specific configuration is not defined yet");
|
||||
warn!("No device specific configration requires write");
|
||||
}
|
||||
|
||||
fn activate(
|
||||
@ -365,6 +456,16 @@ impl VirtioDevice for Console {
|
||||
};
|
||||
self.kill_evt = Some(self_kill_evt);
|
||||
|
||||
self.input
|
||||
.acked_features
|
||||
.store(self.acked_features, Ordering::Relaxed);
|
||||
|
||||
if (self.acked_features & (1u64 << VIRTIO_CONSOLE_F_SIZE)) != 0 {
|
||||
if let Err(e) = (interrupt_cb)(&VirtioInterruptType::Config, None) {
|
||||
error!("Failed to signal console driver: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(out) = self.out.take() {
|
||||
let mut handler = ConsoleEpollHandler {
|
||||
queues,
|
||||
@ -375,6 +476,7 @@ impl VirtioDevice for Console {
|
||||
input_queue_evt: queue_evts.remove(0),
|
||||
output_queue_evt: queue_evts.remove(0),
|
||||
input_evt: self.input.input_evt.try_clone().unwrap(),
|
||||
config_evt: self.input.config_evt.try_clone().unwrap(),
|
||||
kill_evt,
|
||||
};
|
||||
|
||||
|
@ -143,4 +143,5 @@ pub enum Error {
|
||||
EpollCreateFd(io::Error),
|
||||
EpollCtl(io::Error),
|
||||
EpollWait(io::Error),
|
||||
FailedSignalingDriver(io::Error),
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ vfio = { path = "../vfio" }
|
||||
vm-virtio = { path = "../vm-virtio" }
|
||||
vm-allocator = { path = "../vm-allocator" }
|
||||
vmm-sys-util = { git = "https://github.com/rust-vmm/vmm-sys-util" }
|
||||
signal-hook = "0.1.10"
|
||||
|
||||
[dependencies.linux-loader]
|
||||
git = "https://github.com/rust-vmm/linux-loader"
|
||||
|
@ -16,6 +16,7 @@ extern crate kvm_ioctls;
|
||||
extern crate libc;
|
||||
extern crate linux_loader;
|
||||
extern crate net_util;
|
||||
extern crate signal_hook;
|
||||
extern crate vfio;
|
||||
extern crate vm_allocator;
|
||||
extern crate vm_memory;
|
||||
@ -31,13 +32,14 @@ use kvm_bindings::{
|
||||
};
|
||||
use kvm_ioctls::*;
|
||||
use libc::O_TMPFILE;
|
||||
use libc::{c_void, siginfo_t, EFD_NONBLOCK};
|
||||
use libc::{c_void, siginfo_t, EFD_NONBLOCK, TIOCGWINSZ};
|
||||
use linux_loader::loader::KernelLoader;
|
||||
use net_util::Tap;
|
||||
use pci::{
|
||||
InterruptDelivery, InterruptParameters, PciConfigIo, PciDevice, PciInterruptPin, PciRoot,
|
||||
};
|
||||
use qcow::{self, ImageType, QcowFile};
|
||||
use signal_hook::{iterator::Signals, SIGWINCH};
|
||||
use std::ffi::CString;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{self, sink, stdout};
|
||||
@ -491,6 +493,23 @@ impl UserIoapicIrq {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_win_size() -> (u16, u16) {
|
||||
#[repr(C)]
|
||||
struct WS {
|
||||
rows: u16,
|
||||
cols: u16,
|
||||
};
|
||||
let ws: WS = WS {
|
||||
rows: 0u16,
|
||||
cols: 0u16,
|
||||
};
|
||||
unsafe {
|
||||
libc::ioctl(0, TIOCGWINSZ, &ws);
|
||||
}
|
||||
|
||||
(ws.cols, ws.rows)
|
||||
}
|
||||
|
||||
impl devices::Interrupt for UserIoapicIrq {
|
||||
fn deliver(&self) -> result::Result<(), io::Error> {
|
||||
self.ioapic
|
||||
@ -512,7 +531,7 @@ struct DeviceManager {
|
||||
|
||||
// Serial port on 0x3f8
|
||||
serial: Option<Arc<Mutex<devices::legacy::Serial>>>,
|
||||
console: Option<Arc<vm_virtio::ConsoleInput>>,
|
||||
console_input: Option<Arc<vm_virtio::ConsoleInput>>,
|
||||
|
||||
// i8042 device for exit
|
||||
i8042: Arc<Mutex<devices::legacy::I8042Device>>,
|
||||
@ -604,8 +623,10 @@ impl DeviceManager {
|
||||
ConsoleOutputMode::Null => Some(Box::new(sink())),
|
||||
ConsoleOutputMode::Off => None,
|
||||
};
|
||||
let (col, row) = get_win_size();
|
||||
let console = if console_writer.is_some() {
|
||||
let (virtio_console_device, console) = vm_virtio::Console::new(console_writer)
|
||||
let (virtio_console_device, console_input) =
|
||||
vm_virtio::Console::new(console_writer, col, row)
|
||||
.map_err(DeviceManagerError::CreateVirtioConsole)?;
|
||||
DeviceManager::add_virtio_pci_device(
|
||||
Box::new(virtio_console_device),
|
||||
@ -616,7 +637,7 @@ impl DeviceManager {
|
||||
&mut buses,
|
||||
&interrupt_info,
|
||||
)?;
|
||||
Some(console)
|
||||
Some(console_input)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -638,7 +659,7 @@ impl DeviceManager {
|
||||
io_bus,
|
||||
mmio_bus,
|
||||
serial,
|
||||
console,
|
||||
console_input: console,
|
||||
i8042,
|
||||
exit_evt,
|
||||
ioapic,
|
||||
@ -1447,7 +1468,7 @@ impl<'a> Vm<'a> {
|
||||
let mut events = vec![epoll::Event::new(epoll::Events::empty(), 0); EPOLL_EVENTS_LEN];
|
||||
let epoll_fd = self.epoll.as_raw_fd();
|
||||
|
||||
if (self.devices.serial.is_some() || self.devices.console.is_some()) && self.on_tty {
|
||||
if (self.devices.serial.is_some() || self.devices.console_input.is_some()) && self.on_tty {
|
||||
io::stdin()
|
||||
.lock()
|
||||
.set_raw_mode()
|
||||
@ -1503,11 +1524,11 @@ impl<'a> Vm<'a> {
|
||||
.map_err(Error::Serial)?;
|
||||
}
|
||||
|
||||
if self.devices.console.is_some()
|
||||
if self.devices.console_input.is_some()
|
||||
&& self.config.console.mode.input_enabled()
|
||||
{
|
||||
self.devices
|
||||
.console
|
||||
.console_input
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.queue_input_bytes(&out[..count]);
|
||||
@ -1530,6 +1551,15 @@ impl<'a> Vm<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn os_signal_handler(signals: Signals, console_input_clone: Arc<vm_virtio::ConsoleInput>) {
|
||||
for signal in signals.forever() {
|
||||
if signal == SIGWINCH {
|
||||
let (col, row) = get_win_size();
|
||||
console_input_clone.update_console_size(col, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&mut self, entry_addr: GuestAddress) -> Result<()> {
|
||||
self.devices.register_devices()?;
|
||||
|
||||
@ -1581,6 +1611,16 @@ impl<'a> Vm<'a> {
|
||||
// Unblock all CPU threads.
|
||||
vcpu_thread_barrier.wait();
|
||||
|
||||
if let Some(console_input) = &self.devices.console_input {
|
||||
let console_input_clone = console_input.clone();
|
||||
let signals = Signals::new(&[SIGWINCH]);
|
||||
match signals {
|
||||
Ok(sig) => {
|
||||
thread::spawn(move || Vm::os_signal_handler(sig, console_input_clone));
|
||||
}
|
||||
Err(e) => error!("Signal not found {}", e),
|
||||
}
|
||||
}
|
||||
self.control_loop()?;
|
||||
|
||||
Ok(())
|
||||
|
Loading…
x
Reference in New Issue
Block a user