diff options
Diffstat (limited to 'src/guest')
-rw-r--r-- | src/guest/wl.rs | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/guest/wl.rs b/src/guest/wl.rs new file mode 100644 index 0000000..e273246 --- /dev/null +++ b/src/guest/wl.rs @@ -0,0 +1,183 @@ +// 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, 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; +use std::os::unix::prelude::*; +use std::process; +use sys_util::{error, net::UnixSeqpacketListener, GuestMemory}; +use vm_control::MaybeOwnedFd; + +#[cfg(any(target_arch = "arm", target_arch = "aarch64"))] +pub use aarch64::arch_memory_regions; +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +pub use x86_64::arch_memory_regions; + +type Socket = msg_socket2::Socket<Response, Request>; + +fn main() { + eprintln!("hello world"); + + // Create and display the 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 control 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 msg_socket: Socket = msg_socket2::Socket::new(conn); + + let (memory_params, ext_socket) = match msg_socket.recv() { + Ok(Request::Create { + memory_params, + ext_socket, + }) => (memory_params, ext_socket), + + Ok(msg) => { + panic!("received unexpected message: {:?}", msg); + } + + Err(e) => { + panic!("recv error: {}", e); + } + }; + + 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 dbg!(msg_socket.recv()) { + Ok(Request::DebugLabel) => { + let result = wl.debug_label(); + if let Err(e) = msg_socket.send(Response::DebugLabel(result)) { + panic!("responding to DebugLabel failed: {}", e); + } + } + + Ok(Request::DeviceType) => { + let result = wl.device_type(); + if let Err(e) = msg_socket.send(Response::DeviceType(result)) { + panic!("responding to DeviceType failed: {}", e); + } + } + + Ok(Request::QueueMaxSizes) => { + let result = wl.queue_max_sizes(); + if let Err(e) = msg_socket.send(dbg!(Response::QueueMaxSizes(result))) { + panic!("responding to QueueMaxSizes failed: {}", e); + } + } + + Ok(Request::Features) => { + let result = wl.features(); + if let Err(e) = msg_socket.send(Response::Features(result)) { + panic!("responding to Features failed: {}", e); + } + } + + Ok(Request::AckFeatures(value)) => wl.ack_features(value), + + Ok(Request::ReadConfig { offset, len }) => { + let mut data = vec![0; len]; + wl.read_config(offset, &mut data); + if let Err(e) = msg_socket.send(Response::ReadConfig(data)) { + panic!("responding to ReadConfig failed: {}", e); + } + } + + Ok(Request::WriteConfig { offset, ref data }) => wl.write_config(offset, data), + + Ok(Request::Activate { + shm, + interrupt, + interrupt_resample_evt, + queues, + queue_evts, + }) => { + let shm = shm.owned(); + + let regions = arch_memory_regions(memory_params); + let mem = + GuestMemory::with_memfd(®ions, shm).expect("GuestMemory::with_memfd failed"); + + let interrupt: MsgSocket<InterruptProxyEvent, ()> = + MsgSocket::new(interrupt.owned()); + + wl.activate( + mem, + Box::new(InterruptProxy::new( + interrupt, + interrupt_resample_evt.owned(), + )), + queues, + queue_evts.into_iter().map(MaybeOwnedFd::owned).collect(), + ); + + println!("activated Wl"); + } + + Ok(Request::Reset) => { + let result = wl.reset(); + if let Err(e) = msg_socket.send(dbg!(Response::Reset(result))) { + panic!("responding to Reset failed: {}", e); + } + } + + Ok(Request::GetDeviceBars(address)) => { + let result = wl.get_device_bars(address); + if let Err(e) = msg_socket.send(Response::GetDeviceBars(result)) { + panic!("responding to GetDeviceBars failed: {}", e); + } + } + + Ok(Request::GetDeviceCaps) => { + let result = wl + .get_device_caps() + .into_iter() + .map(|c| RemotePciCapability::from(&*c)) + .collect(); + if let Err(e) = msg_socket.send(Response::GetDeviceCaps(result)) { + panic!("responding to GetDeviceCaps failed: {}", e); + } + } + + Ok(Request::Kill) => { + // Will block until worker shuts down. + drop(wl); + + if let Err(e) = msg_socket.send(Response::Kill) { + error!("responding to Kill failed: {}", e); + } + + break; + } + + Ok(msg @ Request::Create { .. }) => panic!("unexpected message {:?}", msg), + + Err(e) => panic!("recv failed: {}", e), + } + } +} |