mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-21 20:15:21 +00:00
virtio-devices: determine tty size in console
This prepares us to be able to handle console resizes in the console device's epoll loop, which we'll have to do if the output is a pty, since we won't get SIGWINCH from it. Signed-off-by: Alyssa Ross <hi@alyssa.is>
This commit is contained in:
parent
68e6a14deb
commit
28382a1491
@ -11,7 +11,7 @@ use crate::seccomp_filters::Thread;
|
||||
use crate::thread_helper::spawn_virtio_thread;
|
||||
use crate::GuestMemoryMmap;
|
||||
use crate::VirtioInterrupt;
|
||||
use libc::EFD_NONBLOCK;
|
||||
use libc::{EFD_NONBLOCK, TIOCGWINSZ};
|
||||
use seccompiler::SeccompAction;
|
||||
use std::cmp;
|
||||
use std::collections::VecDeque;
|
||||
@ -46,7 +46,7 @@ const FILE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 5;
|
||||
//Console size feature bit
|
||||
const VIRTIO_CONSOLE_F_SIZE: u64 = 0;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||
#[derive(Copy, Clone, Debug, Versionize)]
|
||||
#[repr(C, packed)]
|
||||
pub struct VirtioConsoleConfig {
|
||||
cols: u16,
|
||||
@ -55,6 +55,17 @@ pub struct VirtioConsoleConfig {
|
||||
emerg_wr: u32,
|
||||
}
|
||||
|
||||
impl Default for VirtioConsoleConfig {
|
||||
fn default() -> Self {
|
||||
VirtioConsoleConfig {
|
||||
cols: 0,
|
||||
rows: 0,
|
||||
max_nr_ports: 1,
|
||||
emerg_wr: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Safe because it only has data and has no implicit padding.
|
||||
unsafe impl ByteValued for VirtioConsoleConfig {}
|
||||
|
||||
@ -287,12 +298,13 @@ pub struct ConsoleResizer {
|
||||
}
|
||||
|
||||
impl ConsoleResizer {
|
||||
pub fn update_console_size(&self, cols: u16, rows: u16) {
|
||||
pub fn update_console_size(&self) {
|
||||
if self
|
||||
.acked_features
|
||||
.fetch_and(1u64 << VIRTIO_CONSOLE_F_SIZE, Ordering::AcqRel)
|
||||
!= 0
|
||||
{
|
||||
let (cols, rows) = get_win_size();
|
||||
self.config.lock().unwrap().update_console_size(cols, rows);
|
||||
//Send the interrupt to the driver
|
||||
let _ = self.config_evt.write(1);
|
||||
@ -301,15 +313,6 @@ impl ConsoleResizer {
|
||||
}
|
||||
|
||||
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;
|
||||
@ -336,6 +339,24 @@ pub struct ConsoleState {
|
||||
in_buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
fn get_win_size() -> (u16, u16) {
|
||||
#[repr(C)]
|
||||
#[derive(Default)]
|
||||
struct WindowSize {
|
||||
rows: u16,
|
||||
cols: u16,
|
||||
xpixel: u16,
|
||||
ypixel: u16,
|
||||
}
|
||||
let ws: WindowSize = WindowSize::default();
|
||||
|
||||
unsafe {
|
||||
libc::ioctl(0, TIOCGWINSZ, &ws);
|
||||
}
|
||||
|
||||
(ws.cols, ws.rows)
|
||||
}
|
||||
|
||||
impl VersionMapped for ConsoleState {}
|
||||
|
||||
impl Console {
|
||||
@ -343,8 +364,6 @@ impl Console {
|
||||
pub fn new(
|
||||
id: String,
|
||||
endpoint: Endpoint,
|
||||
cols: u16,
|
||||
rows: u16,
|
||||
iommu: bool,
|
||||
seccomp_action: SeccompAction,
|
||||
exit_evt: EventFd,
|
||||
@ -356,13 +375,15 @@ impl Console {
|
||||
}
|
||||
|
||||
let config_evt = EventFd::new(EFD_NONBLOCK).unwrap();
|
||||
let console_config = Arc::new(Mutex::new(VirtioConsoleConfig::new(cols, rows)));
|
||||
let console_config = Arc::new(Mutex::new(VirtioConsoleConfig::default()));
|
||||
let resizer = Arc::new(ConsoleResizer {
|
||||
config_evt,
|
||||
config: console_config.clone(),
|
||||
acked_features: AtomicU64::new(0),
|
||||
});
|
||||
|
||||
resizer.update_console_size();
|
||||
|
||||
Ok((
|
||||
Console {
|
||||
common: VirtioCommon {
|
||||
|
@ -48,6 +48,7 @@ macro_rules! or {
|
||||
}
|
||||
|
||||
// See include/uapi/asm-generic/ioctls.h in the kernel code.
|
||||
const TIOCGWINSZ: u64 = 0x5413;
|
||||
const FIONBIO: u64 = 0x5421;
|
||||
|
||||
// See include/uapi/linux/vfio.h in the kernel code.
|
||||
@ -57,6 +58,10 @@ const VFIO_IOMMU_UNMAP_DMA: u64 = 0x3b72;
|
||||
// See include/uapi/linux/if_tun.h in the kernel code.
|
||||
const TUNSETOFFLOAD: u64 = 0x4004_54d0;
|
||||
|
||||
fn create_virtio_console_ioctl_seccomp_rule() -> Vec<SeccompRule> {
|
||||
or![and![Cond::new(1, ArgLen::Dword, Eq, TIOCGWINSZ).unwrap()]]
|
||||
}
|
||||
|
||||
fn create_virtio_iommu_ioctl_seccomp_rule() -> Vec<SeccompRule> {
|
||||
or![
|
||||
and![Cond::new(1, ArgLen::Dword, Eq, VFIO_IOMMU_MAP_DMA).unwrap()],
|
||||
@ -99,6 +104,7 @@ fn virtio_block_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
|
||||
|
||||
fn virtio_console_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
|
||||
vec![
|
||||
(libc::SYS_ioctl, create_virtio_console_ioctl_seccomp_rule()),
|
||||
(libc::SYS_mprotect, vec![]),
|
||||
(libc::SYS_prctl, vec![]),
|
||||
(libc::SYS_sched_getaffinity, vec![]),
|
||||
|
@ -62,7 +62,7 @@ use hypervisor::DeviceFd;
|
||||
use hypervisor::IoEventAddress;
|
||||
use libc::{
|
||||
isatty, tcgetattr, tcsetattr, termios, ECHO, ICANON, ISIG, MAP_NORESERVE, MAP_PRIVATE,
|
||||
MAP_SHARED, O_TMPFILE, PROT_READ, PROT_WRITE, TCSANOW, TIOCGWINSZ,
|
||||
MAP_SHARED, O_TMPFILE, PROT_READ, PROT_WRITE, TCSANOW,
|
||||
};
|
||||
use pci::VfioPciDevice;
|
||||
use pci::{
|
||||
@ -450,24 +450,6 @@ type VirtioDeviceArc = Arc<Mutex<dyn virtio_devices::VirtioDevice>>;
|
||||
#[cfg(feature = "acpi")]
|
||||
const DEVICE_MANAGER_ACPI_SIZE: usize = 0x10;
|
||||
|
||||
pub fn get_win_size() -> (u16, u16) {
|
||||
#[repr(C)]
|
||||
#[derive(Default)]
|
||||
struct WindowSize {
|
||||
rows: u16,
|
||||
cols: u16,
|
||||
xpixel: u16,
|
||||
ypixel: u16,
|
||||
}
|
||||
let ws: WindowSize = WindowSize::default();
|
||||
|
||||
unsafe {
|
||||
libc::ioctl(0, TIOCGWINSZ, &ws);
|
||||
}
|
||||
|
||||
(ws.cols, ws.rows)
|
||||
}
|
||||
|
||||
const TIOCSPTLCK: libc::c_int = 0x4004_5431;
|
||||
const TIOCGTPEER: libc::c_int = 0x5441;
|
||||
|
||||
@ -543,9 +525,9 @@ impl Console {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_console_size(&self, cols: u16, rows: u16) {
|
||||
pub fn update_console_size(&self) {
|
||||
if let Some(resizer) = self.console_resizer.as_ref() {
|
||||
resizer.update_console_size(cols, rows)
|
||||
resizer.update_console_size()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1716,14 +1698,11 @@ impl DeviceManager {
|
||||
ConsoleOutputMode::Null => Endpoint::Null,
|
||||
ConsoleOutputMode::Off => return Ok(None),
|
||||
};
|
||||
let (col, row) = get_win_size();
|
||||
let id = String::from(CONSOLE_DEVICE_NAME);
|
||||
|
||||
let (virtio_console_device, console_resizer) = virtio_devices::Console::new(
|
||||
id.clone(),
|
||||
endpoint,
|
||||
col,
|
||||
row,
|
||||
self.force_iommu | console_config.iommu,
|
||||
self.seccomp_action.clone(),
|
||||
self.exit_evt
|
||||
|
@ -17,9 +17,7 @@ use crate::config::{
|
||||
ConsoleOutputMode, DeviceConfig, DiskConfig, FsConfig, HotplugMethod, NetConfig, PmemConfig,
|
||||
UserDeviceConfig, ValidationError, VmConfig, VsockConfig,
|
||||
};
|
||||
use crate::device_manager::{
|
||||
self, get_win_size, Console, DeviceManager, DeviceManagerError, PtyPair,
|
||||
};
|
||||
use crate::device_manager::{self, Console, DeviceManager, DeviceManagerError, PtyPair};
|
||||
use crate::device_tree::DeviceTree;
|
||||
use crate::memory_manager::{Error as MemoryManagerError, MemoryManager};
|
||||
use crate::migration::{get_vm_snapshot, url_to_path, VM_SNAPSHOT_FILE};
|
||||
@ -1602,8 +1600,7 @@ impl Vm {
|
||||
for signal in signals.forever() {
|
||||
match signal {
|
||||
SIGWINCH => {
|
||||
let (col, row) = get_win_size();
|
||||
console_input_clone.update_console_size(col, row);
|
||||
console_input_clone.update_console_size();
|
||||
}
|
||||
SIGTERM | SIGINT => {
|
||||
if on_tty {
|
||||
|
Loading…
x
Reference in New Issue
Block a user