mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: Hide underlying console setup from VM
Refactor the underlying console details into the DeviceManager and abstract away. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
committed by
Sebastien Boeuf
parent
d089ee4e25
commit
d2db34edf2
@@ -209,13 +209,51 @@ pub fn get_win_size() -> (u16, u16) {
|
|||||||
(ws.cols, ws.rows)
|
(ws.cols, ws.rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Console {
|
||||||
|
// Serial port on 0x3f8
|
||||||
|
serial: Option<Arc<Mutex<devices::legacy::Serial>>>,
|
||||||
|
console_input: Option<Arc<vm_virtio::ConsoleInput>>,
|
||||||
|
input_enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
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)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.console_input.is_some() {
|
||||||
|
self.console_input.as_ref().unwrap().queue_input_bytes(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_console_size(&self, cols: u16, rows: u16) {
|
||||||
|
if self.console_input.is_some() {
|
||||||
|
self.console_input
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.update_console_size(cols, rows)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input_enabled(&self) -> bool {
|
||||||
|
self.input_enabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct DeviceManager {
|
pub struct DeviceManager {
|
||||||
io_bus: devices::Bus,
|
io_bus: devices::Bus,
|
||||||
mmio_bus: devices::Bus,
|
mmio_bus: devices::Bus,
|
||||||
|
|
||||||
// Serial port on 0x3f8
|
// Console abstraction
|
||||||
pub serial: Option<Arc<Mutex<devices::legacy::Serial>>>,
|
console: Arc<Console>,
|
||||||
pub console_input: Option<Arc<vm_virtio::ConsoleInput>>,
|
|
||||||
|
|
||||||
// i8042 device for i8042 reset
|
// i8042 device for i8042 reset
|
||||||
i8042: Arc<Mutex<devices::legacy::I8042Device>>,
|
i8042: Arc<Mutex<devices::legacy::I8042Device>>,
|
||||||
@@ -321,7 +359,7 @@ impl DeviceManager {
|
|||||||
ConsoleOutputMode::Off => None,
|
ConsoleOutputMode::Off => None,
|
||||||
};
|
};
|
||||||
let (col, row) = get_win_size();
|
let (col, row) = get_win_size();
|
||||||
let console = if console_writer.is_some() {
|
let console_input = if console_writer.is_some() {
|
||||||
let (virtio_console_device, console_input) =
|
let (virtio_console_device, console_input) =
|
||||||
vm_virtio::Console::new(console_writer, col, row)
|
vm_virtio::Console::new(console_writer, col, row)
|
||||||
.map_err(DeviceManagerError::CreateVirtioConsole)?;
|
.map_err(DeviceManagerError::CreateVirtioConsole)?;
|
||||||
@@ -339,6 +377,13 @@ impl DeviceManager {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let console = Arc::new(Console {
|
||||||
|
serial,
|
||||||
|
console_input,
|
||||||
|
input_enabled: vm_info.vm_cfg.serial.mode.input_enabled()
|
||||||
|
|| vm_info.vm_cfg.console.mode.input_enabled(),
|
||||||
|
});
|
||||||
|
|
||||||
let mut mmap_regions = Vec::new();
|
let mut mmap_regions = Vec::new();
|
||||||
|
|
||||||
DeviceManager::add_virtio_devices(
|
DeviceManager::add_virtio_devices(
|
||||||
@@ -358,8 +403,7 @@ impl DeviceManager {
|
|||||||
Ok(DeviceManager {
|
Ok(DeviceManager {
|
||||||
io_bus,
|
io_bus,
|
||||||
mmio_bus,
|
mmio_bus,
|
||||||
serial,
|
console,
|
||||||
console_input: console,
|
|
||||||
i8042,
|
i8042,
|
||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
acpi_device,
|
acpi_device,
|
||||||
@@ -906,10 +950,10 @@ impl DeviceManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_devices(&mut self) -> DeviceManagerResult<()> {
|
pub fn register_devices(&mut self) -> DeviceManagerResult<()> {
|
||||||
if self.serial.is_some() {
|
if self.console.serial.is_some() {
|
||||||
// Insert serial device
|
// Insert serial device
|
||||||
self.io_bus
|
self.io_bus
|
||||||
.insert(self.serial.as_ref().unwrap().clone(), 0x3f8, 0x8)
|
.insert(self.console.serial.as_ref().unwrap().clone(), 0x3f8, 0x8)
|
||||||
.map_err(DeviceManagerError::BusError)?;
|
.map_err(DeviceManagerError::BusError)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -949,6 +993,10 @@ impl DeviceManager {
|
|||||||
pub fn ioapic(&self) -> &Option<Arc<Mutex<ioapic::Ioapic>>> {
|
pub fn ioapic(&self) -> &Option<Arc<Mutex<ioapic::Ioapic>>> {
|
||||||
&self.ioapic
|
&self.ioapic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn console(&self) -> &Arc<Console> {
|
||||||
|
&self.console
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for DeviceManager {
|
impl Drop for DeviceManager {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ extern crate vm_virtio;
|
|||||||
extern crate vmm_sys_util;
|
extern crate vmm_sys_util;
|
||||||
|
|
||||||
use crate::config::{ConsoleOutputMode, VmConfig};
|
use crate::config::{ConsoleOutputMode, VmConfig};
|
||||||
use crate::device_manager::{get_win_size, DeviceManager, DeviceManagerError};
|
use crate::device_manager::{get_win_size, Console, DeviceManager, DeviceManagerError};
|
||||||
use arch::RegionType;
|
use arch::RegionType;
|
||||||
use devices::ioapic;
|
use devices::ioapic;
|
||||||
use kvm_bindings::{
|
use kvm_bindings::{
|
||||||
@@ -172,10 +172,7 @@ pub enum Error {
|
|||||||
/// Cannot create epoll context.
|
/// Cannot create epoll context.
|
||||||
EpollError(io::Error),
|
EpollError(io::Error),
|
||||||
|
|
||||||
/// Write to the serial console failed.
|
/// Write to the console failed.
|
||||||
Serial(vmm_sys_util::errno::Error),
|
|
||||||
|
|
||||||
/// Write to the virtio console failed.
|
|
||||||
Console(vmm_sys_util::errno::Error),
|
Console(vmm_sys_util::errno::Error),
|
||||||
|
|
||||||
/// Cannot setup terminal in raw mode.
|
/// Cannot setup terminal in raw mode.
|
||||||
@@ -827,7 +824,7 @@ impl<'a> Vm<'a> {
|
|||||||
let mut events = vec![epoll::Event::new(epoll::Events::empty(), 0); EPOLL_EVENTS_LEN];
|
let mut events = vec![epoll::Event::new(epoll::Events::empty(), 0); EPOLL_EVENTS_LEN];
|
||||||
let epoll_fd = self.epoll.as_raw_fd();
|
let epoll_fd = self.epoll.as_raw_fd();
|
||||||
|
|
||||||
if (self.devices.serial.is_some() || self.devices.console_input.is_some()) && self.on_tty {
|
if self.devices.console().input_enabled() && self.on_tty {
|
||||||
io::stdin()
|
io::stdin()
|
||||||
.lock()
|
.lock()
|
||||||
.set_raw_mode()
|
.set_raw_mode()
|
||||||
@@ -878,29 +875,13 @@ impl<'a> Vm<'a> {
|
|||||||
let count = io::stdin()
|
let count = io::stdin()
|
||||||
.lock()
|
.lock()
|
||||||
.read_raw(&mut out)
|
.read_raw(&mut out)
|
||||||
.map_err(Error::Serial)?;
|
.map_err(Error::Console)?;
|
||||||
|
|
||||||
if self.devices.serial.is_some()
|
if self.devices.console().input_enabled() {
|
||||||
&& self.config.serial.mode.input_enabled()
|
|
||||||
{
|
|
||||||
self.devices
|
self.devices
|
||||||
.serial
|
.console()
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.lock()
|
|
||||||
.expect("Failed to process stdin event due to poisoned lock")
|
|
||||||
.queue_input_bytes(&out[..count])
|
.queue_input_bytes(&out[..count])
|
||||||
.map_err(Error::Serial)?;
|
.map_err(Error::Console)?;
|
||||||
}
|
|
||||||
|
|
||||||
if self.devices.console_input.is_some()
|
|
||||||
&& self.config.console.mode.input_enabled()
|
|
||||||
{
|
|
||||||
self.devices
|
|
||||||
.console_input
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.queue_input_bytes(&out[..count]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -938,11 +919,7 @@ impl<'a> Vm<'a> {
|
|||||||
Ok(exit_behaviour)
|
Ok(exit_behaviour)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn os_signal_handler(
|
fn os_signal_handler(signals: Signals, console_input_clone: Arc<Console>, quit_signum: i32) {
|
||||||
signals: Signals,
|
|
||||||
console_input_clone: Arc<vm_virtio::ConsoleInput>,
|
|
||||||
quit_signum: i32,
|
|
||||||
) {
|
|
||||||
for signal in signals.forever() {
|
for signal in signals.forever() {
|
||||||
match signal {
|
match signal {
|
||||||
SIGWINCH => {
|
SIGWINCH => {
|
||||||
@@ -1030,8 +1007,8 @@ impl<'a> Vm<'a> {
|
|||||||
// Unblock all CPU threads.
|
// Unblock all CPU threads.
|
||||||
vcpu_thread_barrier.wait();
|
vcpu_thread_barrier.wait();
|
||||||
|
|
||||||
if let Some(console_input) = &self.devices.console_input {
|
if self.devices.console().input_enabled() {
|
||||||
let console_input_clone = console_input.clone();
|
let console = self.devices.console().clone();
|
||||||
let quit_signum = validate_signal_num(VCPU_RTSIG_OFFSET, true).unwrap();
|
let quit_signum = validate_signal_num(VCPU_RTSIG_OFFSET, true).unwrap();
|
||||||
let signals = Signals::new(&[SIGWINCH, quit_signum]);
|
let signals = Signals::new(&[SIGWINCH, quit_signum]);
|
||||||
match signals {
|
match signals {
|
||||||
@@ -1039,9 +1016,7 @@ impl<'a> Vm<'a> {
|
|||||||
self.threads.push(
|
self.threads.push(
|
||||||
thread::Builder::new()
|
thread::Builder::new()
|
||||||
.name("signal_handler".to_string())
|
.name("signal_handler".to_string())
|
||||||
.spawn(move || {
|
.spawn(move || Vm::os_signal_handler(sig, console, quit_signum))
|
||||||
Vm::os_signal_handler(sig, console_input_clone, quit_signum)
|
|
||||||
})
|
|
||||||
.map_err(Error::SignalHandlerSpawn)?,
|
.map_err(Error::SignalHandlerSpawn)?,
|
||||||
);
|
);
|
||||||
;
|
;
|
||||||
|
|||||||
Reference in New Issue
Block a user