mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-03-20 07:58:55 +00:00
vmm, virtio-console: Move input reading into virtio-console thread
Move the processing of the input from stdin, PTY or file from the VMM thread to the existing virtio-console thread. The handling of the resize of a virtio-console has not changed but the name of the struct used to support that has been renamed to reflect its usage. Fixes: #3060 Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
0d01eac1d4
commit
c2144b5690
@ -14,9 +14,9 @@ use libc::EFD_NONBLOCK;
|
||||
use seccompiler::{apply_filter, SeccompAction};
|
||||
use std::cmp;
|
||||
use std::collections::VecDeque;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::ops::DerefMut;
|
||||
use std::io::{Read, Write};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::result;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
@ -40,6 +40,8 @@ const OUTPUT_QUEUE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2;
|
||||
const INPUT_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 3;
|
||||
// Console configuration change event is triggered.
|
||||
const CONFIG_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 4;
|
||||
// File written to (input ready)
|
||||
const FILE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 5;
|
||||
|
||||
//Console size feature bit
|
||||
const VIRTIO_CONSOLE_F_SIZE: u64 = 0;
|
||||
@ -61,7 +63,7 @@ struct ConsoleEpollHandler {
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
interrupt_cb: Arc<dyn VirtioInterrupt>,
|
||||
in_buffer: Arc<Mutex<VecDeque<u8>>>,
|
||||
out: Arc<Mutex<Box<dyn io::Write + Send + Sync + 'static>>>,
|
||||
endpoint: Endpoint,
|
||||
input_queue_evt: EventFd,
|
||||
output_queue_evt: EventFd,
|
||||
input_evt: EventFd,
|
||||
@ -70,6 +72,42 @@ struct ConsoleEpollHandler {
|
||||
pause_evt: EventFd,
|
||||
}
|
||||
|
||||
pub enum Endpoint {
|
||||
File(File),
|
||||
FilePair(File, File),
|
||||
Null,
|
||||
}
|
||||
|
||||
impl Endpoint {
|
||||
fn out_file(&self) -> Option<&File> {
|
||||
match self {
|
||||
Self::File(f) => Some(f),
|
||||
Self::FilePair(f, _) => Some(f),
|
||||
Self::Null => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn in_file(&self) -> Option<&File> {
|
||||
match self {
|
||||
Self::File(_) => None,
|
||||
Self::FilePair(_, f) => Some(f),
|
||||
Self::Null => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Endpoint {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
Self::File(f) => Self::File(f.try_clone().unwrap()),
|
||||
Self::FilePair(f_out, f_in) => {
|
||||
Self::FilePair(f_out.try_clone().unwrap(), f_in.try_clone().unwrap())
|
||||
}
|
||||
Self::Null => Self::Null,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConsoleEpollHandler {
|
||||
/*
|
||||
* Each port of virtio console device has one receive
|
||||
@ -127,14 +165,10 @@ impl ConsoleEpollHandler {
|
||||
let mem = self.mem.memory();
|
||||
for avail_desc in trans_queue.iter(&mem) {
|
||||
let len;
|
||||
let mut out = self.out.lock().unwrap();
|
||||
let _ = mem.write_to(
|
||||
avail_desc.addr,
|
||||
&mut out.deref_mut(),
|
||||
avail_desc.len as usize,
|
||||
);
|
||||
let _ = out.flush();
|
||||
|
||||
if let Some(ref mut out) = self.endpoint.out_file() {
|
||||
let _ = mem.write_to(avail_desc.addr, out, avail_desc.len as usize);
|
||||
let _ = out.flush();
|
||||
}
|
||||
len = avail_desc.len;
|
||||
used_desc_heads[used_count] = (avail_desc.index, len);
|
||||
used_count += 1;
|
||||
@ -165,6 +199,9 @@ impl ConsoleEpollHandler {
|
||||
helper.add_event(self.output_queue_evt.as_raw_fd(), OUTPUT_QUEUE_EVENT)?;
|
||||
helper.add_event(self.input_evt.as_raw_fd(), INPUT_EVENT)?;
|
||||
helper.add_event(self.config_evt.as_raw_fd(), CONFIG_EVENT)?;
|
||||
if let Some(in_file) = self.endpoint.in_file() {
|
||||
helper.add_event(in_file.as_raw_fd(), FILE_EVENT)?;
|
||||
}
|
||||
helper.run(paused, paused_sync, self)?;
|
||||
|
||||
Ok(())
|
||||
@ -217,6 +254,22 @@ impl EpollHelperHandler for ConsoleEpollHandler {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
FILE_EVENT => {
|
||||
let mut input = [0u8; 64];
|
||||
if let Some(ref mut in_file) = self.endpoint.in_file() {
|
||||
if let Ok(count) = in_file.read(&mut input) {
|
||||
let mut in_buffer = self.in_buffer.lock().unwrap();
|
||||
in_buffer.extend(&input[..count]);
|
||||
}
|
||||
|
||||
if self.process_input_queue() {
|
||||
if let Err(e) = self.signal_used_queue() {
|
||||
error!("Failed to signal used queue: {:?}", e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
error!("Unknown event for virtio-console");
|
||||
return true;
|
||||
@ -226,22 +279,14 @@ impl EpollHelperHandler for ConsoleEpollHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/// Input device.
|
||||
pub struct ConsoleInput {
|
||||
input_evt: EventFd,
|
||||
/// Resize handler
|
||||
pub struct ConsoleResizer {
|
||||
config_evt: EventFd,
|
||||
in_buffer: Arc<Mutex<VecDeque<u8>>>,
|
||||
config: Arc<Mutex<VirtioConsoleConfig>>,
|
||||
acked_features: AtomicU64,
|
||||
}
|
||||
|
||||
impl ConsoleInput {
|
||||
pub fn queue_input_bytes(&self, input: &[u8]) {
|
||||
let mut in_buffer = self.in_buffer.lock().unwrap();
|
||||
in_buffer.extend(input);
|
||||
let _ = self.input_evt.write(1);
|
||||
}
|
||||
|
||||
impl ConsoleResizer {
|
||||
pub fn update_console_size(&self, cols: u16, rows: u16) {
|
||||
if self
|
||||
.acked_features
|
||||
@ -276,9 +321,10 @@ pub struct Console {
|
||||
common: VirtioCommon,
|
||||
id: String,
|
||||
config: Arc<Mutex<VirtioConsoleConfig>>,
|
||||
input: Arc<ConsoleInput>,
|
||||
out: Arc<Mutex<Box<dyn io::Write + Send + Sync + 'static>>>,
|
||||
resizer: Arc<ConsoleResizer>,
|
||||
endpoint: Endpoint,
|
||||
seccomp_action: SeccompAction,
|
||||
in_buffer: Arc<Mutex<VecDeque<u8>>>,
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
@ -295,25 +341,22 @@ impl Console {
|
||||
/// Create a new virtio console device that gets random data from /dev/urandom.
|
||||
pub fn new(
|
||||
id: String,
|
||||
out: Box<dyn io::Write + Send + Sync + 'static>,
|
||||
endpoint: Endpoint,
|
||||
cols: u16,
|
||||
rows: u16,
|
||||
iommu: bool,
|
||||
seccomp_action: SeccompAction,
|
||||
) -> io::Result<(Console, Arc<ConsoleInput>)> {
|
||||
) -> io::Result<(Console, Arc<ConsoleResizer>)> {
|
||||
let mut avail_features = 1u64 << VIRTIO_F_VERSION_1 | 1u64 << VIRTIO_CONSOLE_F_SIZE;
|
||||
|
||||
if iommu {
|
||||
avail_features |= 1u64 << VIRTIO_F_IOMMU_PLATFORM;
|
||||
}
|
||||
|
||||
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,
|
||||
let resizer = Arc::new(ConsoleResizer {
|
||||
config_evt,
|
||||
in_buffer: Arc::new(Mutex::new(VecDeque::new())),
|
||||
config: console_config.clone(),
|
||||
acked_features: AtomicU64::new(0),
|
||||
});
|
||||
@ -330,11 +373,12 @@ impl Console {
|
||||
},
|
||||
id,
|
||||
config: console_config,
|
||||
input: console_input.clone(),
|
||||
out: Arc::new(Mutex::new(out)),
|
||||
resizer: resizer.clone(),
|
||||
endpoint,
|
||||
seccomp_action,
|
||||
in_buffer: Arc::new(Mutex::new(VecDeque::new())),
|
||||
},
|
||||
console_input,
|
||||
resizer,
|
||||
))
|
||||
}
|
||||
|
||||
@ -343,7 +387,7 @@ impl Console {
|
||||
avail_features: self.common.avail_features,
|
||||
acked_features: self.common.acked_features,
|
||||
config: *(self.config.lock().unwrap()),
|
||||
in_buffer: self.input.in_buffer.lock().unwrap().clone().into(),
|
||||
in_buffer: self.in_buffer.lock().unwrap().clone().into(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,7 +395,7 @@ impl Console {
|
||||
self.common.avail_features = state.avail_features;
|
||||
self.common.acked_features = state.acked_features;
|
||||
*(self.config.lock().unwrap()) = state.config;
|
||||
*(self.input.in_buffer.lock().unwrap()) = state.in_buffer.clone().into();
|
||||
*(self.in_buffer.lock().unwrap()) = state.in_buffer.clone().into();
|
||||
}
|
||||
}
|
||||
|
||||
@ -393,7 +437,7 @@ impl VirtioDevice for Console {
|
||||
mut queue_evts: Vec<EventFd>,
|
||||
) -> ActivateResult {
|
||||
self.common.activate(&queues, &queue_evts, &interrupt_cb)?;
|
||||
self.input
|
||||
self.resizer
|
||||
.acked_features
|
||||
.store(self.common.acked_features, Ordering::Relaxed);
|
||||
|
||||
@ -404,17 +448,18 @@ impl VirtioDevice for Console {
|
||||
}
|
||||
|
||||
let (kill_evt, pause_evt) = self.common.dup_eventfds();
|
||||
let input_evt = EventFd::new(EFD_NONBLOCK).unwrap();
|
||||
|
||||
let mut handler = ConsoleEpollHandler {
|
||||
queues,
|
||||
mem,
|
||||
interrupt_cb,
|
||||
in_buffer: self.input.in_buffer.clone(),
|
||||
out: self.out.clone(),
|
||||
in_buffer: self.in_buffer.clone(),
|
||||
endpoint: self.endpoint.clone(),
|
||||
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(),
|
||||
input_evt,
|
||||
config_evt: self.resizer.config_evt.try_clone().unwrap(),
|
||||
kill_evt,
|
||||
pause_evt,
|
||||
};
|
||||
|
@ -73,7 +73,7 @@ use seccompiler::SeccompAction;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::fs::{read_link, File, OpenOptions};
|
||||
use std::io::{self, sink, stdout, Seek, SeekFrom};
|
||||
use std::io::{self, stdout, Seek, SeekFrom};
|
||||
use std::mem::zeroed;
|
||||
use std::num::Wrapping;
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
@ -88,7 +88,7 @@ use vfio_ioctls::{VfioContainer, VfioDevice};
|
||||
use virtio_devices::transport::VirtioPciDevice;
|
||||
use virtio_devices::transport::VirtioTransport;
|
||||
use virtio_devices::vhost_user::VhostUserConfig;
|
||||
use virtio_devices::{DmaRemapping, IommuMapping};
|
||||
use virtio_devices::{DmaRemapping, Endpoint, IommuMapping};
|
||||
use virtio_devices::{VirtioSharedMemory, VirtioSharedMemoryList};
|
||||
use vm_allocator::SystemAllocator;
|
||||
#[cfg(feature = "kvm")]
|
||||
@ -535,7 +535,7 @@ pub struct Console {
|
||||
serial: Option<Arc<Mutex<Serial>>>,
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
serial: Option<Arc<Mutex<Pl011>>>,
|
||||
virtio_console_input: Option<Arc<virtio_devices::ConsoleInput>>,
|
||||
console_resizer: Option<Arc<virtio_devices::ConsoleResizer>>,
|
||||
input: Option<ConsoleInput>,
|
||||
}
|
||||
|
||||
@ -552,21 +552,9 @@ impl Console {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn queue_input_bytes_console(&self, out: &[u8]) {
|
||||
if self.virtio_console_input.is_some() {
|
||||
self.virtio_console_input
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.queue_input_bytes(out);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_console_size(&self, cols: u16, rows: u16) {
|
||||
if self.virtio_console_input.is_some() {
|
||||
self.virtio_console_input
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.update_console_size(cols, rows)
|
||||
if let Some(resizer) = self.console_resizer.as_ref() {
|
||||
resizer.update_console_size(cols, rows)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1695,6 +1683,81 @@ impl DeviceManager {
|
||||
self.modify_mode(f.as_raw_fd(), |t| t.c_lflag &= !(ICANON | ECHO | ISIG))
|
||||
}
|
||||
|
||||
fn add_virtio_console_device(
|
||||
&mut self,
|
||||
virtio_devices: &mut Vec<(VirtioDeviceArc, bool, String)>,
|
||||
console_pty: Option<PtyPair>,
|
||||
) -> DeviceManagerResult<Option<Arc<virtio_devices::ConsoleResizer>>> {
|
||||
let console_config = self.config.lock().unwrap().console.clone();
|
||||
let endpoint = match console_config.mode {
|
||||
ConsoleOutputMode::File => {
|
||||
let file = File::create(console_config.file.as_ref().unwrap())
|
||||
.map_err(DeviceManagerError::ConsoleOutputFileOpen)?;
|
||||
Endpoint::File(file)
|
||||
}
|
||||
ConsoleOutputMode::Pty => {
|
||||
if let Some(pty) = console_pty {
|
||||
self.config.lock().unwrap().console.file = Some(pty.path.clone());
|
||||
let file = pty.main.try_clone().unwrap();
|
||||
self.console_pty = Some(Arc::new(Mutex::new(pty)));
|
||||
Endpoint::FilePair(file.try_clone().unwrap(), file)
|
||||
} else {
|
||||
let (main, mut sub, path) =
|
||||
create_pty(false).map_err(DeviceManagerError::ConsolePtyOpen)?;
|
||||
self.set_raw_mode(&mut sub)
|
||||
.map_err(DeviceManagerError::SetPtyRaw)?;
|
||||
self.config.lock().unwrap().console.file = Some(path.clone());
|
||||
let file = main.try_clone().unwrap();
|
||||
self.console_pty = Some(Arc::new(Mutex::new(PtyPair { main, sub, path })));
|
||||
Endpoint::FilePair(file.try_clone().unwrap(), file)
|
||||
}
|
||||
}
|
||||
ConsoleOutputMode::Tty => {
|
||||
// If an interactive TTY then we can accept input
|
||||
if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } {
|
||||
Endpoint::FilePair(
|
||||
// Duplicating the file descriptors like this is needed as otherwise
|
||||
// they will be closed on a reboot and the numbers reused
|
||||
unsafe { File::from_raw_fd(libc::dup(libc::STDOUT_FILENO)) },
|
||||
unsafe { File::from_raw_fd(libc::dup(libc::STDIN_FILENO)) },
|
||||
)
|
||||
} else {
|
||||
Endpoint::File(unsafe { File::from_raw_fd(libc::dup(libc::STDOUT_FILENO)) })
|
||||
}
|
||||
}
|
||||
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(),
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioConsole)?;
|
||||
let virtio_console_device = Arc::new(Mutex::new(virtio_console_device));
|
||||
virtio_devices.push((
|
||||
Arc::clone(&virtio_console_device) as VirtioDeviceArc,
|
||||
console_config.iommu,
|
||||
id.clone(),
|
||||
));
|
||||
|
||||
// Fill the device tree with a new node. In case of restore, we
|
||||
// know there is nothing to do, so we can simply override the
|
||||
// existing entry.
|
||||
self.device_tree
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(id.clone(), device_node!(id, virtio_console_device));
|
||||
|
||||
Ok(Some(console_resizer))
|
||||
}
|
||||
|
||||
fn add_console_device(
|
||||
&mut self,
|
||||
interrupt_manager: &Arc<dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>>,
|
||||
@ -1702,6 +1765,7 @@ impl DeviceManager {
|
||||
serial_pty: Option<PtyPair>,
|
||||
console_pty: Option<PtyPair>,
|
||||
) -> DeviceManagerResult<Arc<Console>> {
|
||||
let console_config = self.config.lock().unwrap().console.clone();
|
||||
let serial_config = self.config.lock().unwrap().serial.clone();
|
||||
let serial_writer: Option<Box<dyn io::Write + Send>> = match serial_config.mode {
|
||||
ConsoleOutputMode::File => Some(Box::new(
|
||||
@ -1736,66 +1800,7 @@ impl DeviceManager {
|
||||
None
|
||||
};
|
||||
|
||||
// Create serial and virtio-console
|
||||
let console_config = self.config.lock().unwrap().console.clone();
|
||||
let console_writer: Option<Box<dyn io::Write + Send + Sync>> = match console_config.mode {
|
||||
ConsoleOutputMode::File => Some(Box::new(
|
||||
File::create(console_config.file.as_ref().unwrap())
|
||||
.map_err(DeviceManagerError::ConsoleOutputFileOpen)?,
|
||||
)),
|
||||
ConsoleOutputMode::Pty => {
|
||||
if let Some(pty) = console_pty {
|
||||
self.config.lock().unwrap().console.file = Some(pty.path.clone());
|
||||
let writer = pty.main.try_clone().unwrap();
|
||||
self.console_pty = Some(Arc::new(Mutex::new(pty)));
|
||||
Some(Box::new(writer))
|
||||
} else {
|
||||
let (main, mut sub, path) =
|
||||
create_pty(false).map_err(DeviceManagerError::ConsolePtyOpen)?;
|
||||
self.set_raw_mode(&mut sub)
|
||||
.map_err(DeviceManagerError::SetPtyRaw)?;
|
||||
self.config.lock().unwrap().console.file = Some(path.clone());
|
||||
let writer = main.try_clone().unwrap();
|
||||
self.console_pty = Some(Arc::new(Mutex::new(PtyPair { main, sub, path })));
|
||||
Some(Box::new(writer))
|
||||
}
|
||||
}
|
||||
ConsoleOutputMode::Tty => Some(Box::new(stdout())),
|
||||
ConsoleOutputMode::Null => Some(Box::new(sink())),
|
||||
ConsoleOutputMode::Off => None,
|
||||
};
|
||||
let (col, row) = get_win_size();
|
||||
let virtio_console_input = if let Some(writer) = console_writer {
|
||||
let id = String::from(CONSOLE_DEVICE_NAME);
|
||||
|
||||
let (virtio_console_device, virtio_console_input) = virtio_devices::Console::new(
|
||||
id.clone(),
|
||||
writer,
|
||||
col,
|
||||
row,
|
||||
self.force_iommu | console_config.iommu,
|
||||
self.seccomp_action.clone(),
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateVirtioConsole)?;
|
||||
let virtio_console_device = Arc::new(Mutex::new(virtio_console_device));
|
||||
virtio_devices.push((
|
||||
Arc::clone(&virtio_console_device) as VirtioDeviceArc,
|
||||
console_config.iommu,
|
||||
id.clone(),
|
||||
));
|
||||
|
||||
// Fill the device tree with a new node. In case of restore, we
|
||||
// know there is nothing to do, so we can simply override the
|
||||
// existing entry.
|
||||
self.device_tree
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(id.clone(), device_node!(id, virtio_console_device));
|
||||
|
||||
Some(virtio_console_input)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let console_resizer = self.add_virtio_console_device(virtio_devices, console_pty)?;
|
||||
|
||||
let input = if serial_config.mode.input_enabled() {
|
||||
Some(ConsoleInput::Serial)
|
||||
@ -1807,8 +1812,8 @@ impl DeviceManager {
|
||||
|
||||
Ok(Arc::new(Console {
|
||||
serial,
|
||||
virtio_console_input,
|
||||
input,
|
||||
console_resizer,
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -150,8 +150,7 @@ pub enum EpollDispatch {
|
||||
Stdin = 2,
|
||||
Api = 3,
|
||||
ActivateVirtioDevices = 4,
|
||||
ConsolePty = 5,
|
||||
SerialPty = 6,
|
||||
SerialPty = 5,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
@ -164,8 +163,7 @@ impl From<u64> for EpollDispatch {
|
||||
2 => Stdin,
|
||||
3 => Api,
|
||||
4 => ActivateVirtioDevices,
|
||||
5 => ConsolePty,
|
||||
6 => SerialPty,
|
||||
5 => SerialPty,
|
||||
_ => Unknown,
|
||||
}
|
||||
}
|
||||
@ -324,10 +322,6 @@ impl Vmm {
|
||||
let reset_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
|
||||
let activate_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
|
||||
|
||||
if unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0 {
|
||||
epoll.add_stdin().map_err(Error::Epoll)?;
|
||||
}
|
||||
|
||||
epoll
|
||||
.add_event(&exit_evt, EpollDispatch::Exit)
|
||||
.map_err(Error::Epoll)?;
|
||||
@ -400,11 +394,14 @@ impl Vmm {
|
||||
.add_event(&serial_pty.main, EpollDispatch::SerialPty)
|
||||
.map_err(VmError::EventfdError)?;
|
||||
};
|
||||
if let Some(console_pty) = vm.console_pty() {
|
||||
self.epoll
|
||||
.add_event(&console_pty.main, EpollDispatch::ConsolePty)
|
||||
.map_err(VmError::EventfdError)?;
|
||||
};
|
||||
if matches!(
|
||||
vm_config.lock().unwrap().serial.mode,
|
||||
config::ConsoleOutputMode::Tty
|
||||
) && unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0
|
||||
{
|
||||
self.epoll.add_stdin().map_err(VmError::EventfdError)?;
|
||||
}
|
||||
|
||||
self.vm = Some(vm);
|
||||
}
|
||||
}
|
||||
@ -1302,7 +1299,7 @@ impl Vmm {
|
||||
.map_err(Error::ActivateVirtioDevices)?;
|
||||
}
|
||||
}
|
||||
event @ (EpollDispatch::ConsolePty | EpollDispatch::SerialPty) => {
|
||||
event @ EpollDispatch::SerialPty => {
|
||||
if let Some(ref vm) = self.vm {
|
||||
vm.handle_pty(event).map_err(Error::Pty)?;
|
||||
}
|
||||
|
@ -1928,15 +1928,6 @@ impl Vm {
|
||||
.map_err(Error::Console)?;
|
||||
}
|
||||
};
|
||||
} else if matches!(event, EpollDispatch::ConsolePty) {
|
||||
if let Some(mut pty) = dm.console_pty() {
|
||||
let mut out = [0u8; 64];
|
||||
let count = pty.main.read(&mut out).map_err(Error::PtyConsole)?;
|
||||
let console = dm.console();
|
||||
if console.input_enabled() {
|
||||
console.queue_input_bytes_console(&out[..count])
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -1964,15 +1955,6 @@ impl Vm {
|
||||
.console()
|
||||
.queue_input_bytes_serial(&out[..count])
|
||||
.map_err(Error::Console)?;
|
||||
} else if matches!(
|
||||
self.config.lock().unwrap().console.mode,
|
||||
ConsoleOutputMode::Tty
|
||||
) {
|
||||
self.device_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.console()
|
||||
.queue_input_bytes_console(&out[..count])
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
Loading…
x
Reference in New Issue
Block a user