summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-04-10 13:19:04 +0000
committerAlyssa Ross <hi@alyssa.is>2020-06-15 09:37:29 +0000
commiteb90518961ca5f00bd832429be840600ce305fb4 (patch)
tree8415abc6314ac439b47d90305194cc88eca76146 /src
parentaa9ee49fdf908aef32d4363704099a0584834d4c (diff)
downloadcrosvm-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.rs187
-rw-r--r--src/guest/wl.rs (renamed from src/wl.rs)32
-rw-r--r--src/linux.rs17
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")? {