crosvm: vvu: proxy: Implement instantiating a VVU proxy device

This change adds a command line parameter for instantiating a VVU proxy
device.

BUG=b:194136484
TEST=Test with sibling VM with Vhost master connecting to a device VM.

Change-Id: I5ff56e6f1ebca5a7078eca3d951ddbfd411d14fc
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3290381
Reviewed-by: Chirantan Ekbote
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Abhishek Bhardwaj <abhishekbh@chromium.org>
This commit is contained in:
Abhishek Bhardwaj 2021-11-01 15:52:23 -07:00 committed by Commit Bot
parent d98f01af14
commit 103c1b75b9
5 changed files with 55 additions and 17 deletions

View file

@ -14,7 +14,6 @@ use std::fs::File;
use std::io::Write;
use std::os::unix::io::AsRawFd;
use std::os::unix::net::UnixListener;
use std::path::{Path, PathBuf};
use std::thread;
use base::{error, info, AsRawDescriptor, Event, EventType, PollToken, RawDescriptor, WaitContext};
@ -548,8 +547,11 @@ struct ActivateParams {
}
pub struct VirtioVhostUser {
// Path to open and accept a socket connection from the Vhost-user sibling.
sibling_socket_path: PathBuf,
base_features: u64,
// Bound socket waiting to accept a socket connection from the Vhost-user
// sibling.
listener: UnixListener,
// Device configuration.
config: VirtioVhostUserConfig,
@ -571,9 +573,10 @@ pub struct VirtioVhostUser {
}
impl VirtioVhostUser {
pub fn new(sibling_socket_path: &Path) -> Result<VirtioVhostUser> {
pub fn new(base_features: u64, listener: UnixListener) -> Result<VirtioVhostUser> {
Ok(VirtioVhostUser {
sibling_socket_path: sibling_socket_path.to_owned(),
base_features,
listener,
config: VirtioVhostUserConfig {
status: Le32::from(0),
max_vhost_queues: Le32::from(MAX_VHOST_DEVICE_QUEUES as u32),
@ -669,15 +672,7 @@ impl VirtioVhostUser {
};
self.kill_evt = Some(self_kill_evt);
let listener = match UnixListener::bind(&self.sibling_socket_path) {
Ok(listener) => listener,
Err(e) => {
error!("failed to bind listener: {}", e);
return;
}
};
let socket = match listener.accept() {
let socket = match self.listener.accept() {
Ok((socket, _)) => socket,
Err(e) => {
error!("failed to accept connection: {}", e);
@ -740,13 +735,15 @@ impl Drop for VirtioVhostUser {
}
impl VirtioDevice for VirtioVhostUser {
fn keep_rds(&self) -> Vec<RawDescriptor> {
let mut rds = Vec::new();
fn features(&self) -> u64 {
self.base_features
}
fn keep_rds(&self) -> Vec<RawDescriptor> {
let mut rds = vec![self.listener.as_raw_fd()];
if let Some(kill_evt) = &self.kill_evt {
rds.push(kill_evt.as_raw_descriptor());
}
rds
}

View file

@ -0,0 +1,14 @@
# Copyright 2022 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@include /usr/share/policy/crosvm/common_device.policy
accept4: 1
bind: 1
fstat: 1
getdents64: 1
ioctl: arg1 == SIOCGIFFLAGS || arg1 == SIOCSIFFLAGS || arg1 == TCGETS
prctl: arg0 == PR_SET_NAME
socket: arg0 == AF_UNIX
socketpair: 1

View file

@ -405,6 +405,7 @@ pub struct Config {
pub no_legacy: bool,
pub host_cpu_topology: bool,
pub stub_pci_devices: Vec<StubPciParameters>,
pub vvu_proxy: Vec<VhostUserOption>,
}
impl Default for Config {
@ -492,6 +493,7 @@ impl Default for Config {
vhost_user_snd: Vec::new(),
vhost_user_vsock: Vec::new(),
vhost_user_wl: Vec::new(),
vvu_proxy: Vec::new(),
#[cfg(feature = "direct")]
direct_pmio: None,
#[cfg(feature = "direct")]

View file

@ -12,6 +12,7 @@ use std::io::stdin;
use std::iter;
use std::mem;
use std::net::Ipv4Addr;
use std::os::unix::net::UnixListener;
use std::os::unix::{io::FromRawFd, net::UnixStream, prelude::OpenOptionsExt};
use std::path::{Path, PathBuf};
use std::str;
@ -32,6 +33,7 @@ use devices::serial_device::{SerialHardware, SerialParameters};
use devices::vfio::{VfioCommonSetup, VfioCommonTrait};
#[cfg(feature = "audio_cras")]
use devices::virtio::snd::cras_backend::Parameters as CrasSndParameters;
use devices::virtio::vhost::user::proxy::VirtioVhostUser;
#[cfg(feature = "audio")]
use devices::virtio::vhost::user::vmm::Snd as VhostUserSnd;
use devices::virtio::vhost::user::vmm::{
@ -330,6 +332,21 @@ fn create_vhost_user_snd_device(cfg: &Config, option: &VhostUserOption) -> Devic
})
}
fn create_vvu_proxy_device(cfg: &Config, opt: &VhostUserOption) -> DeviceResult {
let listener = UnixListener::bind(&opt.socket).map_err(|e| {
error!("failed to bind listener for vvu proxy device: {}", e);
e
})?;
let dev = VirtioVhostUser::new(virtio::base_features(cfg.protected_vm), listener)
.context("failed to create VVU proxy device")?;
Ok(VirtioDeviceStub {
dev: Box::new(dev),
jail: simple_jail(cfg, "vvu_proxy_device")?,
})
}
fn create_rng_device(cfg: &Config) -> DeviceResult {
let dev = virtio::Rng::new(virtio::base_features(cfg.protected_vm))
.context("failed to set up rng")?;
@ -1531,6 +1548,10 @@ fn create_virtio_devices(
)?);
}
for opt in &cfg.vvu_proxy {
devs.push(create_vvu_proxy_device(cfg, opt)?);
}
#[cfg_attr(not(feature = "gpu"), allow(unused_mut))]
let mut resource_bridges = Vec::<Tube>::new();

View file

@ -2158,6 +2158,9 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
"stub-pci-device" => {
cfg.stub_pci_devices.push(parse_stub_pci_parameters(value)?);
}
"vvu-proxy" => cfg.vvu_proxy.push(VhostUserOption {
socket: PathBuf::from(value.unwrap()),
}),
"help" => return Err(argument::Error::PrintHelp),
_ => unreachable!(),
}
@ -2476,6 +2479,7 @@ iommu=on|off - indicates whether to enable virtio IOMMU for this device"),
Argument::value("vhost-user-wl", "SOCKET_PATH:TUBE_PATH", "Paths to a vhost-user socket for wayland and a Tube socket for additional wayland-specific messages"),
Argument::value("vhost-user-fs", "SOCKET_PATH:TAG",
"Path to a socket path for vhost-user fs, and tag for the shared dir"),
Argument::value("vvu-proxy", "SOCKET_PATH", "Socket path for the Virtio Vhost User proxy device"),
#[cfg(feature = "direct")]
Argument::value("direct-pmio", "PATH@RANGE[,RANGE[,...]]", "Path and ranges for direct port mapped I/O access. RANGE may be decimal or hex (starting with 0x)."),
#[cfg(feature = "direct")]