diff options
author | Alyssa Ross <hi@alyssa.is> | 2020-04-10 13:19:04 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2020-06-15 09:37:29 +0000 |
commit | eb90518961ca5f00bd832429be840600ce305fb4 (patch) | |
tree | 8415abc6314ac439b47d90305194cc88eca76146 /src | |
parent | aa9ee49fdf908aef32d4363704099a0584834d4c (diff) | |
download | crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar.gz crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar.bz2 crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar.lz crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar.xz crosvm-eb90518961ca5f00bd832429be840600ce305fb4.tar.zst crosvm-eb90518961ca5f00bd832429be840600ce305fb4.zip |
three parts
Diffstat (limited to 'src')
-rw-r--r-- | src/ext/wl_main.rs | 187 | ||||
-rw-r--r-- | src/guest/wl.rs (renamed from src/wl.rs) | 32 | ||||
-rw-r--r-- | src/linux.rs | 17 |
3 files changed, 218 insertions, 18 deletions
diff --git a/src/ext/wl_main.rs b/src/ext/wl_main.rs new file mode 100644 index 0000000..0b8d6a3 --- /dev/null +++ b/src/ext/wl_main.rs @@ -0,0 +1,187 @@ +// Copyright 2017 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. + +use std::env::args_os; +use std::fs::remove_file; +use std::io::{stdout, IoSlice, Write}; +use std::os::unix::prelude::*; +use std::process; + +use devices::virtio::{remote, virtualized}; +use sys_util::net::{UnixSeqpacket, UnixSeqpacketListener}; +use sys_util::{PollContext, PollToken, ScmSocket}; + +fn main() { + // Create and display the incoming socket. + 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 socket"); + match stdout().write_all(path.as_bytes()) { + Ok(()) => println!(), + Err(e) => eprintln!("{}", e), + } + + // Receive connection from crosvm. + let conn = server.accept().expect("accept failed"); + let client_virtio_device_msg_socket: msg_socket2::Socket<remote::Response, remote::Request> = + msg_socket2::Socket::new(conn); + + let (memory_params, client_vm_control_socket) = match client_virtio_device_msg_socket.recv() { + Ok(remote::Request::Create { + memory_params, + vm_control_socket, + }) => (memory_params, vm_control_socket.owned()), + + Ok(msg) => panic!("unexpected message: {:?}", msg), + Err(e) => panic!("recv error: {}", e), + }; + + let server_virtio_device_socket_path = args_os().nth(1).expect("missing server socket path"); + let server_virtio_device_socket = + UnixSeqpacket::connect(server_virtio_device_socket_path).expect("connect failed"); + let server_virtio_device_msg_socket: msg_socket2::Socket< + virtualized::Request, + virtualized::Response, + > = msg_socket2::Socket::new(server_virtio_device_socket); + + let (server_vm_control_socket, ext_vm_control_socket) = + UnixSeqpacket::pair().expect("pair failed"); + + server_virtio_device_msg_socket + .send(virtualized::Request::Create { + memory_params, + ext_socket: ext_vm_control_socket, // TODO: proxy rather than passing through + }) + .expect("send failed"); + + #[derive(Debug, PollToken)] + enum Token { + ClientVirtioDevice, + ClientVmControl, + ServerVirtioDevice, + ServerVmControl, + } + + let poll_ctx = match PollContext::build_with(&[ + (&client_virtio_device_msg_socket, Token::ClientVirtioDevice), + (&client_vm_control_socket, Token::ClientVmControl), + (&server_virtio_device_msg_socket, Token::ServerVirtioDevice), + (&server_vm_control_socket, Token::ServerVmControl), + ]) { + Ok(pc) => pc, + Err(e) => panic!("failed creating PollContext: {}", e), + }; + + loop { + let events = match poll_ctx.wait() { + Ok(v) => v, + Err(e) => panic!("failed polling for events: {}", e), + }; + + for event in &events { + match event.token() { + Token::ClientVirtioDevice => { + let msg = match dbg!(client_virtio_device_msg_socket.recv()) { + Ok(remote::Request::DebugLabel) => virtualized::Request::DebugLabel, + Ok(remote::Request::DeviceType) => virtualized::Request::DeviceType, + Ok(remote::Request::QueueMaxSizes) => virtualized::Request::QueueMaxSizes, + Ok(remote::Request::Features) => virtualized::Request::Features, + Ok(remote::Request::AckFeatures(value)) => { + virtualized::Request::AckFeatures(value) + } + Ok(remote::Request::ReadConfig { offset, len }) => { + virtualized::Request::ReadConfig { offset, len } + } + Ok(remote::Request::WriteConfig { offset, data }) => { + virtualized::Request::WriteConfig { offset, data } + } + Ok(remote::Request::Activate { + shm, + interrupt, + interrupt_resample_evt, + queues, + queue_evts, + }) => virtualized::Request::Activate { + shm, + interrupt, + interrupt_resample_evt, + queues, + queue_evts, + }, + Ok(remote::Request::Reset) => virtualized::Request::Reset, + Ok(remote::Request::GetDeviceBars(address)) => { + virtualized::Request::GetDeviceBars(address) + } + Ok(remote::Request::GetDeviceCaps) => virtualized::Request::GetDeviceCaps, + Ok(remote::Request::Kill) => virtualized::Request::Kill, + + Ok(req @ remote::Request::Create { .. }) => { + panic!("unexpected message: {:?}", req) + } + + Err(e) => panic!("recv failed: {}", e), + }; + + if let Err(e) = server_virtio_device_msg_socket.send(msg) { + panic!("send failed: {}", e); + } + } + + Token::ClientVmControl => { + let (buf, fds) = client_vm_control_socket + .recv_as_vec_with_fds() + .expect("recv failed"); + server_vm_control_socket + .send_with_fds(&[IoSlice::new(&buf)], &fds[..]) + .expect("send failed"); + } + + Token::ServerVirtioDevice => { + let msg = match server_virtio_device_msg_socket.recv() { + Ok(virtualized::Response::DebugLabel(label)) => { + remote::Response::DebugLabel(label) + } + Ok(virtualized::Response::DeviceType(typ)) => { + remote::Response::DeviceType(typ) + } + Ok(virtualized::Response::Features(value)) => { + remote::Response::Features(value) + } + Ok(virtualized::Response::GetDeviceBars(bars)) => { + remote::Response::GetDeviceBars(bars) + } + Ok(virtualized::Response::GetDeviceCaps(caps)) => { + remote::Response::GetDeviceCaps(caps) + } + Ok(virtualized::Response::Kill) => remote::Response::Kill, + Ok(virtualized::Response::QueueMaxSizes(sizes)) => { + remote::Response::QueueMaxSizes(sizes) + } + Ok(virtualized::Response::ReadConfig(config)) => { + remote::Response::ReadConfig(config) + } + Ok(virtualized::Response::Reset(result)) => remote::Response::Reset(result), + Err(e) => panic!("recv failed: {}", e), + }; + + if let Err(e) = client_virtio_device_msg_socket.send(dbg!(msg)) { + panic!("send failed: {}", e); + } + } + + Token::ServerVmControl => { + let (buf, fds) = server_vm_control_socket + .recv_as_vec_with_fds() + .expect("recv failed"); + client_vm_control_socket + .send_with_fds(&[IoSlice::new(&buf)], &fds[..]) + .expect("send failed"); + } + } + } + } +} diff --git a/src/wl.rs b/src/guest/wl.rs index 1581b2c..e273246 100644 --- a/src/wl.rs +++ b/src/guest/wl.rs @@ -1,10 +1,14 @@ -// SPDX-License-Identifier: BSD-3-Clause +// Copyright 2017 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. +use devices::virtio::remote::RemotePciCapability; +use devices::virtio::virtualized::{Request, Response}; use devices::virtio::{ - InterruptProxy, InterruptProxyEvent, RemotePciCapability, Request, Response, VirtioDevice, - VirtioDeviceNew, Wl, + InterruptProxy, InterruptProxyEvent, Params, VirtioDevice, VirtioDeviceNew, Wl, }; use msg_socket::MsgSocket; +use std::collections::BTreeMap; use std::fs::remove_file; use std::io::prelude::*; use std::io::stdout; @@ -39,11 +43,11 @@ fn main() { let conn = server.accept().expect("accept failed"); let msg_socket: Socket = msg_socket2::Socket::new(conn); - let (device_params, memory_params) = match msg_socket.recv() { + let (memory_params, ext_socket) = match msg_socket.recv() { Ok(Request::Create { - device_params, memory_params, - }) => (device_params, memory_params), + ext_socket, + }) => (memory_params, ext_socket), Ok(msg) => { panic!("received unexpected message: {:?}", msg); @@ -54,10 +58,18 @@ fn main() { } }; - let mut wl = Wl::new(device_params).unwrap(); + let mut wayland_paths = BTreeMap::new(); + wayland_paths.insert("".into(), "/run/user/1000/wayland-0".into()); + + let mut wl = Wl::new(Params { + wayland_paths, + vm_socket: MsgSocket::new(ext_socket), + resource_bridge: None, + }) + .unwrap(); loop { - match msg_socket.recv() { + match dbg!(msg_socket.recv()) { Ok(Request::DebugLabel) => { let result = wl.debug_label(); if let Err(e) = msg_socket.send(Response::DebugLabel(result)) { @@ -74,7 +86,7 @@ fn main() { Ok(Request::QueueMaxSizes) => { let result = wl.queue_max_sizes(); - if let Err(e) = msg_socket.send(Response::QueueMaxSizes(result)) { + if let Err(e) = msg_socket.send(dbg!(Response::QueueMaxSizes(result))) { panic!("responding to QueueMaxSizes failed: {}", e); } } @@ -129,7 +141,7 @@ fn main() { Ok(Request::Reset) => { let result = wl.reset(); - if let Err(e) = msg_socket.send(Response::Reset(result)) { + if let Err(e) = msg_socket.send(dbg!(Response::Reset(result))) { panic!("responding to Reset failed: {}", e); } } diff --git a/src/linux.rs b/src/linux.rs index ce177e0..ee248a4 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -767,22 +767,23 @@ fn create_wayland_device( .collect::<Option<Vec<_>>>() .ok_or(Error::InvalidWaylandPath)?; - let params = Params { - wayland_paths: cfg.wayland_socket_paths.clone(), - vm_socket, - resource_bridge, - }; - let dev: Box<dyn VirtioDevice> = 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) + let controller = virtio::Controller::create(memory_params, vm_socket, msg_socket) .map_err(Error::CreateController)?; Box::new(controller) } - None => Box::new(virtio::Wl::new(params).unwrap()), + None => Box::new( + virtio::Wl::new(Params { + wayland_paths: cfg.wayland_socket_paths.clone(), + vm_socket, + resource_bridge, + }) + .unwrap(), + ), }; let jail = match simple_jail(&cfg, "wl_device")? { |