diff options
Diffstat (limited to 'devices/src/virtio/wl.rs')
-rw-r--r-- | devices/src/virtio/wl.rs | 108 |
1 files changed, 91 insertions, 17 deletions
diff --git a/devices/src/virtio/wl.rs b/devices/src/virtio/wl.rs index 6fefd51..a685e51 100644 --- a/devices/src/virtio/wl.rs +++ b/devices/src/virtio/wl.rs @@ -67,10 +67,39 @@ use sys_util::ioctl_with_ref; use super::resource_bridge::*; use super::{ - DescriptorChain, Interrupt, Queue, Reader, VirtioDevice, Writer, TYPE_WL, VIRTIO_F_VERSION_1, + DescriptorChain, Interrupt, InterruptProxyEvent, Queue, Reader, VirtioDevice, Writer, TYPE_WL, + VIRTIO_F_VERSION_1, }; use vm_control::{MaybeOwnedFd, VmMemoryControlRequestSocket, VmMemoryRequest, VmMemoryResponse}; +use msg_socket::{MsgOnSocket, MsgSocket}; +use sys_util::net::UnixSeqpacket; + +#[derive(Debug, MsgOnSocket)] +pub struct SingleFd { + pub memfd: MaybeOwnedFd, + pub interrupt: MaybeOwnedFd, + pub interrupt_resample_evt: MaybeOwnedFd, + pub in_queue: Queue, + pub out_queue: Queue, + pub vm_socket: MaybeOwnedFd, + pub use_transition_flags: bool, + pub in_queue_evt: MaybeOwnedFd, + pub out_queue_evt: MaybeOwnedFd, + pub kill_evt: MaybeOwnedFd, +} + +type Socket = MsgSocket<SingleFd, ()>; + +lazy_static! { + static ref SOCKET: Socket = { + let mut path = std::env::var("XDG_RUNTIME_DIR").expect("XDG_RUNTIME_DIR missing"); + path.push_str("/crosvm-wl.sock"); + let socket = UnixSeqpacket::connect(&path).expect("connect failed"); + MsgSocket::new(socket) + }; +} + const VIRTWL_SEND_MAX_ALLOCS: usize = 28; const VIRTIO_WL_CMD_VFD_NEW: u32 = 256; const VIRTIO_WL_CMD_VFD_CLOSE: u32 = 257; @@ -1336,7 +1365,7 @@ impl WlState { } } -struct Worker { +pub struct Worker { interrupt: Interrupt, mem: GuestMemory, in_queue: Queue, @@ -1345,15 +1374,15 @@ struct Worker { } impl Worker { - fn new( + pub fn new( mem: GuestMemory, interrupt: Interrupt, in_queue: Queue, out_queue: Queue, - wayland_paths: Map<String, PathBuf>, + wayland_paths: Map<String, PathBuf>, // { "": "/run/user/1000/wayland-0" } vm_socket: VmMemoryControlRequestSocket, use_transition_flags: bool, - resource_bridge: Option<ResourceRequestSocket>, + resource_bridge: Option<ResourceRequestSocket>, // None ) -> Worker { Worker { interrupt, @@ -1369,7 +1398,7 @@ impl Worker { } } - fn run(&mut self, mut queue_evts: Vec<EventFd>, kill_evt: EventFd) { + pub fn run(&mut self, mut queue_evts: Vec<EventFd>, kill_evt: EventFd) { let mut in_desc_chains: VecDeque<DescriptorChain> = VecDeque::with_capacity(QUEUE_SIZE as usize); let in_queue_evt = queue_evts.remove(0); @@ -1529,6 +1558,34 @@ impl Worker { } } +struct InterruptWorker { + socket: MsgSocket<(), InterruptProxyEvent>, + interrupt: Interrupt, +} + +impl InterruptWorker { + fn new(socket: MsgSocket<(), InterruptProxyEvent>, interrupt: Interrupt) -> Self { + Self { socket, interrupt } + } + + fn run(&self) { + loop { + use InterruptProxyEvent::*; + let val = self.socket.recv(); + match val { + Ok(SignalUsedQueue(value)) => self.interrupt.signal_used_queue(value).unwrap(), + Ok(SignalConfigChanged) => self.interrupt.signal_config_changed().unwrap(), + Ok(InterruptResample) => self.interrupt.interrupt_resample().unwrap(), + + Err(e) => { + eprintln!("recv error: {}", e); + panic!("recv error: {}", e) + } + } + } + } +} + pub struct Wl { kill_evt: Option<EventFd>, worker_thread: Option<thread::JoinHandle<()>>, @@ -1579,6 +1636,12 @@ impl VirtioDevice for Wl { keep_fds.push(resource_bridge.as_raw_fd()); } + if let Some(ref kill_evt) = self.kill_evt { + keep_fds.push(kill_evt.as_raw_fd()); + } + + keep_fds.push(SOCKET.as_raw_fd()); + keep_fds } @@ -1624,21 +1687,32 @@ impl VirtioDevice for Wl { let wayland_paths = self.wayland_paths.clone(); let use_transition_flags = self.use_transition_flags; let resource_bridge = self.resource_bridge.take(); + + let (ours, theirs) = UnixSeqpacket::pair().expect("pair failed"); + + if let Err(e) = SOCKET.send(&SingleFd { + memfd: MaybeOwnedFd::Borrowed(mem.as_raw_fd()), + interrupt: MaybeOwnedFd::Borrowed(theirs.as_raw_fd()), + interrupt_resample_evt: MaybeOwnedFd::Borrowed( + interrupt.get_resample_evt().as_raw_fd(), + ), + in_queue: queues.remove(0), + out_queue: queues.remove(0), + vm_socket: MaybeOwnedFd::Borrowed(vm_socket.as_raw_fd()), + use_transition_flags, + in_queue_evt: MaybeOwnedFd::Borrowed(queue_evts[0].as_raw_fd()), + out_queue_evt: MaybeOwnedFd::Borrowed(queue_evts[1].as_raw_fd()), + kill_evt: MaybeOwnedFd::Borrowed(kill_evt.as_raw_fd()), + }) { + error!("failed to send SingleFd: {}", e); + return; + } + let worker_result = thread::Builder::new() .name("virtio_wl".to_string()) .spawn(move || { - Worker::new( - mem, - interrupt, - queues.remove(0), - queues.remove(0), - wayland_paths, - vm_socket, - use_transition_flags, - resource_bridge, - ) - .run(queue_evts, kill_evt); + InterruptWorker::new(MsgSocket::new(ours), interrupt).run(); }); match worker_result { |