aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederick Mayle <fmayle@google.com>2023-11-09 23:20:35 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-11-09 23:20:35 +0000
commite7b3c7b32c68197ca252bb90e262f11b77222d1b (patch)
tree16884898ac7178d3574190152c1dcfde5ed9e432
parentdd8dd381e0766595f8b1ccf554da0ba358a62cbe (diff)
parentec982164912a30d730c8fcaef14a99f3ee869b78 (diff)
downloadcrosvm-e7b3c7b32c68197ca252bb90e262f11b77222d1b.tar.gz
Merge changes I16e3fdd5,I1baf006b into main am: fd3a5e7fe5 am: ec98216491
Original change: https://android-review.googlesource.com/c/platform/external/crosvm/+/2824115 Change-Id: Icaff3758e2ff9a14cda0b230b346cd95afcf729d Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--devices/src/virtio/console.rs35
-rw-r--r--devices/src/virtio/console/sys/linux.rs18
-rw-r--r--devices/src/virtio/console/sys/windows.rs11
3 files changed, 31 insertions, 33 deletions
diff --git a/devices/src/virtio/console.rs b/devices/src/virtio/console.rs
index 88646da24..6523783ee 100644
--- a/devices/src/virtio/console.rs
+++ b/devices/src/virtio/console.rs
@@ -43,6 +43,7 @@ use zerocopy::AsBytes;
use zerocopy::FromBytes;
use zerocopy::FromZeroes;
+use crate::serial::sys::InStreamType;
use crate::virtio::base_features;
use crate::virtio::copy_config;
use crate::virtio::DeviceType;
@@ -256,20 +257,15 @@ impl Worker {
}
}
-enum ConsoleInput {
- FromRead(crate::serial::sys::InStreamType),
- FromThread(Arc<Mutex<VecDeque<u8>>>),
-}
-
/// Virtio console device.
pub struct Console {
base_features: u64,
in_avail_evt: Option<Event>,
worker_thread: Option<WorkerThread<Worker>>,
- input: Option<ConsoleInput>,
+ input: Option<InStreamType>,
output: Option<Box<dyn io::Write + Send>>,
keep_descriptors: Vec<Descriptor>,
- input_thread: Option<WorkerThread<()>>,
+ input_thread: Option<WorkerThread<InStreamType>>,
// input_buffer is not continuously updated. It holds the state of the buffer when a snapshot
// happens, or when a restore is performed. On a fresh startup, it will be empty. On a restore,
// it will contain whatever data was remaining in the buffer in the snapshot.
@@ -285,7 +281,7 @@ struct ConsoleSnapshot {
impl Console {
fn new(
protection_type: ProtectionType,
- input: Option<ConsoleInput>,
+ input: Option<InStreamType>,
output: Option<Box<dyn io::Write + Send>>,
keep_rds: Vec<RawDescriptor>,
) -> Console {
@@ -360,16 +356,15 @@ impl VirtioDevice for Console {
// descriptor). Moving the blocking read call to a separate thread and sending data back to
// the main worker thread with an event for notification bridges this gap.
let input = match self.input.take() {
- Some(ConsoleInput::FromRead(read)) => {
+ Some(read) => {
let (buffer, thread) = sys::spawn_input_thread(
read,
self.in_avail_evt.as_ref().unwrap(),
- self.input_buffer.clone(),
+ std::mem::take(&mut self.input_buffer),
);
self.input_thread = Some(thread);
Some(buffer)
}
- Some(ConsoleInput::FromThread(buffer)) => Some(buffer),
None => None,
};
let output = self.output.take().unwrap_or_else(|| Box::new(io::sink()));
@@ -395,9 +390,14 @@ impl VirtioDevice for Console {
}
fn reset(&mut self) -> bool {
+ self.input = self.input_thread.take().map(|t| t.stop());
if let Some(worker_thread) = self.worker_thread.take() {
let worker = worker_thread.stop();
- self.input = worker.input.map(ConsoleInput::FromThread);
+ // NOTE: Even though we are reseting the device, it still makes sense to preserve the
+ // pending input bytes that the host sent but the guest hasn't accepted yet.
+ self.input_buffer = worker
+ .input
+ .map_or(VecDeque::new(), |arc_mutex| arc_mutex.lock().clone());
self.output = Some(worker.output);
return true;
}
@@ -405,14 +405,13 @@ impl VirtioDevice for Console {
}
fn virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>> {
+ self.input = self.input_thread.take().map(|t| t.stop());
if let Some(worker_thread) = self.worker_thread.take() {
- if let Some(input_thread) = self.input_thread.take() {
- input_thread.stop();
- }
let worker = worker_thread.stop();
- if let Some(in_buf_ref) = worker.input.as_ref() {
- self.input_buffer = in_buf_ref.lock().clone();
- }
+ self.input_buffer = worker
+ .input
+ .map_or(VecDeque::new(), |arc_mutex| arc_mutex.lock().clone());
+ self.output = Some(worker.output);
let receive_queue = match Arc::try_unwrap(worker.receive_queue) {
Ok(mutex) => mutex.into_inner(),
Err(_) => return Err(anyhow!("failed to retrieve receive queue to sleep device.")),
diff --git a/devices/src/virtio/console/sys/linux.rs b/devices/src/virtio/console/sys/linux.rs
index bbd9ffc39..f78dc4fab 100644
--- a/devices/src/virtio/console/sys/linux.rs
+++ b/devices/src/virtio/console/sys/linux.rs
@@ -17,9 +17,9 @@ use base::WaitContext;
use base::WorkerThread;
use sync::Mutex;
+use crate::serial::sys::InStreamType;
use crate::serial_device::SerialInput;
use crate::virtio::console::Console;
-use crate::virtio::console::ConsoleInput;
use crate::virtio::ProtectionType;
use crate::SerialDevice;
@@ -34,12 +34,7 @@ impl SerialDevice for Console {
_out_timestamp: bool,
keep_rds: Vec<RawDescriptor>,
) -> Console {
- Console::new(
- protection_type,
- input.map(ConsoleInput::FromRead),
- out,
- keep_rds,
- )
+ Console::new(protection_type, input, out, keep_rds)
}
}
@@ -58,10 +53,10 @@ fn is_a_fatal_input_error(e: &io::Error) -> bool {
/// * `rx` - Data source that the reader thread will wait on to send data back to the buffer
/// * `in_avail_evt` - Event triggered by the thread when new input is available on the buffer
pub(in crate::virtio::console) fn spawn_input_thread(
- mut rx: crate::serial::sys::InStreamType,
+ mut rx: InStreamType,
in_avail_evt: &Event,
input_buffer: VecDeque<u8>,
-) -> (Arc<Mutex<VecDeque<u8>>>, WorkerThread<()>) {
+) -> (Arc<Mutex<VecDeque<u8>>>, WorkerThread<InStreamType>) {
let buffer = Arc::new(Mutex::new(input_buffer));
let buffer_cloned = buffer.clone();
@@ -88,7 +83,7 @@ pub(in crate::virtio::console) fn spawn_input_thread(
Ok(ctx) => ctx,
Err(e) => {
error!("failed creating WaitContext {:?}", e);
- return;
+ return rx;
}
};
@@ -99,7 +94,7 @@ pub(in crate::virtio::console) fn spawn_input_thread(
Ok(events) => events,
Err(e) => {
error!("Failed to wait for events. {}", e);
- return;
+ return rx;
}
};
for event in events.iter() {
@@ -149,6 +144,7 @@ pub(in crate::virtio::console) fn spawn_input_thread(
}
}
}
+ rx
});
(buffer_cloned, res)
}
diff --git a/devices/src/virtio/console/sys/windows.rs b/devices/src/virtio/console/sys/windows.rs
index c238dfd77..58e7bd018 100644
--- a/devices/src/virtio/console/sys/windows.rs
+++ b/devices/src/virtio/console/sys/windows.rs
@@ -18,7 +18,6 @@ use sync::Mutex;
use crate::serial_device::SerialInput;
use crate::virtio::console::Console;
-use crate::virtio::console::ConsoleInput;
use crate::virtio::ProtectionType;
use crate::SerialDevice;
@@ -46,7 +45,7 @@ impl SerialDevice for Console {
) -> Console {
Console::new(
protection_type,
- Some(ConsoleInput::FromRead(Box::new(pipe_in))),
+ Some(Box::new(pipe_in)),
Some(Box::new(pipe_out)),
keep_rds,
)
@@ -90,7 +89,10 @@ pub(in crate::virtio::console) fn spawn_input_thread(
mut rx: Box<named_pipes::PipeConnection>,
in_avail_evt: &Event,
input_buffer: VecDeque<u8>,
-) -> (Arc<Mutex<VecDeque<u8>>>, WorkerThread<()>) {
+) -> (
+ Arc<Mutex<VecDeque<u8>>>,
+ WorkerThread<Box<named_pipes::PipeConnection>>,
+) {
let buffer = Arc::new(Mutex::new(input_buffer));
let buffer_cloned = buffer.clone();
@@ -107,7 +109,7 @@ pub(in crate::virtio::console) fn spawn_input_thread(
}
match rx.wait_for_client_connection_overlapped_blocking(&kill_evt) {
- Err(e) if e.kind() == io::ErrorKind::Interrupted => return,
+ Err(e) if e.kind() == io::ErrorKind::Interrupted => return rx,
Err(e) => panic!("failed to wait for client: {}", e),
Ok(()) => (),
}
@@ -148,6 +150,7 @@ pub(in crate::virtio::console) fn spawn_input_thread(
// Depending on the platform, a short sleep is needed here (ie. Windows).
read_delay_if_needed();
}
+ rx
});
(buffer_cloned, res)
}