From a201fd46bd0549655b85bcd6e609fdabd1add837 Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Tue, 31 Mar 2020 09:39:11 +0000 Subject: make remote wayland device optional --- devices/src/virtio/controller.rs | 2 + devices/src/virtio/wl.rs | 6 +- src/crosvm.rs | 2 + src/linux.rs | 156 +++++++++++++++++++-------------------- src/main.rs | 18 ++++- src/wl.rs | 15 +++- 6 files changed, 112 insertions(+), 87 deletions(-) diff --git a/devices/src/virtio/controller.rs b/devices/src/virtio/controller.rs index be7228a..7500164 100644 --- a/devices/src/virtio/controller.rs +++ b/devices/src/virtio/controller.rs @@ -668,6 +668,8 @@ pub struct Controller { } impl Controller { + /// Construct a controller, and initialize (but don't activate) + /// the remote device. pub fn create( device_params: Params, memory_params: MemoryParams, diff --git a/devices/src/virtio/wl.rs b/devices/src/virtio/wl.rs index 6671693..6a412f9 100644 --- a/devices/src/virtio/wl.rs +++ b/devices/src/virtio/wl.rs @@ -30,7 +30,7 @@ use std::collections::btree_map::Entry; use std::collections::{BTreeMap as Map, BTreeSet as Set, VecDeque}; -use std::convert::From; +use std::convert::{From, Infallible}; use std::error::Error as StdError; use std::fmt::{self, Display}; use std::fs::File; @@ -1628,9 +1628,9 @@ impl<'de> DeserializeWithFds<'de> for Params { impl VirtioDeviceNew for Wl { type Params = Params; - type Error = (); + type Error = Infallible; - fn new(params: Params) -> Result { + fn new(params: Params) -> Result { let Params { wayland_paths, vm_socket, diff --git a/src/crosvm.rs b/src/crosvm.rs index 1ea7e0d..e6e7268 100644 --- a/src/crosvm.rs +++ b/src/crosvm.rs @@ -181,6 +181,7 @@ pub struct Config { pub tap_fd: Vec, pub cid: Option, pub wayland_socket_paths: BTreeMap, + pub remote_wayland_device_socket_path: Option, pub wayland_dmabuf: bool, pub x_display: Option, pub shared_dirs: Vec, @@ -235,6 +236,7 @@ impl Default for Config { gpu_parameters: None, software_tpm: false, wayland_socket_paths: BTreeMap::new(), + remote_wayland_device_socket_path: None, wayland_dmabuf: false, x_display: None, display_window_keyboard: false, diff --git a/src/linux.rs b/src/linux.rs index a416a3e..ce177e0 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -31,7 +31,7 @@ use acpi_tables::sdt::SDT; #[cfg(feature = "gpu")] use devices::virtio::EventDevice; -use devices::virtio::{self, Console, Params, VirtioDevice}; +use devices::virtio::{self, Console, Params, VirtioDevice, VirtioDeviceNew}; use devices::{ self, Ac97Backend, Ac97Dev, Bus, HostBackendDeviceProvider, PciDevice, VfioContainer, VfioDevice, VfioPciDevice, VirtioPciDevice, XhciController, @@ -87,9 +87,10 @@ pub enum Error { BuildVm(::Error), ChownTpmStorage(sys_util::Error), CloneEventFd(sys_util::Error), - ControllerCreate(msg_socket2::Error), + ConnectRemoteDevice(io::Error), CreateAc97(devices::PciDeviceError), CreateConsole(arch::serial::Error), + CreateController(msg_socket2::Error), CreateDiskError(disk::Error), CreateEventFd(sys_util::Error), CreatePollContext(sys_util::Error), @@ -152,7 +153,6 @@ pub enum Error { VhostNetDeviceNew(virtio::vhost::Error), VhostVsockDeviceNew(virtio::vhost::Error), VirtioPciDev(sys_util::Error), - WaylandDeviceNew(sys_util::Error), } impl Display for Error { @@ -174,9 +174,10 @@ impl Display for Error { BuildVm(e) => write!(f, "The architecture failed to build the vm: {}", e), ChownTpmStorage(e) => write!(f, "failed to chown tpm storage: {}", e), CloneEventFd(e) => write!(f, "failed to clone eventfd: {}", e), - ControllerCreate(e) => write!(f, "failed to create device controller: {}", e), + ConnectRemoteDevice(e) => write!(f, "failed to connect to remote device socket: {}", e), CreateAc97(e) => write!(f, "failed to create ac97 device: {}", e), CreateConsole(e) => write!(f, "failed to create console device: {}", e), + CreateController(e) => write!(f, "failed to create device controller: {}", e), CreateDiskError(e) => write!(f, "failed to create virtual disk: {}", e), CreateEventFd(e) => write!(f, "failed to create eventfd: {}", e), CreatePollContext(e) => write!(f, "failed to create poll context: {}", e), @@ -248,7 +249,6 @@ impl Display for Error { VhostNetDeviceNew(e) => write!(f, "failed to set up vhost networking: {}", e), VhostVsockDeviceNew(e) => write!(f, "failed to set up virtual socket device: {}", e), VirtioPciDev(e) => write!(f, "failed to create virtio pci dev: {}", e), - WaylandDeviceNew(e) => write!(f, "failed to create wayland device: {}", e), } } } @@ -411,7 +411,7 @@ type DeviceResult = std::result::Result; fn create_block_device( cfg: &Config, disk: &DiskOption, - disk_device_socket: DiskControlResponseSocket, + disk_device_control_socket: DiskControlResponseSocket, ) -> DeviceResult { // Special case '/proc/self/fd/*' paths. The FD is already open, just use it. let raw_image: File = if disk.path.parent() == Some(Path::new("/proc/self/fd")) { @@ -438,7 +438,7 @@ fn create_block_device( disk.read_only, disk.sparse, disk.block_size, - Some(disk_device_socket), + Some(disk_device_control_socket), ) .map_err(Error::BlockDeviceNew)?; @@ -652,7 +652,7 @@ fn create_net_device( fn create_gpu_device( cfg: &Config, exit_evt: &EventFd, - gpu_device_socket: VmMemoryControlRequestSocket, + gpu_device_control_socket: VmMemoryControlRequestSocket, gpu_sockets: Vec, wayland_socket_path: Option<&PathBuf>, x_display: Option, @@ -678,7 +678,7 @@ fn create_gpu_device( let dev = virtio::Gpu::new( exit_evt.try_clone().map_err(Error::CloneEventFd)?, - Some(gpu_device_socket), + Some(gpu_device_control_socket), NonZeroU8::new(1).unwrap(), // number of scanouts gpu_sockets, display_backends, @@ -756,7 +756,7 @@ fn create_gpu_device( fn create_wayland_device( cfg: &Config, - socket: VmMemoryControlRequestSocket, + vm_socket: VmMemoryControlRequestSocket, resource_bridge: Option, memory_params: MemoryParams, ) -> DeviceResult { @@ -767,20 +767,23 @@ fn create_wayland_device( .collect::>>() .ok_or(Error::InvalidWaylandPath)?; - let mut path = std::env::var("XDG_RUNTIME_DIR").expect("XDG_RUNTIME_DIR missing"); - path.push_str("/crosvm-wl.sock"); - let seq_socket = UnixSeqpacket::connect(&path).expect("connect failed"); - let msg_socket = msg_socket2::Socket::new(seq_socket); - let dev = virtio::Controller::create( - Params { - wayland_paths: cfg.wayland_socket_paths.clone(), - vm_socket: socket, - resource_bridge, - }, - memory_params, - msg_socket, - ) - .map_err(Error::ControllerCreate)?; + let params = Params { + wayland_paths: cfg.wayland_socket_paths.clone(), + vm_socket, + resource_bridge, + }; + + let dev: Box = match cfg.remote_wayland_device_socket_path { + Some(ref socket_path) => { + let socket = UnixSeqpacket::connect(socket_path).map_err(Error::ConnectRemoteDevice)?; + let msg_socket = msg_socket2::Socket::new(socket); + let controller = virtio::Controller::create(params, memory_params, msg_socket) + .map_err(Error::CreateController)?; + Box::new(controller) + } + + None => Box::new(virtio::Wl::new(params).unwrap()), + }; let jail = match simple_jail(&cfg, "wl_device")? { Some(mut jail) => { @@ -808,10 +811,7 @@ fn create_wayland_device( None => None, }; - Ok(VirtioDeviceStub { - dev: Box::new(dev), - jail, - }) + Ok(VirtioDeviceStub { dev, jail }) } #[cfg(any(feature = "video-decoder", feature = "video-encoder"))] @@ -1066,7 +1066,7 @@ fn create_console_device(cfg: &Config, param: &SerialParameters) -> DeviceResult }) } -// gpu_device_socket is not used when GPU support is disabled. +// gpu_device_control_socket is not used when GPU support is disabled. #[cfg_attr(not(feature = "gpu"), allow(unused_variables))] fn create_virtio_devices( cfg: &Config, @@ -1075,11 +1075,11 @@ fn create_virtio_devices( vm: &mut Vm, resources: &mut SystemAllocator, _exit_evt: &EventFd, - wayland_device_socket: VmMemoryControlRequestSocket, - gpu_device_socket: VmMemoryControlRequestSocket, - balloon_device_socket: BalloonControlResponseSocket, - disk_device_sockets: &mut Vec, - pmem_device_sockets: &mut Vec, + wayland_device_control_socket: VmMemoryControlRequestSocket, + gpu_device_control_socket: VmMemoryControlRequestSocket, + balloon_device_control_socket: BalloonControlResponseSocket, + disk_device_control_sockets: &mut Vec, + pmem_device_control_sockets: &mut Vec, ) -> DeviceResult> { let mut devs = Vec::new(); @@ -1093,19 +1093,19 @@ fn create_virtio_devices( } for disk in &cfg.disks { - let disk_device_socket = disk_device_sockets.remove(0); - devs.push(create_block_device(cfg, disk, disk_device_socket)?); + let disk_device_control_socket = disk_device_control_sockets.remove(0); + devs.push(create_block_device(cfg, disk, disk_device_control_socket)?); } for (index, pmem_disk) in cfg.pmem_devices.iter().enumerate() { - let pmem_device_socket = pmem_device_sockets.remove(0); + let pmem_device_control_socket = pmem_device_control_sockets.remove(0); devs.push(create_pmem_device( cfg, vm, resources, pmem_disk, index, - pmem_device_socket, + pmem_device_control_socket, )?); } @@ -1138,7 +1138,7 @@ fn create_virtio_devices( devs.push(create_vinput_device(cfg, dev_path)?); } - devs.push(create_balloon_device(cfg, balloon_device_socket)?); + devs.push(create_balloon_device(cfg, balloon_device_control_socket)?); // We checked above that if the IP is defined, then the netmask is, too. for tap_fd in &cfg.tap_fd { @@ -1154,7 +1154,7 @@ fn create_virtio_devices( #[cfg_attr(not(feature = "gpu"), allow(unused_mut))] let mut resource_bridges = Vec::::new(); - if !cfg.wayland_socket_paths.is_empty() { + if !cfg.wayland_socket_paths.is_empty() || cfg.remote_wayland_device_socket_path.is_some() { #[cfg_attr(not(feature = "gpu"), allow(unused_mut))] let mut wl_resource_bridge = None::; @@ -1170,7 +1170,7 @@ fn create_virtio_devices( devs.push(create_wayland_device( cfg, - wayland_device_socket, + wayland_device_control_socket, wl_resource_bridge, mem_params, )?); @@ -1205,7 +1205,7 @@ fn create_virtio_devices( if let Some(gpu_parameters) = &cfg.gpu_parameters { let mut event_devices = Vec::new(); if cfg.display_window_mouse { - let (event_device_socket, virtio_dev_socket) = + let (event_device_control_socket, virtio_dev_socket) = UnixStream::pair().map_err(Error::CreateSocket)?; let (single_touch_width, single_touch_height) = cfg .virtio_single_touch @@ -1222,22 +1222,22 @@ fn create_virtio_devices( dev: Box::new(dev), jail: simple_jail(&cfg, "input_device")?, }); - event_devices.push(EventDevice::touchscreen(event_device_socket)); + event_devices.push(EventDevice::touchscreen(event_device_control_socket)); } if cfg.display_window_keyboard { - let (event_device_socket, virtio_dev_socket) = + let (event_device_control_socket, virtio_dev_socket) = UnixStream::pair().map_err(Error::CreateSocket)?; let dev = virtio::new_keyboard(virtio_dev_socket).map_err(Error::InputDeviceNew)?; devs.push(VirtioDeviceStub { dev: Box::new(dev), jail: simple_jail(&cfg, "input_device")?, }); - event_devices.push(EventDevice::keyboard(event_device_socket)); + event_devices.push(EventDevice::keyboard(event_device_control_socket)); } devs.push(create_gpu_device( cfg, _exit_evt, - gpu_device_socket, + gpu_device_control_socket, resource_bridges, // Use the unnamed socket for GPU display screens. cfg.wayland_socket_paths.get(""), @@ -1279,11 +1279,11 @@ fn create_devices( resources: &mut SystemAllocator, exit_evt: &EventFd, control_sockets: &mut Vec, - wayland_device_socket: VmMemoryControlRequestSocket, - gpu_device_socket: VmMemoryControlRequestSocket, - balloon_device_socket: BalloonControlResponseSocket, - disk_device_sockets: &mut Vec, - pmem_device_sockets: &mut Vec, + wayland_device_control_socket: VmMemoryControlRequestSocket, + gpu_device_control_socket: VmMemoryControlRequestSocket, + balloon_device_control_socket: BalloonControlResponseSocket, + disk_device_control_sockets: &mut Vec, + pmem_device_control_sockets: &mut Vec, usb_provider: HostBackendDeviceProvider, ) -> DeviceResult, Option)>> { let stubs = create_virtio_devices( @@ -1293,20 +1293,20 @@ fn create_devices( vm, resources, exit_evt, - wayland_device_socket, - gpu_device_socket, - balloon_device_socket, - disk_device_sockets, - pmem_device_sockets, + wayland_device_control_socket, + gpu_device_control_socket, + balloon_device_control_socket, + disk_device_control_sockets, + pmem_device_control_sockets, )?; let mut pci_devices = Vec::new(); for stub in stubs { - let (msi_host_socket, msi_device_socket) = + let (msi_host_socket, msi_device_control_socket) = msg_socket::pair::().map_err(Error::CreateSocket)?; control_sockets.push(TaggedControlSocket::VmIrq(msi_host_socket)); - let dev = VirtioPciDevice::new(mem.clone(), stub.dev, msi_device_socket) + let dev = VirtioPciDevice::new(mem.clone(), stub.dev, msi_device_control_socket) .map_err(Error::VirtioPciDev)?; let dev = Box::new(dev) as Box; pci_devices.push((dev, stub.jail)); @@ -1332,11 +1332,11 @@ fn create_devices( for vfio_path in &cfg.vfio { // create one Irq and Mem request socket for each vfio device - let (vfio_host_socket_irq, vfio_device_socket_irq) = + let (vfio_host_socket_irq, vfio_device_control_socket_irq) = msg_socket::pair::().map_err(Error::CreateSocket)?; control_sockets.push(TaggedControlSocket::VmIrq(vfio_host_socket_irq)); - let (vfio_host_socket_mem, vfio_device_socket_mem) = + let (vfio_host_socket_mem, vfio_device_control_socket_mem) = msg_socket::pair::() .map_err(Error::CreateSocket)?; control_sockets.push(TaggedControlSocket::VmMemory(vfio_host_socket_mem)); @@ -1345,8 +1345,8 @@ fn create_devices( .map_err(Error::CreateVfioDevice)?; let vfiopcidevice = Box::new(VfioPciDevice::new( vfiodevice, - vfio_device_socket_irq, - vfio_device_socket_mem, + vfio_device_control_socket_irq, + vfio_device_control_socket_mem, )); pci_devices.push((vfiopcidevice, simple_jail(&cfg, "vfio_device")?)); } @@ -1792,40 +1792,40 @@ pub fn run_config(cfg: Config) -> Result<()> { }; let mut control_sockets = Vec::new(); - let (wayland_host_socket, wayland_device_socket) = + let (wayland_host_socket, wayland_device_control_socket) = msg_socket::pair::().map_err(Error::CreateSocket)?; control_sockets.push(TaggedControlSocket::VmMemory(wayland_host_socket)); // Balloon gets a special socket so balloon requests can be forwarded from the main process. - let (balloon_host_socket, balloon_device_socket) = + let (balloon_host_socket, balloon_device_control_socket) = msg_socket::pair::() .map_err(Error::CreateSocket)?; // Create one control socket per disk. - let mut disk_device_sockets = Vec::new(); + let mut disk_device_control_sockets = Vec::new(); let mut disk_host_sockets = Vec::new(); let disk_count = cfg.disks.len(); for _ in 0..disk_count { - let (disk_host_socket, disk_device_socket) = + let (disk_host_socket, disk_device_control_socket) = msg_socket::pair::() .map_err(Error::CreateSocket)?; disk_host_sockets.push(disk_host_socket); - disk_device_sockets.push(disk_device_socket); + disk_device_control_sockets.push(disk_device_control_socket); } - let mut pmem_device_sockets = Vec::new(); + let mut pmem_device_control_sockets = Vec::new(); let pmem_count = cfg.pmem_devices.len(); for _ in 0..pmem_count { - let (pmem_host_socket, pmem_device_socket) = + let (pmem_host_socket, pmem_device_control_socket) = msg_socket::pair::().map_err(Error::CreateSocket)?; - pmem_device_sockets.push(pmem_device_socket); + pmem_device_control_sockets.push(pmem_device_control_socket); control_sockets.push(TaggedControlSocket::VmMsync(pmem_host_socket)); } - let (gpu_host_socket, gpu_device_socket) = + let (gpu_host_socket, gpu_device_control_socket) = msg_socket::pair::().map_err(Error::CreateSocket)?; control_sockets.push(TaggedControlSocket::VmMemory(gpu_host_socket)); - let (ioapic_host_socket, ioapic_device_socket) = + let (ioapic_host_socket, ioapic_device_control_socket) = msg_socket::pair::().map_err(Error::CreateSocket)?; control_sockets.push(TaggedControlSocket::VmIrq(ioapic_host_socket)); @@ -1833,7 +1833,7 @@ pub fn run_config(cfg: Config) -> Result<()> { let linux = Arch::build_vm( components, cfg.split_irqchip, - ioapic_device_socket, + ioapic_device_control_socket, &cfg.serial_parameters, simple_jail(&cfg, "serial")?, |mem, mem_params, vm, sys_allocator, exit_evt| { @@ -1845,11 +1845,11 @@ pub fn run_config(cfg: Config) -> Result<()> { sys_allocator, exit_evt, &mut control_sockets, - wayland_device_socket, - gpu_device_socket, - balloon_device_socket, - &mut disk_device_sockets, - &mut pmem_device_sockets, + wayland_device_control_socket, + gpu_device_control_socket, + balloon_device_control_socket, + &mut disk_device_control_sockets, + &mut pmem_device_control_sockets, usb_provider, ) }, diff --git a/src/main.rs b/src/main.rs index 36f3881..7ea2e01 100644 --- a/src/main.rs +++ b/src/main.rs @@ -871,6 +871,15 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: } cfg.wayland_socket_paths.insert(name.to_string(), path); } + "wayland-device-sock" => { + let path = PathBuf::from(value.unwrap()); + if cfg.remote_wayland_device_socket_path.is_some() { + return Err(argument::Error::TooManyArguments(String::from( + "wayland device socket already supplied", + ))); + } + cfg.remote_wayland_device_socket_path = Some(path); + } #[cfg(feature = "wl-dmabuf")] "wayland-dmabuf" => cfg.wayland_dmabuf = true, "x-display" => { @@ -1446,9 +1455,7 @@ Possible key values: Argument::value("x-display", "DISPLAY", "X11 display name to use."), Argument::flag( "display-window-keyboard", - "\ -Capture keyboard input from the display window. -", + "Capture keyboard input from the display window.", ), Argument::flag( "display-window-mouse", @@ -1470,6 +1477,11 @@ Path to the Wayland socket to use. The unnamed one is used for displaying virtual screens. Named ones are only for IPC. ", ), + Argument::value( + "wayland-device-sock", + "PATH", + "Path to a remote crosvm Wayland device to use.", + ), #[cfg(feature = "wl-dmabuf")] Argument::flag( "wayland-dmabuf", diff --git a/src/wl.rs b/src/wl.rs index bf8989e..1581b2c 100644 --- a/src/wl.rs +++ b/src/wl.rs @@ -6,6 +6,10 @@ use devices::virtio::{ }; use msg_socket::MsgSocket; use std::fs::remove_file; +use std::io::prelude::*; +use std::io::stdout; +use std::os::unix::prelude::*; +use std::process; use sys_util::{error, net::UnixSeqpacketListener, GuestMemory}; use vm_control::MaybeOwnedFd; @@ -20,11 +24,16 @@ fn main() { eprintln!("hello world"); // Create and display the socket. - let mut path = std::env::var("XDG_RUNTIME_DIR").expect("XDG_RUNTIME_DIR missing"); - path.push_str("/crosvm-wl.sock"); + let mut path = std::env::var_os("XDG_RUNTIME_DIR").expect("XDG_RUNTIME_DIR missing"); + path.push("/crosvm_wl-"); + path.push(process::id().to_string()); + path.push(".sock"); let _ = remove_file(&path); let server = UnixSeqpacketListener::bind(&path).expect("failed to create control socket"); - println!("{}", path); + match stdout().write_all(path.as_bytes()) { + Ok(()) => println!(), + Err(e) => eprintln!("{}", e), + } // Receive connection from crosvm. let conn = server.accept().expect("accept failed"); -- cgit 1.4.1