devices: vvu: Add uuid argument for vvu-proxy

Add optional `uuid` argument to `--vvu-proxy` so a user can specify a
UUID that will be stored in virtio_vhost_user_config space so that the
guest can read the value by reading /sys/devices/pci*/*/resources.
We can use this value to allow the guest to know the socket path that
the VVU proxy device uses.

BUG=b:215472603
TEST=pcimem /sys/device/pci.../resource0 0x2008 b*16,
     where 0x2008 == (DEVICE_CONFIG_BAR_OFFSET + offset in vvu config)

Change-Id: I99f1d988cb793b44682ddf927837139dabd42cf8
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3516669
Reviewed-by: Alexandre Courbot <acourbot@chromium.org>
Auto-Submit: Keiichi Watanabe <keiichiw@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Keiichi Watanabe <keiichiw@chromium.org>
This commit is contained in:
Keiichi Watanabe 2022-03-10 21:28:44 +09:00 committed by Chromeos LUCI
parent 04b9ce6d8a
commit 15b4769df5
6 changed files with 59 additions and 26 deletions

View file

@ -175,6 +175,7 @@ serde_json = "*"
sync = { path = "common/sync" }
tempfile = "3"
thiserror = { version = "1.0.20" }
uuid = { version = "0.8.2" }
vhost = { path = "vhost" }
vm_control = { path = "vm_control" }
acpi_tables = { path = "acpi_tables" }

View file

@ -61,6 +61,7 @@ system_api = { version = "*", optional = true }
thiserror = "1.0.20"
tpm2 = { path = "../tpm2", optional = true }
usb_util = { path = "../usb_util" }
uuid = { version = "0.8.2" }
vfio_sys = { path = "../vfio_sys" }
vhost = { path = "../vhost" }
vmm_vhost = { path = "../third_party/vmm_vhost", features = ["vmm", "device", "vfio-device"] }

View file

@ -22,6 +22,7 @@ use base::{
use data_model::{DataInit, Le32};
use libc::{recv, MSG_DONTWAIT, MSG_PEEK};
use resources::Alloc;
use uuid::Uuid;
use vm_control::{VmMemoryRequest, VmMemoryResponse};
use vm_memory::GuestMemory;
use vmm_vhost::{
@ -993,6 +994,7 @@ impl VirtioVhostUser {
listener: UnixListener,
main_process_tube: Tube,
pci_address: Option<PciAddress>,
uuid: Option<Uuid>,
) -> Result<VirtioVhostUser> {
Ok(VirtioVhostUser {
base_features,
@ -1000,7 +1002,7 @@ impl VirtioVhostUser {
config: VirtioVhostUserConfig {
status: Le32::from(0),
max_vhost_queues: Le32::from(MAX_VHOST_DEVICE_QUEUES as u32),
uuid: [0; CONFIG_UUID_SIZE],
uuid: *uuid.unwrap_or_default().as_bytes(),
},
kill_evt: None,
worker_thread: None,

View file

@ -39,6 +39,7 @@ use hypervisor::ProtectionType;
use libc::{getegid, geteuid};
#[cfg(feature = "gpu")]
use platform::GpuRenderServerParameters;
use uuid::Uuid;
use vm_control::BatteryType;
static KVM_PATH: &str = "/dev/kvm";
@ -89,6 +90,7 @@ pub struct VhostUserWlOption {
pub struct VvuOption {
pub socket: PathBuf,
pub addr: Option<PciAddress>,
pub uuid: Option<Uuid>,
}
/// A bind mount for directories in the plugin process.

View file

@ -228,6 +228,7 @@ pub fn create_vvu_proxy_device(cfg: &Config, opt: &VvuOption, tube: Tube) -> Dev
listener,
tube,
opt.addr,
opt.uuid,
)
.context("failed to create VVU proxy device")?;

View file

@ -61,6 +61,7 @@ use disk::{
create_composite_disk, create_disk_file, create_zero_filler, ImagePartitionType, PartitionInfo,
};
use hypervisor::ProtectionType;
use uuid::Uuid;
use vm_control::{
client::{
do_modify_battery, do_usb_attach, do_usb_detach, do_usb_list, handle_request, vms_request,
@ -2276,32 +2277,56 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
cfg.stub_pci_devices.push(parse_stub_pci_parameters(value)?);
}
"vvu-proxy" => {
let opts: Vec<_> = value.unwrap().split(',').collect();
let opts: Vec<_> = value.unwrap().splitn(2, ',').collect();
let socket = PathBuf::from(opts[0]);
let addr = match opts.get(1) {
Some(opt) => {
let kvs = argument::parse_key_value_options("vvu-proxy", opt, ',')
.collect::<Vec<_>>();
if kvs.len() != 1 || kvs[0].key() != "addr" {
return Err(argument::Error::InvalidValue {
value: opt.to_string(),
expected: String::from(
"Please specify PCI address for VVU: addr=BUS:DEVICE.FUNCTION",
),
});
}
let pci_address = kvs[0].value()?;
Some(PciAddress::from_string(pci_address).map_err(|e| {
argument::Error::InvalidValue {
value: pci_address.to_string(),
expected: format!("vvu-proxy PCI address: {}", e),
}
})?)
}
None => None,
let mut vvu_opt = VvuOption {
socket,
addr: None,
uuid: Default::default(),
};
cfg.vvu_proxy.push(VvuOption { socket, addr });
if let Some(kvs) = opts.get(1) {
for kv in argument::parse_key_value_options("vvu-proxy", kvs, ',') {
match kv.key() {
"addr" => {
let pci_address = kv.value()?;
if vvu_opt.addr.is_some() {
return Err(argument::Error::TooManyArguments(
"`addr` already given".to_owned(),
));
}
vvu_opt.addr =
Some(PciAddress::from_string(pci_address).map_err(|e| {
argument::Error::InvalidValue {
value: pci_address.to_string(),
expected: format!("vvu-proxy PCI address: {}", e),
}
})?);
}
"uuid" => {
let value = kv.value()?;
if vvu_opt.uuid.is_some() {
return Err(argument::Error::TooManyArguments(
"`uuid` already given".to_owned(),
));
}
let uuid = Uuid::parse_str(value).map_err(|e| {
argument::Error::InvalidValue {
value: value.to_string(),
expected: format!("invalid UUID is given for vvu-proxy: {}", e),
}
})?;
vvu_opt.uuid = Some(uuid);
}
_ => {
kv.invalid_key_err();
}
}
}
}
cfg.vvu_proxy.push(vvu_opt);
}
"coiommu" => {
let mut params: devices::CoIommuParameters = Default::default();
@ -2777,9 +2802,10 @@ 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[,addr=DOMAIN:BUS:DEVICE.FUNCTION]", "Socket path for the Virtio Vhost User proxy device.
Argument::value("vvu-proxy", "SOCKET_PATH[,addr=DOMAIN:BUS:DEVICE.FUNCTION,uuid=UUID]", "Socket path for the Virtio Vhost User proxy device.
Parameters
addr=BUS:DEVICE.FUNCTION - PCI address that the proxy device will be allocated"),
addr=BUS:DEVICE.FUNCTION - PCI address that the proxy device will be allocated (default: automatically allocated)
uuid=UUID - UUID which will be stored in VVU PCI config space that is readable from guest userspace"),
#[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")]