mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-10 04:07:23 +00:00
devices: resync with downstream
This closes the deltas between some of the files of the crate. The changes include - Enables building/testing balloon module on windows. - Suppressing dead-code warnings on windows in cross platform files. - u16 to enum fix. - Organizing imports. - Using Descriptor(windows friendly) over RawDescriptor. - Using Option<Tube> instead of Tube. - Fix some args parsing on windows. BUG=213149155 TEST=presubmit and built on windows downstream Change-Id: Idd2ee81384bc5fade610aa864b2c712ea0a0e0d2 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3783010 Tested-by: Vikram Auradkar <auradkar@google.com> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Commit-Queue: Vikram Auradkar <auradkar@google.com> Auto-Submit: Vikram Auradkar <auradkar@google.com>
This commit is contained in:
parent
15e1e977d2
commit
02028483bc
27 changed files with 167 additions and 148 deletions
|
@ -66,7 +66,8 @@ sync = { path = "../common/sync" }
|
|||
system_api = { version = "*", optional = true }
|
||||
thiserror = "1.0.20"
|
||||
tpm2 = { path = "../tpm2", optional = true }
|
||||
uuid = { version = "0.8.2" }
|
||||
tracing = { path = "../tracing" }
|
||||
uuid = { version = "0.8.2", features = [ "serde" ] }
|
||||
vhost = { path = "../vhost" }
|
||||
vmm_vhost = { path = "../third_party/vmm_vhost", features = ["vmm", "device", "vfio-device"] }
|
||||
virtio_sys = { path = "../virtio_sys" }
|
||||
|
@ -87,8 +88,9 @@ vfio_sys = { path = "../vfio_sys" }
|
|||
[target.'cfg(windows)'.dependencies]
|
||||
broker_ipc = { path = "../broker_ipc" }
|
||||
chrono = "*"
|
||||
tracing = { path = "../tracing" }
|
||||
metrics = { path = "../metrics" }
|
||||
tube_transporter = { path = "../tube_transporter" }
|
||||
win_util = { path = "../win_util"}
|
||||
winapi = "*"
|
||||
|
||||
[dependencies.futures]
|
||||
|
|
|
@ -192,6 +192,7 @@ impl DelayedIoApicIrqEvents {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(windows, allow(dead_code))]
|
||||
#[cfg(test)]
|
||||
/// This module contains tests that apply to any implementations of IrqChipX86_64
|
||||
pub(super) mod tests {
|
||||
|
|
|
@ -75,7 +75,7 @@ pub const PCI_VENDOR_ID_INTEL: u16 = 0x8086;
|
|||
pub const PCI_VENDOR_ID_REDHAT: u16 = 0x1b36;
|
||||
|
||||
#[repr(u16)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum CrosvmDeviceId {
|
||||
Pit = 1,
|
||||
Pic = 2,
|
||||
|
@ -118,7 +118,8 @@ impl TryFrom<u16> for CrosvmDeviceId {
|
|||
14 => Ok(CrosvmDeviceId::DirectMmio),
|
||||
15 => Ok(CrosvmDeviceId::DirectIo),
|
||||
16 => Ok(CrosvmDeviceId::UserspaceIrqChip),
|
||||
17 => Ok(CrosvmDeviceId::Pflash),
|
||||
17 => Ok(CrosvmDeviceId::VmWatchdog),
|
||||
18 => Ok(CrosvmDeviceId::Pflash),
|
||||
_ => Err(base::Error::new(EINVAL)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#![cfg_attr(windows, allow(dead_code))]
|
||||
|
||||
use base::{error, AsRawDescriptor, Event, RawDescriptor, Tube};
|
||||
use bit_field::*;
|
||||
use data_model::DataInit;
|
||||
|
|
|
@ -12,8 +12,6 @@ use std::sync::Arc;
|
|||
use std::thread::{self};
|
||||
|
||||
use base::{error, Event, Result};
|
||||
#[cfg(windows)]
|
||||
use base::{named_pipes, FileSync};
|
||||
|
||||
use crate::bus::BusAccessInfo;
|
||||
use crate::pci::CrosvmDeviceId;
|
||||
|
|
|
@ -8,9 +8,8 @@ use std::thread::{self, JoinHandle};
|
|||
use std::time::Duration;
|
||||
|
||||
use base::{
|
||||
error,
|
||||
named_pipes::{self, PipeConnection},
|
||||
Event, EventToken, FileSync, RawDescriptor, Result, WaitContext,
|
||||
error, named_pipes::PipeConnection, Event, EventToken, FileSync, RawDescriptor, Result,
|
||||
WaitContext,
|
||||
};
|
||||
use hypervisor::ProtectionType;
|
||||
|
||||
|
@ -117,7 +116,7 @@ impl SerialDevice for Serial {
|
|||
out: Option<Box<dyn io::Write + Send>>,
|
||||
sync: Option<Box<dyn FileSync + Send>>,
|
||||
out_timestamp: bool,
|
||||
keep_rds: Vec<RawDescriptor>,
|
||||
_keep_rds: Vec<RawDescriptor>,
|
||||
) -> Serial {
|
||||
let system_params = SystemSerialParams {
|
||||
out_timestamp,
|
||||
|
@ -137,9 +136,9 @@ impl SerialDevice for Serial {
|
|||
fn new_with_pipe(
|
||||
_protected_vm: ProtectionType,
|
||||
interrupt_evt: Event,
|
||||
pipe_in: named_pipes::PipeConnection,
|
||||
pipe_out: named_pipes::PipeConnection,
|
||||
keep_rds: Vec<RawDescriptor>,
|
||||
pipe_in: PipeConnection,
|
||||
pipe_out: PipeConnection,
|
||||
_keep_rds: Vec<RawDescriptor>,
|
||||
) -> Serial {
|
||||
let system_params = SystemSerialParams {
|
||||
out_timestamp: false,
|
||||
|
@ -238,8 +237,6 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
use regex::Regex;
|
||||
use std::sync::Arc;
|
||||
use sync::Mutex;
|
||||
|
||||
use crate::serial::tests::*;
|
||||
use crate::serial::*;
|
||||
|
|
|
@ -3,9 +3,7 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
use super::error::{Error, Result};
|
||||
use base::{
|
||||
error, warn, AsRawDescriptor, Descriptor, Event, EventType, RawDescriptor, WaitContext,
|
||||
};
|
||||
use base::{error, warn, AsRawDescriptor, Descriptor, Event, EventType, WaitContext};
|
||||
use std::collections::BTreeMap;
|
||||
use std::mem::drop;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
@ -41,7 +39,7 @@ impl FailHandle for Option<Arc<dyn FailHandle>> {
|
|||
pub struct EventLoop {
|
||||
fail_handle: Option<Arc<dyn FailHandle>>,
|
||||
poll_ctx: Arc<WaitContext<Descriptor>>,
|
||||
handlers: Arc<Mutex<BTreeMap<RawDescriptor, Weak<dyn EventHandler>>>>,
|
||||
handlers: Arc<Mutex<BTreeMap<Descriptor, Weak<dyn EventHandler>>>>,
|
||||
stop_evt: Event,
|
||||
}
|
||||
|
||||
|
@ -60,7 +58,7 @@ impl EventLoop {
|
|||
.and_then(|e| Ok((e.try_clone()?, e)))
|
||||
.map_err(Error::CreateEvent)?;
|
||||
|
||||
let fd_callbacks: Arc<Mutex<BTreeMap<RawDescriptor, Weak<dyn EventHandler>>>> =
|
||||
let fd_callbacks: Arc<Mutex<BTreeMap<Descriptor, Weak<dyn EventHandler>>>> =
|
||||
Arc::new(Mutex::new(BTreeMap::new()));
|
||||
let poll_ctx: WaitContext<Descriptor> = WaitContext::new()
|
||||
.and_then(|pc| {
|
||||
|
@ -100,7 +98,7 @@ impl EventLoop {
|
|||
}
|
||||
|
||||
let mut locked = fd_callbacks.lock();
|
||||
let weak_handler = match locked.get(&fd) {
|
||||
let weak_handler = match locked.get(&Descriptor(fd)) {
|
||||
Some(cb) => cb.clone(),
|
||||
None => {
|
||||
warn!("callback for fd {} already removed", fd);
|
||||
|
@ -127,7 +125,7 @@ impl EventLoop {
|
|||
|
||||
if remove {
|
||||
let _ = poll_ctx.delete(&event.token);
|
||||
let _ = locked.remove(&fd);
|
||||
let _ = locked.remove(&Descriptor(fd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +152,7 @@ impl EventLoop {
|
|||
}
|
||||
self.handlers
|
||||
.lock()
|
||||
.insert(descriptor.as_raw_descriptor(), handler);
|
||||
.insert(Descriptor(descriptor.as_raw_descriptor()), handler);
|
||||
// This might fail due to epoll syscall. Check epoll_ctl(2).
|
||||
self.poll_ctx
|
||||
.add_for_event(
|
||||
|
@ -176,7 +174,9 @@ impl EventLoop {
|
|||
self.poll_ctx
|
||||
.delete(descriptor)
|
||||
.map_err(Error::WaitContextDeleteDescriptor)?;
|
||||
self.handlers.lock().remove(&descriptor.as_raw_descriptor());
|
||||
self.handlers
|
||||
.lock()
|
||||
.remove(&Descriptor(descriptor.as_raw_descriptor()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
//! Provides helpers that make it easier to process virtio queues on an async executor.
|
||||
|
||||
#![cfg_attr(windows, allow(dead_code))]
|
||||
|
||||
use anyhow::{bail, Context};
|
||||
use async_task::Task;
|
||||
use base::warn;
|
||||
|
|
|
@ -491,7 +491,7 @@ fn run_worker(
|
|||
&guest_address,
|
||||
len,
|
||||
#[cfg(windows)]
|
||||
dynamic_mapping_tube,
|
||||
&dynamic_mapping_tube,
|
||||
#[cfg(unix)]
|
||||
&mem,
|
||||
)
|
||||
|
@ -511,7 +511,7 @@ fn run_worker(
|
|||
&guest_address,
|
||||
len,
|
||||
#[cfg(windows)]
|
||||
dynamic_mapping_tube,
|
||||
&dynamic_mapping_tube,
|
||||
)
|
||||
},
|
||||
);
|
||||
|
@ -571,7 +571,7 @@ fn run_worker(
|
|||
|
||||
/// Virtio device for memory balloon inflation/deflation.
|
||||
pub struct Balloon {
|
||||
command_tube: Tube,
|
||||
command_tube: Option<Tube>,
|
||||
#[cfg(windows)]
|
||||
dynamic_mapping_tube: Option<Tube>,
|
||||
inflate_tube: Option<Tube>,
|
||||
|
@ -616,7 +616,7 @@ impl Balloon {
|
|||
};
|
||||
|
||||
Ok(Balloon {
|
||||
command_tube,
|
||||
command_tube: Some(command_tube),
|
||||
#[cfg(windows)]
|
||||
dynamic_mapping_tube: Some(dynamic_mapping_tube),
|
||||
inflate_tube,
|
||||
|
@ -662,7 +662,10 @@ impl Drop for Balloon {
|
|||
|
||||
impl VirtioDevice for Balloon {
|
||||
fn keep_rds(&self) -> Vec<RawDescriptor> {
|
||||
let mut rds = vec![self.command_tube.as_raw_descriptor()];
|
||||
let mut rds = Vec::new();
|
||||
if let Some(command_tube) = &self.command_tube {
|
||||
rds.push(command_tube.as_raw_descriptor());
|
||||
}
|
||||
if let Some(inflate_tube) = &self.inflate_tube {
|
||||
rds.push(inflate_tube.as_raw_descriptor());
|
||||
}
|
||||
|
@ -723,8 +726,10 @@ impl VirtioDevice for Balloon {
|
|||
|
||||
let state = self.state.clone();
|
||||
|
||||
// TODO(b/222588331): this relies on Tube::try_clone working
|
||||
#[cfg(unix)]
|
||||
#[allow(deprecated)]
|
||||
let command_tube = match self.command_tube.try_clone() {
|
||||
let command_tube = match self.command_tube.as_ref().unwrap().try_clone() {
|
||||
Ok(tube) => tube,
|
||||
Err(e) => {
|
||||
error!("failed to clone command tube {:?}", e);
|
||||
|
@ -732,6 +737,8 @@ impl VirtioDevice for Balloon {
|
|||
}
|
||||
};
|
||||
#[cfg(windows)]
|
||||
let command_tube = self.command_tube.take().unwrap();
|
||||
#[cfg(windows)]
|
||||
let mapping_tube = self.dynamic_mapping_tube.take().unwrap();
|
||||
let inflate_tube = self.inflate_tube.take();
|
||||
let worker_result = thread::Builder::new()
|
||||
|
|
|
@ -34,15 +34,19 @@ pub(in crate::virtio::balloon) async fn send_adjusted_response_async(
|
|||
|
||||
pub(in crate::virtio::balloon) fn send_adjusted_response_if_needed(
|
||||
state: &Arc<AsyncMutex<BalloonState>>,
|
||||
command_tube: &Tube,
|
||||
command_tube: &Option<Tube>,
|
||||
config: virtio_balloon_config,
|
||||
) {
|
||||
let mut state = block_on(state.lock());
|
||||
state.actual_pages = config.actual.to_native();
|
||||
if state.failable_update && state.actual_pages == state.num_pages {
|
||||
state.failable_update = false;
|
||||
if let Err(e) = send_adjusted_response(command_tube, state.num_pages) {
|
||||
error!("Failed to send response {:?}", e);
|
||||
if let Some(ref command_tube) = command_tube {
|
||||
if let Err(e) = send_adjusted_response(command_tube, state.num_pages) {
|
||||
error!("Failed to send response {:?}", e);
|
||||
}
|
||||
} else {
|
||||
panic!("Command tube missing!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@ use std::sync::Arc;
|
|||
|
||||
use balloon_control::BalloonTubeResult;
|
||||
use base::{warn, Tube};
|
||||
use cros_async::{AsyncMutex, AsyncTube};
|
||||
use cros_async::{block_on, sync::Mutex as AsyncMutex, AsyncTube};
|
||||
use vm_control::{VmMemoryRequest, VmMemoryResponse};
|
||||
use vm_memory::{GuestAddress, GuestMemory};
|
||||
use vm_memory::GuestAddress;
|
||||
|
||||
use crate::virtio::balloon::virtio_balloon_config;
|
||||
use crate::virtio::balloon::{BalloonState, VIRTIO_BALLOON_PFN_SHIFT};
|
||||
|
@ -22,12 +22,12 @@ pub(in crate::virtio::balloon) fn send_adjusted_response(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(in crate::virtio::balloon) async fn send_adjusted_response_if_needed(
|
||||
pub(in crate::virtio::balloon) fn send_adjusted_response_if_needed(
|
||||
state: &Arc<AsyncMutex<BalloonState>>,
|
||||
_command_tube: &Tube,
|
||||
_command_tube: &Option<Tube>,
|
||||
config: virtio_balloon_config,
|
||||
) {
|
||||
let mut state = block_on(self.state.lock());
|
||||
let mut state = block_on(state.lock());
|
||||
state.actual_pages = config.actual.to_native();
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,10 @@ pub(in crate::virtio::balloon) fn free_memory(
|
|||
len: u64,
|
||||
dynamic_mapping_tube: &Tube,
|
||||
) {
|
||||
let request = VmMemoryRequest::DynamicallyFreeMemoryRange { guest_address, len };
|
||||
let request = VmMemoryRequest::DynamicallyFreeMemoryRange {
|
||||
guest_address: *guest_address,
|
||||
size: len,
|
||||
};
|
||||
if let Err(e) = dynamic_mapping_tube.send(&request) {
|
||||
warn!(
|
||||
"Failed to send free memory request. Marking pages unused failed: {}, addr={}",
|
||||
|
@ -61,8 +64,15 @@ pub(in crate::virtio::balloon) fn free_memory(
|
|||
}
|
||||
}
|
||||
|
||||
pub(in crate::virtio::balloon) fn reclaim_memory(guest_address: &GuestAddress, len: u64) {
|
||||
let request = VmMemoryRequest::DynamicallyReclaimMemoryRange { guest_address, len };
|
||||
pub(in crate::virtio::balloon) fn reclaim_memory(
|
||||
guest_address: &GuestAddress,
|
||||
len: u64,
|
||||
dynamic_mapping_tube: &Tube,
|
||||
) {
|
||||
let request = VmMemoryRequest::DynamicallyReclaimMemoryRange {
|
||||
guest_address: *guest_address,
|
||||
size: len,
|
||||
};
|
||||
if let Err(e) = dynamic_mapping_tube.send(&request) {
|
||||
warn!(
|
||||
"Failed to send reclaim memory request. Marking pages used failed: {}, addr={}",
|
||||
|
|
|
@ -13,11 +13,11 @@ use std::thread;
|
|||
use std::time::Duration;
|
||||
use std::u32;
|
||||
|
||||
#[cfg(unix)]
|
||||
use base::AsRawDescriptor;
|
||||
use base::Error as SysError;
|
||||
use base::Result as SysResult;
|
||||
use base::{
|
||||
error, info, warn, AsRawDescriptor, Event, EventToken, RawDescriptor, Timer, Tube, WaitContext,
|
||||
};
|
||||
use base::{error, info, warn, Event, EventToken, RawDescriptor, Timer, Tube, WaitContext};
|
||||
use data_model::DataInit;
|
||||
use disk::DiskFile;
|
||||
|
||||
|
@ -140,7 +140,7 @@ fn deserialize_disk_id<'de, D: Deserializer<'de>>(
|
|||
Ok(Some(ret))
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, serde_keyvalue::FromKeyValues)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, serde_keyvalue::FromKeyValues)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct DiskOption {
|
||||
pub path: PathBuf,
|
||||
|
@ -657,6 +657,8 @@ impl VirtioDevice for Block {
|
|||
keep_rds.extend(disk_image.as_raw_descriptors());
|
||||
}
|
||||
|
||||
// TODO: b/143318939 uncomment this when msgOnSocket is ported
|
||||
#[cfg(unix)]
|
||||
if let Some(control_tube) = &self.control_tube {
|
||||
keep_rds.push(control_tube.as_raw_descriptor());
|
||||
}
|
||||
|
@ -1142,6 +1144,24 @@ mod tests {
|
|||
}
|
||||
);
|
||||
|
||||
// io_concurrency
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let params = from_block_arg("/some/path.img,io_concurrency=4").unwrap();
|
||||
assert_eq!(
|
||||
params,
|
||||
DiskOption {
|
||||
path: "/some/path.img".into(),
|
||||
read_only: false,
|
||||
sparse: true,
|
||||
o_direct: false,
|
||||
block_size: 512,
|
||||
id: None,
|
||||
io_concurrency: NonZeroU32::new(4).unwrap(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// id
|
||||
let params = from_block_arg("/some/path.img,id=DISK").unwrap();
|
||||
assert_eq!(
|
||||
|
|
|
@ -146,6 +146,7 @@ struct State {
|
|||
page_mask: u64,
|
||||
// Hot-pluggable PCI endpoints ranges
|
||||
// RangeInclusive: (start endpoint PCI address .. =end endpoint PCI address)
|
||||
#[cfg_attr(windows, allow(dead_code))]
|
||||
hp_endpoints_ranges: Vec<RangeInclusive<u32>>,
|
||||
// All PCI endpoints that attach to certain IOMMU domain
|
||||
// key: endpoint PCI address
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
//! doc, "Arrays of sizes from 0 to 32 (inclusive) implement the Default trait
|
||||
//! if the element type allows it."
|
||||
|
||||
#![cfg_attr(windows, allow(dead_code))]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use data_model::{DataInit, Le16, Le32, Le64};
|
||||
|
|
|
@ -11,16 +11,16 @@ use cros_async::AsyncTube;
|
|||
use crate::virtio::iommu::{Result, State};
|
||||
|
||||
pub(in crate::virtio::iommu) async fn handle_command_tube(
|
||||
state: &Rc<RefCell<State>>,
|
||||
command_tube: AsyncTube,
|
||||
_state: &Rc<RefCell<State>>,
|
||||
_command_tube: AsyncTube,
|
||||
) -> Result<()> {
|
||||
panic!("IOMMU is not supported on Windows");
|
||||
}
|
||||
|
||||
pub(in crate::virtio::iommu) async fn handle_translate_request(
|
||||
state: &Rc<RefCell<State>>,
|
||||
request_tube: Option<AsyncTube>,
|
||||
response_tubes: Option<BTreeMap<u32, AsyncTube>>,
|
||||
_state: &Rc<RefCell<State>>,
|
||||
_request_tube: Option<AsyncTube>,
|
||||
_response_tubes: Option<BTreeMap<u32, AsyncTube>>,
|
||||
) -> Result<()> {
|
||||
// TODO nkgold (b/222588331): the below implementation assures AsyncTube::send is sync, where it
|
||||
// should be async (as it is on Windows). Once that's fixed there's no reason this function
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
mod async_device;
|
||||
mod async_utils;
|
||||
mod balloon;
|
||||
mod descriptor_utils;
|
||||
mod input;
|
||||
mod interrupt;
|
||||
|
@ -27,6 +28,7 @@ pub mod resource_bridge;
|
|||
pub mod snd;
|
||||
pub mod vhost;
|
||||
|
||||
pub use self::balloon::*;
|
||||
pub use self::block::*;
|
||||
pub use self::console::*;
|
||||
pub use self::descriptor_utils::Error as DescriptorError;
|
||||
|
@ -44,7 +46,6 @@ pub use self::virtio_device::*;
|
|||
pub use self::virtio_pci_device::*;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
mod balloon;
|
||||
mod p9;
|
||||
mod pmem;
|
||||
pub mod wl;
|
||||
|
@ -54,7 +55,6 @@ cfg_if::cfg_if! {
|
|||
pub mod gpu;
|
||||
pub mod net;
|
||||
|
||||
pub use self::balloon::*;
|
||||
#[cfg(feature = "gpu")]
|
||||
pub use self::gpu::*;
|
||||
pub use self::iommu::sys::unix::vfio_wrapper;
|
||||
|
|
|
@ -254,6 +254,11 @@ impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
|
|||
|
||||
#[derive(Clone)]
|
||||
/// A virtio queue's parameters.
|
||||
///
|
||||
/// WARNING: it is NOT safe to clone and then use n>1 Queue(s) to interact with the same virtqueue.
|
||||
/// That will prevent descriptor index tracking from being accurate, which can cause incorrect
|
||||
/// interrupt masking.
|
||||
/// TODO(b/201119859) drop Clone from this struct.
|
||||
pub struct Queue {
|
||||
/// The maximal size in elements offered by the device
|
||||
pub max_size: u16,
|
||||
|
@ -773,6 +778,7 @@ mod tests {
|
|||
use super::super::Interrupt;
|
||||
use super::*;
|
||||
use crate::IrqLevelEvent;
|
||||
use memoffset::offset_of;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::Arc;
|
||||
|
@ -879,10 +885,8 @@ mod tests {
|
|||
10,
|
||||
);
|
||||
|
||||
// Calculating the offset of used_event within Avail structure
|
||||
#[allow(deref_nullptr)]
|
||||
let used_event_offset: u64 =
|
||||
unsafe { &(*(::std::ptr::null::<Avail>())).used_event as *const _ as u64 };
|
||||
// Offset of used_event within Avail structure
|
||||
let used_event_offset = offset_of!(Avail, used_event) as u64;
|
||||
let used_event_address = GuestAddress(AVAIL_OFFSET + used_event_offset);
|
||||
|
||||
// Assume driver submit 0x100 req to device,
|
||||
|
@ -955,10 +959,8 @@ mod tests {
|
|||
10,
|
||||
);
|
||||
|
||||
// Calculating the offset of used_event within Avail structure
|
||||
#[allow(deref_nullptr)]
|
||||
let used_event_offset: u64 =
|
||||
unsafe { &(*(::std::ptr::null::<Avail>())).used_event as *const _ as u64 };
|
||||
// Offset of used_event within Avail structure
|
||||
let used_event_offset = offset_of!(Avail, used_event) as u64;
|
||||
let used_event_address = GuestAddress(AVAIL_OFFSET + used_event_offset);
|
||||
|
||||
// Assume driver submit 0x100 req to device,
|
||||
|
|
|
@ -81,7 +81,7 @@ pub struct Sound {
|
|||
|
||||
impl VirtioDevice for Sound {
|
||||
fn keep_rds(&self) -> Vec<RawDescriptor> {
|
||||
self.vios_client.keep_fds()
|
||||
self.vios_client.keep_rds()
|
||||
}
|
||||
|
||||
fn device_type(&self) -> DeviceType {
|
||||
|
|
|
@ -173,7 +173,7 @@ impl ShmStreamSource<base::Error> for VioSShmStreamSource {
|
|||
/// This list helps users of the ShmStreamSource enter Linux jails without
|
||||
/// closing needed file descriptors.
|
||||
fn keep_fds(&self) -> Vec<RawDescriptor> {
|
||||
self.vios_client.keep_fds()
|
||||
self.vios_client.keep_rds()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ use data_model::{DataInit, VolatileMemory, VolatileMemoryError, VolatileSlice};
|
|||
use std::collections::{HashMap, VecDeque};
|
||||
use std::fs::File;
|
||||
use std::io::{Error as IOError, ErrorKind as IOErrorKind, IoSliceMut, Seek, SeekFrom};
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::path::Path;
|
||||
use std::sync::mpsc::{channel, Receiver, RecvError, Sender};
|
||||
use std::sync::Arc;
|
||||
|
@ -447,14 +447,14 @@ impl VioSClient {
|
|||
}
|
||||
|
||||
/// Get a list of file descriptors used by the implementation.
|
||||
pub fn keep_fds(&self) -> Vec<RawFd> {
|
||||
let control_fd = self.control_socket.lock().as_raw_fd();
|
||||
let event_fd = self.event_socket.as_raw_fd();
|
||||
pub fn keep_rds(&self) -> Vec<RawDescriptor> {
|
||||
let control_desc = self.control_socket.lock().as_raw_descriptor();
|
||||
let event_desc = self.event_socket.as_raw_descriptor();
|
||||
let recv_event = self.recv_event.as_raw_descriptor();
|
||||
let event_notifier = self.event_notifier.as_raw_descriptor();
|
||||
let mut ret = vec![control_fd, event_fd, recv_event, event_notifier];
|
||||
ret.append(&mut self.tx.keep_fds());
|
||||
ret.append(&mut self.rx.keep_fds());
|
||||
let mut ret = vec![control_desc, event_desc, recv_event, event_notifier];
|
||||
ret.append(&mut self.tx.keep_rds());
|
||||
ret.append(&mut self.rx.keep_rds());
|
||||
ret
|
||||
}
|
||||
|
||||
|
@ -747,7 +747,7 @@ impl IoBufferQueue {
|
|||
seq_socket_send(&self.socket, msg)
|
||||
}
|
||||
|
||||
fn keep_fds(&self) -> Vec<RawDescriptor> {
|
||||
fn keep_rds(&self) -> Vec<RawDescriptor> {
|
||||
vec![
|
||||
self.file.as_raw_descriptor(),
|
||||
self.socket.as_raw_descriptor(),
|
||||
|
|
|
@ -53,8 +53,8 @@ fn open_disk_file(disk_option: &DiskOption, take_write_lock: bool) -> anyhow::Re
|
|||
.context("Failed to open disk file")
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
#[argh(description = "")]
|
||||
#[derive(FromArgs, Debug)]
|
||||
#[argh(subcommand, name = "block", description = "")]
|
||||
pub struct Options {
|
||||
#[argh(
|
||||
option,
|
||||
|
@ -64,19 +64,7 @@ pub struct Options {
|
|||
bootstrap: usize,
|
||||
}
|
||||
|
||||
pub fn start_device(program_name: &str, args: &[&str]) -> anyhow::Result<()> {
|
||||
let opts = match Options::from_args(&[program_name], args) {
|
||||
Ok(opts) => opts,
|
||||
Err(e) => {
|
||||
if e.status.is_err() {
|
||||
bail!(e.output);
|
||||
} else {
|
||||
println!("{}", e.output);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
pub fn start_device(opts: Options) -> anyhow::Result<()> {
|
||||
tracing::init();
|
||||
|
||||
let raw_transport_tube = opts.bootstrap as RawDescriptor;
|
||||
|
|
|
@ -90,6 +90,7 @@ use {base::clear_fd_flags, std::os::unix::io::AsRawFd};
|
|||
pub struct CallEvent(Event);
|
||||
|
||||
impl CallEvent {
|
||||
#[cfg_attr(windows, allow(dead_code))]
|
||||
pub fn into_inner(self) -> Event {
|
||||
self.0
|
||||
}
|
||||
|
@ -226,6 +227,7 @@ impl Vring {
|
|||
}
|
||||
|
||||
/// Performs the run loop for an already-constructed request handler.
|
||||
#[cfg_attr(windows, allow(dead_code))]
|
||||
pub async fn run_handler<S, E>(mut req_handler: SlaveReqHandler<S, E>, ex: &Executor) -> Result<()>
|
||||
where
|
||||
S: VhostUserSlaveReqHandler,
|
||||
|
@ -791,11 +793,14 @@ impl SharedMemoryMapper for VhostShmemMapper {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[cfg(unix)]
|
||||
use std::sync::mpsc::channel;
|
||||
#[cfg(unix)]
|
||||
use std::sync::Barrier;
|
||||
|
||||
use anyhow::{anyhow, bail};
|
||||
use data_model::DataInit;
|
||||
#[cfg(unix)]
|
||||
use tempfile::{Builder, TempDir};
|
||||
|
||||
use crate::virtio::vhost::user::vmm::VhostUserHandler;
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
use std::fs::File;
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use base::named_pipes::{BlockingMode, FramingMode, PipeConnection};
|
||||
|
@ -13,15 +11,10 @@ use cros_async::{EventAsync, Executor};
|
|||
use futures::FutureExt;
|
||||
use futures::{pin_mut, select};
|
||||
use tube_transporter::{TubeTransferDataList, TubeTransporterReader};
|
||||
use vm_memory::GuestMemory;
|
||||
use vmm_vhost::{Protocol, SlaveReqHandler};
|
||||
use vmm_vhost::SlaveReqHandler;
|
||||
|
||||
use crate::virtio::vhost::user::device::{
|
||||
handler::{
|
||||
CallEvent, DeviceRequestHandler, MappingInfo, VhostResult, VhostUserBackend,
|
||||
VhostUserMemoryRegion, VhostUserRegularOps,
|
||||
},
|
||||
listener::{VhostUserListener, VhostUserListenerTrait},
|
||||
use crate::virtio::vhost::user::device::handler::{
|
||||
CallEvent, DeviceRequestHandler, VhostUserRegularOps,
|
||||
};
|
||||
|
||||
pub type Doorbell = CallEvent;
|
||||
|
|
|
@ -19,17 +19,17 @@ pub struct VhostUserListener;
|
|||
|
||||
impl VhostUserListenerTrait for VhostUserListener {
|
||||
fn new(
|
||||
path: &str,
|
||||
max_num_queues: usize,
|
||||
keep_rds: Option<&mut Vec<RawDescriptor>>,
|
||||
_path: &str,
|
||||
_max_num_queues: usize,
|
||||
_keep_rds: Option<&mut Vec<RawDescriptor>>,
|
||||
) -> anyhow::Result<Self> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn run_backend(
|
||||
self,
|
||||
backend: Box<dyn VhostUserBackend>,
|
||||
ex: &Executor,
|
||||
_backend: Box<dyn VhostUserBackend>,
|
||||
_ex: &Executor,
|
||||
) -> Pin<Box<dyn Future<Output = anyhow::Result<()>>>> {
|
||||
todo!()
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ cfg_if::cfg_if! {
|
|||
#[cfg(feature = "slirp")]
|
||||
mod net;
|
||||
#[cfg(feature = "slirp")]
|
||||
pub use net::run_net_device;
|
||||
pub use net::{run_net_device, Options as NetOptions};
|
||||
#[cfg(feature = "slirp")]
|
||||
pub use net::sys::windows::NetBackendConfig;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::virtio;
|
|||
use crate::virtio::net::MAX_BUFFER_SIZE;
|
||||
use crate::virtio::net::{process_rx, NetError};
|
||||
use crate::virtio::vhost::user::device::handler::sys::windows::read_from_tube_transporter;
|
||||
use crate::virtio::vhost::user::device::handler::{DeviceRequestHandler, Doorbell};
|
||||
use crate::virtio::vhost::user::device::handler::{sys::Doorbell, DeviceRequestHandler};
|
||||
use crate::virtio::vhost::user::device::net::{
|
||||
run_ctrl_queue, run_tx_queue, NetBackend, NET_EXECUTOR,
|
||||
};
|
||||
|
@ -93,7 +93,7 @@ async fn run_rx_queue<T: TapT>(
|
|||
&mut overlapped_wrapper,
|
||||
);
|
||||
if needs_interrupt {
|
||||
call_evt.lock().signal_used_queue(queue.vector);
|
||||
call_evt.lock().signal_used_queue(queue.vector());
|
||||
}
|
||||
|
||||
// There aren't any RX descriptors available for us to write packets to. Wait for the guest
|
||||
|
@ -127,7 +127,7 @@ pub(in crate::virtio::vhost::user::device::net) fn start_queue<T: 'static + Into
|
|||
let overlapped_wrapper =
|
||||
OverlappedWrapper::new(true).expect("Failed to create overlapped wrapper");
|
||||
|
||||
super::NET_EXECUTOR.with(|ex| {
|
||||
super::super::NET_EXECUTOR.with(|ex| {
|
||||
// Safe because the executor is initialized in main() below.
|
||||
let ex = ex.get().expect("Executor not initialized");
|
||||
|
||||
|
@ -143,11 +143,13 @@ pub(in crate::virtio::vhost::user::device::net) fn start_queue<T: 'static + Into
|
|||
let tap = ex
|
||||
.async_from(tap)
|
||||
.context("failed to create async tap device")?;
|
||||
let read_notifier = overlapped_wrapper
|
||||
.get_h_event_ref()
|
||||
.unwrap()
|
||||
.try_clone()
|
||||
.unwrap();
|
||||
let read_notifier = base::Event(
|
||||
overlapped_wrapper
|
||||
.get_h_event_ref()
|
||||
.unwrap()
|
||||
.try_clone()
|
||||
.unwrap(),
|
||||
);
|
||||
let read_notifier = EventAsync::new_without_reset(read_notifier, &ex)
|
||||
.context("failed to create async read notifier")?;
|
||||
|
||||
|
@ -214,9 +216,9 @@ pub struct NetBackendConfig {
|
|||
pub slirp_kill_event: Event,
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
#[argh(description = "")]
|
||||
struct Options {
|
||||
#[derive(FromArgs, Debug)]
|
||||
#[argh(subcommand, name = "net", description = "")]
|
||||
pub struct Options {
|
||||
#[argh(
|
||||
option,
|
||||
description = "pipe handle end for Tube Transporter",
|
||||
|
@ -229,19 +231,7 @@ struct Options {
|
|||
compile_error!("vhost-user net device requires slirp feature on Windows.");
|
||||
|
||||
#[cfg(feature = "slirp")]
|
||||
pub fn run_device(program_name: &str, args: &[&str]) -> anyhow::Result<()> {
|
||||
let opts = match Options::from_args(&[program_name], args) {
|
||||
Ok(opts) => opts,
|
||||
Err(e) => {
|
||||
if e.status.is_err() {
|
||||
bail!(e.output);
|
||||
} else {
|
||||
println!("{}", e.output);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
pub fn start_device(opts: Options) -> anyhow::Result<()> {
|
||||
// Get the Tubes from the TubeTransporter. Then get the "Config" from the bootstrap_tube
|
||||
// which will contain slirp settings.
|
||||
let raw_transport_tube = opts.bootstrap as RawDescriptor;
|
||||
|
@ -253,7 +243,7 @@ pub fn run_device(program_name: &str, args: &[&str]) -> anyhow::Result<()> {
|
|||
|
||||
let startup_args: CommonChildStartupArgs =
|
||||
bootstrap_tube.recv::<CommonChildStartupArgs>().unwrap();
|
||||
common_child_setup(startup_args).unwrap();
|
||||
let _child_cleanup = common_child_setup(startup_args).unwrap();
|
||||
|
||||
let net_backend_config = bootstrap_tube.recv::<NetBackendConfig>().unwrap();
|
||||
|
||||
|
|
|
@ -198,7 +198,7 @@ impl VirtioDevice for Vsock {
|
|||
};
|
||||
self.kill_evt = Some(self_kill_evt);
|
||||
let host_guid = self.host_guid.clone();
|
||||
let guest_cid = self.guest_cid.clone();
|
||||
let guest_cid = self.guest_cid;
|
||||
let worker_result = thread::Builder::new()
|
||||
.name("userspace_virtio_vsock".to_string())
|
||||
.spawn(move || {
|
||||
|
@ -351,7 +351,7 @@ impl Worker {
|
|||
VsockError::CloneDescriptor(e)
|
||||
})
|
||||
.map(base::Event)?;
|
||||
let evt_async = EventAsync::new(h_evt, &ex).map_err(|e| {
|
||||
let evt_async = EventAsync::new(h_evt, ex).map_err(|e| {
|
||||
error!("Could not create EventAsync.");
|
||||
VsockError::CreateEventAsync(e)
|
||||
})?;
|
||||
|
@ -362,7 +362,7 @@ impl Worker {
|
|||
error!("Could not clone connection_event.");
|
||||
VsockError::CloneDescriptor(e)
|
||||
})?;
|
||||
let connection_evt_async = EventAsync::new(connection_evt_clone, &ex).map_err(|e| {
|
||||
let connection_evt_async = EventAsync::new(connection_evt_clone, ex).map_err(|e| {
|
||||
error!("Could not create EventAsync.");
|
||||
VsockError::CreateEventAsync(e)
|
||||
})?;
|
||||
|
@ -428,7 +428,7 @@ impl Worker {
|
|||
|
||||
let pipe_connection = &mut connection.pipe;
|
||||
let overlapped = &mut connection.overlapped;
|
||||
let guest_port = connection.guest_port.clone();
|
||||
let guest_port = connection.guest_port;
|
||||
let buffer = &mut connection.buffer;
|
||||
|
||||
match overlapped.get_h_event_ref() {
|
||||
|
@ -533,19 +533,18 @@ impl Worker {
|
|||
break;
|
||||
}
|
||||
|
||||
let mut data = vec![0 as u8; len];
|
||||
let mut data = vec![0_u8; len];
|
||||
if len > 0 {
|
||||
if let Err(e) = reader.read_exact(&mut data) {
|
||||
error!("vosck: failed to read data from tx packet: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
match process_packets_queue.send((header, data)).await {
|
||||
Err(e) => error!(
|
||||
if let Err(e) = process_packets_queue.send((header, data)).await {
|
||||
error!(
|
||||
"Error while sending packet to queue, dropping packet: {:?}",
|
||||
e
|
||||
),
|
||||
_ => {}
|
||||
)
|
||||
};
|
||||
queue.add_used(&self.mem, index, 0);
|
||||
queue.trigger_interrupt(&self.mem, &*self.interrupt.borrow());
|
||||
|
@ -649,16 +648,15 @@ impl Worker {
|
|||
buffer,
|
||||
// The connection has just been made, so we haven't received
|
||||
// anything yet.
|
||||
recv_cnt: 0 as usize,
|
||||
prev_recv_cnt: 0 as usize,
|
||||
tx_cnt: 0 as usize,
|
||||
recv_cnt: 0_usize,
|
||||
prev_recv_cnt: 0_usize,
|
||||
tx_cnt: 0_usize,
|
||||
is_buffer_full: false,
|
||||
};
|
||||
self.connections.write().unwrap().insert(port, connection);
|
||||
self.connection_event
|
||||
.write(0) // 0 is arbitrary
|
||||
.expect(&format!(
|
||||
"Failed to signal new connection event for vsock port {}.", port));
|
||||
.unwrap_or_else(|_| panic!("Failed to signal new connection event for vsock port {}.", port));
|
||||
true
|
||||
}
|
||||
Err(e) => {
|
||||
|
@ -801,7 +799,7 @@ impl Worker {
|
|||
let (send, recv) = mpsc::channel(CHANNEL_SIZE);
|
||||
let event_async = EventAsync::new(
|
||||
rx_queue_evt.try_clone().expect("Failed to clone event"),
|
||||
&ex,
|
||||
ex,
|
||||
)
|
||||
.expect("Failed to set up the rx queue event");
|
||||
futures.push(
|
||||
|
@ -817,11 +815,8 @@ impl Worker {
|
|||
send
|
||||
});
|
||||
// Try to send the packet. Do not block other ports if the queue is full.
|
||||
match queue.try_send(packet) {
|
||||
Err(e) => {
|
||||
error!("Error sending packet to queue, dropping packet: {:?}", e)
|
||||
}
|
||||
_ => {}
|
||||
if let Err(e) = queue.try_send(packet) {
|
||||
error!("Error sending packet to queue, dropping packet: {:?}", e)
|
||||
}
|
||||
}
|
||||
SelectResult::Finished(_) => {
|
||||
|
@ -846,7 +841,7 @@ impl Worker {
|
|||
) -> PortPair {
|
||||
while let Some((header, mut data)) = packet_recv_queue.next().await {
|
||||
if !self
|
||||
.handle_tx_packet(header, &mut data, send_queue, &mut rx_queue_evt, ex)
|
||||
.handle_tx_packet(header, &data, send_queue, &mut rx_queue_evt, ex)
|
||||
.await
|
||||
{
|
||||
packet_recv_queue.close();
|
||||
|
@ -1284,7 +1279,7 @@ impl Worker {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_pipe_name(guid: &String, pipe: u32) -> String {
|
||||
fn get_pipe_name(guid: &str, pipe: u32) -> String {
|
||||
format!("\\\\.\\pipe\\{}\\vsock-{}", guid, pipe)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue