mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 11:05:46 +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::thread_helper::spawn_virtio_thread;
|
||||||
use crate::GuestMemoryMmap;
|
use crate::GuestMemoryMmap;
|
||||||
use crate::VirtioInterrupt;
|
use crate::VirtioInterrupt;
|
||||||
use libc::EFD_NONBLOCK;
|
use libc::{EFD_NONBLOCK, TIOCGWINSZ};
|
||||||
use seccompiler::SeccompAction;
|
use seccompiler::SeccompAction;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
@ -46,7 +46,7 @@ const FILE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 5;
|
|||||||
//Console size feature bit
|
//Console size feature bit
|
||||||
const VIRTIO_CONSOLE_F_SIZE: u64 = 0;
|
const VIRTIO_CONSOLE_F_SIZE: u64 = 0;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
#[derive(Copy, Clone, Debug, Versionize)]
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
pub struct VirtioConsoleConfig {
|
pub struct VirtioConsoleConfig {
|
||||||
cols: u16,
|
cols: u16,
|
||||||
@ -55,6 +55,17 @@ pub struct VirtioConsoleConfig {
|
|||||||
emerg_wr: u32,
|
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.
|
// Safe because it only has data and has no implicit padding.
|
||||||
unsafe impl ByteValued for VirtioConsoleConfig {}
|
unsafe impl ByteValued for VirtioConsoleConfig {}
|
||||||
|
|
||||||
@ -287,12 +298,13 @@ pub struct ConsoleResizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConsoleResizer {
|
impl ConsoleResizer {
|
||||||
pub fn update_console_size(&self, cols: u16, rows: u16) {
|
pub fn update_console_size(&self) {
|
||||||
if self
|
if self
|
||||||
.acked_features
|
.acked_features
|
||||||
.fetch_and(1u64 << VIRTIO_CONSOLE_F_SIZE, Ordering::AcqRel)
|
.fetch_and(1u64 << VIRTIO_CONSOLE_F_SIZE, Ordering::AcqRel)
|
||||||
!= 0
|
!= 0
|
||||||
{
|
{
|
||||||
|
let (cols, rows) = get_win_size();
|
||||||
self.config.lock().unwrap().update_console_size(cols, rows);
|
self.config.lock().unwrap().update_console_size(cols, rows);
|
||||||
//Send the interrupt to the driver
|
//Send the interrupt to the driver
|
||||||
let _ = self.config_evt.write(1);
|
let _ = self.config_evt.write(1);
|
||||||
@ -301,15 +313,6 @@ impl ConsoleResizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl VirtioConsoleConfig {
|
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) {
|
pub fn update_console_size(&mut self, cols: u16, rows: u16) {
|
||||||
self.cols = cols;
|
self.cols = cols;
|
||||||
self.rows = rows;
|
self.rows = rows;
|
||||||
@ -336,6 +339,24 @@ pub struct ConsoleState {
|
|||||||
in_buffer: Vec<u8>,
|
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 VersionMapped for ConsoleState {}
|
||||||
|
|
||||||
impl Console {
|
impl Console {
|
||||||
@ -343,8 +364,6 @@ impl Console {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
id: String,
|
id: String,
|
||||||
endpoint: Endpoint,
|
endpoint: Endpoint,
|
||||||
cols: u16,
|
|
||||||
rows: u16,
|
|
||||||
iommu: bool,
|
iommu: bool,
|
||||||
seccomp_action: SeccompAction,
|
seccomp_action: SeccompAction,
|
||||||
exit_evt: EventFd,
|
exit_evt: EventFd,
|
||||||
@ -356,13 +375,15 @@ impl Console {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let config_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_config = Arc::new(Mutex::new(VirtioConsoleConfig::default()));
|
||||||
let resizer = Arc::new(ConsoleResizer {
|
let resizer = Arc::new(ConsoleResizer {
|
||||||
config_evt,
|
config_evt,
|
||||||
config: console_config.clone(),
|
config: console_config.clone(),
|
||||||
acked_features: AtomicU64::new(0),
|
acked_features: AtomicU64::new(0),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
resizer.update_console_size();
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
Console {
|
Console {
|
||||||
common: VirtioCommon {
|
common: VirtioCommon {
|
||||||
|
@ -48,6 +48,7 @@ macro_rules! or {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See include/uapi/asm-generic/ioctls.h in the kernel code.
|
// See include/uapi/asm-generic/ioctls.h in the kernel code.
|
||||||
|
const TIOCGWINSZ: u64 = 0x5413;
|
||||||
const FIONBIO: u64 = 0x5421;
|
const FIONBIO: u64 = 0x5421;
|
||||||
|
|
||||||
// See include/uapi/linux/vfio.h in the kernel code.
|
// 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.
|
// See include/uapi/linux/if_tun.h in the kernel code.
|
||||||
const TUNSETOFFLOAD: u64 = 0x4004_54d0;
|
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> {
|
fn create_virtio_iommu_ioctl_seccomp_rule() -> Vec<SeccompRule> {
|
||||||
or![
|
or![
|
||||||
and![Cond::new(1, ArgLen::Dword, Eq, VFIO_IOMMU_MAP_DMA).unwrap()],
|
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>)> {
|
fn virtio_console_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
|
||||||
vec![
|
vec![
|
||||||
|
(libc::SYS_ioctl, create_virtio_console_ioctl_seccomp_rule()),
|
||||||
(libc::SYS_mprotect, vec![]),
|
(libc::SYS_mprotect, vec![]),
|
||||||
(libc::SYS_prctl, vec![]),
|
(libc::SYS_prctl, vec![]),
|
||||||
(libc::SYS_sched_getaffinity, vec![]),
|
(libc::SYS_sched_getaffinity, vec![]),
|
||||||
|
@ -62,7 +62,7 @@ use hypervisor::DeviceFd;
|
|||||||
use hypervisor::IoEventAddress;
|
use hypervisor::IoEventAddress;
|
||||||
use libc::{
|
use libc::{
|
||||||
isatty, tcgetattr, tcsetattr, termios, ECHO, ICANON, ISIG, MAP_NORESERVE, MAP_PRIVATE,
|
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::VfioPciDevice;
|
||||||
use pci::{
|
use pci::{
|
||||||
@ -450,24 +450,6 @@ type VirtioDeviceArc = Arc<Mutex<dyn virtio_devices::VirtioDevice>>;
|
|||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
const DEVICE_MANAGER_ACPI_SIZE: usize = 0x10;
|
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 TIOCSPTLCK: libc::c_int = 0x4004_5431;
|
||||||
const TIOCGTPEER: libc::c_int = 0x5441;
|
const TIOCGTPEER: libc::c_int = 0x5441;
|
||||||
|
|
||||||
@ -543,9 +525,9 @@ impl Console {
|
|||||||
Ok(())
|
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() {
|
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::Null => Endpoint::Null,
|
||||||
ConsoleOutputMode::Off => return Ok(None),
|
ConsoleOutputMode::Off => return Ok(None),
|
||||||
};
|
};
|
||||||
let (col, row) = get_win_size();
|
|
||||||
let id = String::from(CONSOLE_DEVICE_NAME);
|
let id = String::from(CONSOLE_DEVICE_NAME);
|
||||||
|
|
||||||
let (virtio_console_device, console_resizer) = virtio_devices::Console::new(
|
let (virtio_console_device, console_resizer) = virtio_devices::Console::new(
|
||||||
id.clone(),
|
id.clone(),
|
||||||
endpoint,
|
endpoint,
|
||||||
col,
|
|
||||||
row,
|
|
||||||
self.force_iommu | console_config.iommu,
|
self.force_iommu | console_config.iommu,
|
||||||
self.seccomp_action.clone(),
|
self.seccomp_action.clone(),
|
||||||
self.exit_evt
|
self.exit_evt
|
||||||
|
@ -17,9 +17,7 @@ use crate::config::{
|
|||||||
ConsoleOutputMode, DeviceConfig, DiskConfig, FsConfig, HotplugMethod, NetConfig, PmemConfig,
|
ConsoleOutputMode, DeviceConfig, DiskConfig, FsConfig, HotplugMethod, NetConfig, PmemConfig,
|
||||||
UserDeviceConfig, ValidationError, VmConfig, VsockConfig,
|
UserDeviceConfig, ValidationError, VmConfig, VsockConfig,
|
||||||
};
|
};
|
||||||
use crate::device_manager::{
|
use crate::device_manager::{self, Console, DeviceManager, DeviceManagerError, PtyPair};
|
||||||
self, get_win_size, Console, DeviceManager, DeviceManagerError, PtyPair,
|
|
||||||
};
|
|
||||||
use crate::device_tree::DeviceTree;
|
use crate::device_tree::DeviceTree;
|
||||||
use crate::memory_manager::{Error as MemoryManagerError, MemoryManager};
|
use crate::memory_manager::{Error as MemoryManagerError, MemoryManager};
|
||||||
use crate::migration::{get_vm_snapshot, url_to_path, VM_SNAPSHOT_FILE};
|
use crate::migration::{get_vm_snapshot, url_to_path, VM_SNAPSHOT_FILE};
|
||||||
@ -1602,8 +1600,7 @@ impl Vm {
|
|||||||
for signal in signals.forever() {
|
for signal in signals.forever() {
|
||||||
match signal {
|
match signal {
|
||||||
SIGWINCH => {
|
SIGWINCH => {
|
||||||
let (col, row) = get_win_size();
|
console_input_clone.update_console_size();
|
||||||
console_input_clone.update_console_size(col, row);
|
|
||||||
}
|
}
|
||||||
SIGTERM | SIGINT => {
|
SIGTERM | SIGINT => {
|
||||||
if on_tty {
|
if on_tty {
|
||||||
|
Loading…
Reference in New Issue
Block a user