1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker //! This module implements the virtio wayland used by the guest to access the host's wayland server.
6*bb4ee6a4SAndroid Build Coastguard Worker //!
7*bb4ee6a4SAndroid Build Coastguard Worker //! The virtio wayland protocol is done over two queues: `in` and `out`. The `in` queue is used for
8*bb4ee6a4SAndroid Build Coastguard Worker //! sending commands to the guest that are generated by the host, usually messages from the wayland
9*bb4ee6a4SAndroid Build Coastguard Worker //! server. The `out` queue is for commands from the guest, usually requests to allocate shared
10*bb4ee6a4SAndroid Build Coastguard Worker //! memory, open a wayland server connection, or send data over an existing connection.
11*bb4ee6a4SAndroid Build Coastguard Worker //!
12*bb4ee6a4SAndroid Build Coastguard Worker //! Each `WlVfd` represents one virtual file descriptor created by either the guest or the host.
13*bb4ee6a4SAndroid Build Coastguard Worker //! Virtual file descriptors contain actual file descriptors, either a shared memory file descriptor
14*bb4ee6a4SAndroid Build Coastguard Worker //! or a unix domain socket to the wayland server. In the shared memory case, there is also an
15*bb4ee6a4SAndroid Build Coastguard Worker //! associated slot that indicates which hypervisor memory slot the memory is installed into, as
16*bb4ee6a4SAndroid Build Coastguard Worker //! well as a page frame number that the guest can access the memory from.
17*bb4ee6a4SAndroid Build Coastguard Worker //!
18*bb4ee6a4SAndroid Build Coastguard Worker //! The types starting with `Ctrl` are structures representing the virtio wayland protocol "on the
19*bb4ee6a4SAndroid Build Coastguard Worker //! wire." They are decoded and executed in the `execute` function and encoded as some variant of
20*bb4ee6a4SAndroid Build Coastguard Worker //! `WlResp` for responses.
21*bb4ee6a4SAndroid Build Coastguard Worker //!
22*bb4ee6a4SAndroid Build Coastguard Worker //! There is one `WlState` instance that contains every known vfd and the current state of `in`
23*bb4ee6a4SAndroid Build Coastguard Worker //! queue. The `in` queue requires extra state to buffer messages to the guest in case the `in`
24*bb4ee6a4SAndroid Build Coastguard Worker //! queue is already full. The `WlState` also has a control socket necessary to fulfill certain
25*bb4ee6a4SAndroid Build Coastguard Worker //! requests, such as those registering guest memory.
26*bb4ee6a4SAndroid Build Coastguard Worker //!
27*bb4ee6a4SAndroid Build Coastguard Worker //! The `Worker` is responsible for the poll loop over all possible events, encoding/decoding from
28*bb4ee6a4SAndroid Build Coastguard Worker //! the virtio queue, and routing messages in and out of `WlState`. Possible events include the kill
29*bb4ee6a4SAndroid Build Coastguard Worker //! event, available descriptors on the `in` or `out` queue, and incoming data on any vfd's socket.
30*bb4ee6a4SAndroid Build Coastguard Worker
31*bb4ee6a4SAndroid Build Coastguard Worker use std::cell::RefCell;
32*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::btree_map::Entry;
33*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
34*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeSet;
35*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::VecDeque;
36*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::From;
37*bb4ee6a4SAndroid Build Coastguard Worker use std::error::Error as StdError;
38*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt;
39*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
40*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
41*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Read;
42*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Seek;
43*bb4ee6a4SAndroid Build Coastguard Worker use std::io::SeekFrom;
44*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write;
45*bb4ee6a4SAndroid Build Coastguard Worker use std::mem::size_of;
46*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
47*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_uint;
48*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
49*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_ulonglong;
50*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::net::UnixStream;
51*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
52*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
53*bb4ee6a4SAndroid Build Coastguard Worker use std::rc::Rc;
54*bb4ee6a4SAndroid Build Coastguard Worker use std::result;
55*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
56*bb4ee6a4SAndroid Build Coastguard Worker
57*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::anyhow;
58*bb4ee6a4SAndroid Build Coastguard Worker use anyhow::Context;
59*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
60*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
61*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_iow_nr;
62*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_iowr_nr;
63*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl_with_ref;
64*bb4ee6a4SAndroid Build Coastguard Worker use base::linux::SharedMemoryLinux;
65*bb4ee6a4SAndroid Build Coastguard Worker use base::pagesize;
66*bb4ee6a4SAndroid Build Coastguard Worker use base::pipe;
67*bb4ee6a4SAndroid Build Coastguard Worker use base::round_up_to_page_size;
68*bb4ee6a4SAndroid Build Coastguard Worker use base::unix::FileFlags;
69*bb4ee6a4SAndroid Build Coastguard Worker use base::warn;
70*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
71*bb4ee6a4SAndroid Build Coastguard Worker use base::Error;
72*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
73*bb4ee6a4SAndroid Build Coastguard Worker use base::EventToken;
74*bb4ee6a4SAndroid Build Coastguard Worker use base::EventType;
75*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
76*bb4ee6a4SAndroid Build Coastguard Worker use base::IntoRawDescriptor;
77*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
78*bb4ee6a4SAndroid Build Coastguard Worker use base::MemoryMappingBuilder;
79*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
80*bb4ee6a4SAndroid Build Coastguard Worker use base::MmapError;
81*bb4ee6a4SAndroid Build Coastguard Worker use base::Protection;
82*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor;
83*bb4ee6a4SAndroid Build Coastguard Worker use base::Result;
84*bb4ee6a4SAndroid Build Coastguard Worker use base::SafeDescriptor;
85*bb4ee6a4SAndroid Build Coastguard Worker use base::ScmSocket;
86*bb4ee6a4SAndroid Build Coastguard Worker use base::SharedMemory;
87*bb4ee6a4SAndroid Build Coastguard Worker use base::Tube;
88*bb4ee6a4SAndroid Build Coastguard Worker use base::TubeError;
89*bb4ee6a4SAndroid Build Coastguard Worker use base::VolatileMemoryError;
90*bb4ee6a4SAndroid Build Coastguard Worker use base::WaitContext;
91*bb4ee6a4SAndroid Build Coastguard Worker use base::WorkerThread;
92*bb4ee6a4SAndroid Build Coastguard Worker use data_model::Le32;
93*bb4ee6a4SAndroid Build Coastguard Worker use data_model::Le64;
94*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::MemCacheType;
95*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
96*bb4ee6a4SAndroid Build Coastguard Worker use libc::EBADF;
97*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
98*bb4ee6a4SAndroid Build Coastguard Worker use libc::EINVAL;
99*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
100*bb4ee6a4SAndroid Build Coastguard Worker use libc::ENOSYS;
101*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
102*bb4ee6a4SAndroid Build Coastguard Worker use resources::address_allocator::AddressAllocator;
103*bb4ee6a4SAndroid Build Coastguard Worker use resources::AddressRange;
104*bb4ee6a4SAndroid Build Coastguard Worker use resources::Alloc;
105*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
106*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::DrmFormat;
107*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
108*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::ImageAllocationInfo;
109*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
110*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::ImageMemoryRequirements;
111*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
112*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaDescriptor;
113*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
114*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaError;
115*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
116*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaGralloc;
117*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
118*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaGrallocBackendFlags;
119*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
120*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaGrallocFlags;
121*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
122*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RutabagaIntoRawDescriptor;
123*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
124*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RUTABAGA_MAP_CACHE_CACHED;
125*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
126*bb4ee6a4SAndroid Build Coastguard Worker use rutabaga_gfx::RUTABAGA_MAP_CACHE_MASK;
127*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error as ThisError;
128*bb4ee6a4SAndroid Build Coastguard Worker use vm_control::VmMemorySource;
129*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
130*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
131*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemoryError;
132*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::AsBytes;
133*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromBytes;
134*bb4ee6a4SAndroid Build Coastguard Worker use zerocopy::FromZeroes;
135*bb4ee6a4SAndroid Build Coastguard Worker
136*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
137*bb4ee6a4SAndroid Build Coastguard Worker use super::resource_bridge::get_resource_info;
138*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
139*bb4ee6a4SAndroid Build Coastguard Worker use super::resource_bridge::BufferInfo;
140*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
141*bb4ee6a4SAndroid Build Coastguard Worker use super::resource_bridge::ResourceBridgeError;
142*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
143*bb4ee6a4SAndroid Build Coastguard Worker use super::resource_bridge::ResourceInfo;
144*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
145*bb4ee6a4SAndroid Build Coastguard Worker use super::resource_bridge::ResourceRequest;
146*bb4ee6a4SAndroid Build Coastguard Worker use super::DeviceType;
147*bb4ee6a4SAndroid Build Coastguard Worker use super::Interrupt;
148*bb4ee6a4SAndroid Build Coastguard Worker use super::Queue;
149*bb4ee6a4SAndroid Build Coastguard Worker use super::Reader;
150*bb4ee6a4SAndroid Build Coastguard Worker use super::SharedMemoryMapper;
151*bb4ee6a4SAndroid Build Coastguard Worker use super::SharedMemoryRegion;
152*bb4ee6a4SAndroid Build Coastguard Worker use super::VirtioDevice;
153*bb4ee6a4SAndroid Build Coastguard Worker use super::Writer;
154*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::device_constants::wl::VIRTIO_WL_F_SEND_FENCES;
155*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::device_constants::wl::VIRTIO_WL_F_TRANS_FLAGS;
156*bb4ee6a4SAndroid Build Coastguard Worker use crate::virtio::device_constants::wl::VIRTIO_WL_F_USE_SHMEM;
157*bb4ee6a4SAndroid Build Coastguard Worker
158*bb4ee6a4SAndroid Build Coastguard Worker const QUEUE_SIZE: u16 = 256;
159*bb4ee6a4SAndroid Build Coastguard Worker const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE, QUEUE_SIZE];
160*bb4ee6a4SAndroid Build Coastguard Worker
161*bb4ee6a4SAndroid Build Coastguard Worker const VIRTWL_SEND_MAX_ALLOCS: usize = 28;
162*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CMD_VFD_NEW: u32 = 256;
163*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CMD_VFD_CLOSE: u32 = 257;
164*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CMD_VFD_SEND: u32 = 258;
165*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CMD_VFD_RECV: u32 = 259;
166*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CMD_VFD_NEW_CTX: u32 = 260;
167*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CMD_VFD_NEW_PIPE: u32 = 261;
168*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CMD_VFD_HUP: u32 = 262;
169*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
170*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CMD_VFD_NEW_DMABUF: u32 = 263;
171*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
172*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CMD_VFD_DMABUF_SYNC: u32 = 264;
173*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
174*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CMD_VFD_SEND_FOREIGN_ID: u32 = 265;
175*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CMD_VFD_NEW_CTX_NAMED: u32 = 266;
176*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_RESP_OK: u32 = 4096;
177*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_RESP_VFD_NEW: u32 = 4097;
178*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
179*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_RESP_VFD_NEW_DMABUF: u32 = 4098;
180*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_RESP_ERR: u32 = 4352;
181*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_RESP_OUT_OF_MEMORY: u32 = 4353;
182*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_RESP_INVALID_ID: u32 = 4354;
183*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_RESP_INVALID_TYPE: u32 = 4355;
184*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_RESP_INVALID_FLAGS: u32 = 4356;
185*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_RESP_INVALID_CMD: u32 = 4357;
186*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_VFD_WRITE: u32 = 0x1;
187*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_VFD_READ: u32 = 0x2;
188*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_VFD_MAP: u32 = 0x2;
189*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_VFD_CONTROL: u32 = 0x4;
190*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_VFD_FENCE: u32 = 0x8;
191*bb4ee6a4SAndroid Build Coastguard Worker
192*bb4ee6a4SAndroid Build Coastguard Worker const NEXT_VFD_ID_BASE: u32 = 0x40000000;
193*bb4ee6a4SAndroid Build Coastguard Worker const VFD_ID_HOST_MASK: u32 = NEXT_VFD_ID_BASE;
194*bb4ee6a4SAndroid Build Coastguard Worker // Each in-vq buffer is one page, so we need to leave space for the control header and the maximum
195*bb4ee6a4SAndroid Build Coastguard Worker // number of allocs.
196*bb4ee6a4SAndroid Build Coastguard Worker const IN_BUFFER_LEN: usize =
197*bb4ee6a4SAndroid Build Coastguard Worker 0x1000 - size_of::<CtrlVfdRecv>() - VIRTWL_SEND_MAX_ALLOCS * size_of::<Le32>();
198*bb4ee6a4SAndroid Build Coastguard Worker
199*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
200*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_VFD_DMABUF_SYNC_VALID_FLAG_MASK: u32 = 0x7;
201*bb4ee6a4SAndroid Build Coastguard Worker
202*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
203*bb4ee6a4SAndroid Build Coastguard Worker const DMA_BUF_IOCTL_BASE: c_uint = 0x62;
204*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
205*bb4ee6a4SAndroid Build Coastguard Worker const DMA_BUF_SYNC_WRITE: c_uint = 0x2;
206*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
207*bb4ee6a4SAndroid Build Coastguard Worker const DMA_BUF_SYNC_END: c_uint = 0x4;
208*bb4ee6a4SAndroid Build Coastguard Worker
209*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
210*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
211*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
212*bb4ee6a4SAndroid Build Coastguard Worker struct dma_buf_sync {
213*bb4ee6a4SAndroid Build Coastguard Worker flags: c_ulonglong,
214*bb4ee6a4SAndroid Build Coastguard Worker }
215*bb4ee6a4SAndroid Build Coastguard Worker
216*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
217*bb4ee6a4SAndroid Build Coastguard Worker ioctl_iow_nr!(DMA_BUF_IOCTL_SYNC, DMA_BUF_IOCTL_BASE, 0, dma_buf_sync);
218*bb4ee6a4SAndroid Build Coastguard Worker
219*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
220*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default)]
221*bb4ee6a4SAndroid Build Coastguard Worker struct sync_file_info {
222*bb4ee6a4SAndroid Build Coastguard Worker name: [u8; 32],
223*bb4ee6a4SAndroid Build Coastguard Worker status: i32,
224*bb4ee6a4SAndroid Build Coastguard Worker flags: u32,
225*bb4ee6a4SAndroid Build Coastguard Worker num_fences: u32,
226*bb4ee6a4SAndroid Build Coastguard Worker pad: u32,
227*bb4ee6a4SAndroid Build Coastguard Worker sync_fence_info: u64,
228*bb4ee6a4SAndroid Build Coastguard Worker }
229*bb4ee6a4SAndroid Build Coastguard Worker
230*bb4ee6a4SAndroid Build Coastguard Worker ioctl_iowr_nr!(SYNC_IOC_FILE_INFO, 0x3e, 4, sync_file_info);
231*bb4ee6a4SAndroid Build Coastguard Worker
is_fence(f: &File) -> bool232*bb4ee6a4SAndroid Build Coastguard Worker fn is_fence(f: &File) -> bool {
233*bb4ee6a4SAndroid Build Coastguard Worker let info = sync_file_info::default();
234*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
235*bb4ee6a4SAndroid Build Coastguard Worker // Safe as f is a valid file
236*bb4ee6a4SAndroid Build Coastguard Worker unsafe { ioctl_with_ref(f, SYNC_IOC_FILE_INFO, &info) == 0 }
237*bb4ee6a4SAndroid Build Coastguard Worker }
238*bb4ee6a4SAndroid Build Coastguard Worker
239*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
240*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Default)]
241*bb4ee6a4SAndroid Build Coastguard Worker struct GpuMemoryPlaneDesc {
242*bb4ee6a4SAndroid Build Coastguard Worker stride: u32,
243*bb4ee6a4SAndroid Build Coastguard Worker offset: u32,
244*bb4ee6a4SAndroid Build Coastguard Worker }
245*bb4ee6a4SAndroid Build Coastguard Worker
246*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
247*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug, Default)]
248*bb4ee6a4SAndroid Build Coastguard Worker struct GpuMemoryDesc {
249*bb4ee6a4SAndroid Build Coastguard Worker planes: [GpuMemoryPlaneDesc; 3],
250*bb4ee6a4SAndroid Build Coastguard Worker }
251*bb4ee6a4SAndroid Build Coastguard Worker
252*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CTRL_VFD_SEND_KIND_LOCAL: u32 = 0;
253*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU: u32 = 1;
254*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU_FENCE: u32 = 2;
255*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU_SIGNALED_FENCE: u32 = 3;
256*bb4ee6a4SAndroid Build Coastguard Worker
257*bb4ee6a4SAndroid Build Coastguard Worker const VIRTIO_WL_PFN_SHIFT: u32 = 12;
258*bb4ee6a4SAndroid Build Coastguard Worker
encode_vfd_new( writer: &mut Writer, resp: bool, vfd_id: u32, flags: u32, pfn: u64, size: u32, ) -> WlResult<()>259*bb4ee6a4SAndroid Build Coastguard Worker fn encode_vfd_new(
260*bb4ee6a4SAndroid Build Coastguard Worker writer: &mut Writer,
261*bb4ee6a4SAndroid Build Coastguard Worker resp: bool,
262*bb4ee6a4SAndroid Build Coastguard Worker vfd_id: u32,
263*bb4ee6a4SAndroid Build Coastguard Worker flags: u32,
264*bb4ee6a4SAndroid Build Coastguard Worker pfn: u64,
265*bb4ee6a4SAndroid Build Coastguard Worker size: u32,
266*bb4ee6a4SAndroid Build Coastguard Worker ) -> WlResult<()> {
267*bb4ee6a4SAndroid Build Coastguard Worker let ctrl_vfd_new = CtrlVfdNew {
268*bb4ee6a4SAndroid Build Coastguard Worker hdr: CtrlHeader {
269*bb4ee6a4SAndroid Build Coastguard Worker type_: Le32::from(if resp {
270*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_RESP_VFD_NEW
271*bb4ee6a4SAndroid Build Coastguard Worker } else {
272*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CMD_VFD_NEW
273*bb4ee6a4SAndroid Build Coastguard Worker }),
274*bb4ee6a4SAndroid Build Coastguard Worker flags: Le32::from(0),
275*bb4ee6a4SAndroid Build Coastguard Worker },
276*bb4ee6a4SAndroid Build Coastguard Worker id: Le32::from(vfd_id),
277*bb4ee6a4SAndroid Build Coastguard Worker flags: Le32::from(flags),
278*bb4ee6a4SAndroid Build Coastguard Worker pfn: Le64::from(pfn),
279*bb4ee6a4SAndroid Build Coastguard Worker size: Le32::from(size),
280*bb4ee6a4SAndroid Build Coastguard Worker padding: Default::default(),
281*bb4ee6a4SAndroid Build Coastguard Worker };
282*bb4ee6a4SAndroid Build Coastguard Worker
283*bb4ee6a4SAndroid Build Coastguard Worker writer
284*bb4ee6a4SAndroid Build Coastguard Worker .write_obj(ctrl_vfd_new)
285*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::WriteResponse)
286*bb4ee6a4SAndroid Build Coastguard Worker }
287*bb4ee6a4SAndroid Build Coastguard Worker
288*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
encode_vfd_new_dmabuf( writer: &mut Writer, vfd_id: u32, flags: u32, pfn: u64, size: u32, desc: GpuMemoryDesc, ) -> WlResult<()>289*bb4ee6a4SAndroid Build Coastguard Worker fn encode_vfd_new_dmabuf(
290*bb4ee6a4SAndroid Build Coastguard Worker writer: &mut Writer,
291*bb4ee6a4SAndroid Build Coastguard Worker vfd_id: u32,
292*bb4ee6a4SAndroid Build Coastguard Worker flags: u32,
293*bb4ee6a4SAndroid Build Coastguard Worker pfn: u64,
294*bb4ee6a4SAndroid Build Coastguard Worker size: u32,
295*bb4ee6a4SAndroid Build Coastguard Worker desc: GpuMemoryDesc,
296*bb4ee6a4SAndroid Build Coastguard Worker ) -> WlResult<()> {
297*bb4ee6a4SAndroid Build Coastguard Worker let ctrl_vfd_new_dmabuf = CtrlVfdNewDmabuf {
298*bb4ee6a4SAndroid Build Coastguard Worker hdr: CtrlHeader {
299*bb4ee6a4SAndroid Build Coastguard Worker type_: Le32::from(VIRTIO_WL_RESP_VFD_NEW_DMABUF),
300*bb4ee6a4SAndroid Build Coastguard Worker flags: Le32::from(0),
301*bb4ee6a4SAndroid Build Coastguard Worker },
302*bb4ee6a4SAndroid Build Coastguard Worker id: Le32::from(vfd_id),
303*bb4ee6a4SAndroid Build Coastguard Worker flags: Le32::from(flags),
304*bb4ee6a4SAndroid Build Coastguard Worker pfn: Le64::from(pfn),
305*bb4ee6a4SAndroid Build Coastguard Worker size: Le32::from(size),
306*bb4ee6a4SAndroid Build Coastguard Worker width: Le32::from(0),
307*bb4ee6a4SAndroid Build Coastguard Worker height: Le32::from(0),
308*bb4ee6a4SAndroid Build Coastguard Worker format: Le32::from(0),
309*bb4ee6a4SAndroid Build Coastguard Worker stride0: Le32::from(desc.planes[0].stride),
310*bb4ee6a4SAndroid Build Coastguard Worker stride1: Le32::from(desc.planes[1].stride),
311*bb4ee6a4SAndroid Build Coastguard Worker stride2: Le32::from(desc.planes[2].stride),
312*bb4ee6a4SAndroid Build Coastguard Worker offset0: Le32::from(desc.planes[0].offset),
313*bb4ee6a4SAndroid Build Coastguard Worker offset1: Le32::from(desc.planes[1].offset),
314*bb4ee6a4SAndroid Build Coastguard Worker offset2: Le32::from(desc.planes[2].offset),
315*bb4ee6a4SAndroid Build Coastguard Worker };
316*bb4ee6a4SAndroid Build Coastguard Worker
317*bb4ee6a4SAndroid Build Coastguard Worker writer
318*bb4ee6a4SAndroid Build Coastguard Worker .write_obj(ctrl_vfd_new_dmabuf)
319*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::WriteResponse)
320*bb4ee6a4SAndroid Build Coastguard Worker }
321*bb4ee6a4SAndroid Build Coastguard Worker
encode_vfd_recv(writer: &mut Writer, vfd_id: u32, data: &[u8], vfd_ids: &[u32]) -> WlResult<()>322*bb4ee6a4SAndroid Build Coastguard Worker fn encode_vfd_recv(writer: &mut Writer, vfd_id: u32, data: &[u8], vfd_ids: &[u32]) -> WlResult<()> {
323*bb4ee6a4SAndroid Build Coastguard Worker let ctrl_vfd_recv = CtrlVfdRecv {
324*bb4ee6a4SAndroid Build Coastguard Worker hdr: CtrlHeader {
325*bb4ee6a4SAndroid Build Coastguard Worker type_: Le32::from(VIRTIO_WL_CMD_VFD_RECV),
326*bb4ee6a4SAndroid Build Coastguard Worker flags: Le32::from(0),
327*bb4ee6a4SAndroid Build Coastguard Worker },
328*bb4ee6a4SAndroid Build Coastguard Worker id: Le32::from(vfd_id),
329*bb4ee6a4SAndroid Build Coastguard Worker vfd_count: Le32::from(vfd_ids.len() as u32),
330*bb4ee6a4SAndroid Build Coastguard Worker };
331*bb4ee6a4SAndroid Build Coastguard Worker writer
332*bb4ee6a4SAndroid Build Coastguard Worker .write_obj(ctrl_vfd_recv)
333*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::WriteResponse)?;
334*bb4ee6a4SAndroid Build Coastguard Worker
335*bb4ee6a4SAndroid Build Coastguard Worker for &recv_vfd_id in vfd_ids.iter() {
336*bb4ee6a4SAndroid Build Coastguard Worker writer
337*bb4ee6a4SAndroid Build Coastguard Worker .write_obj(Le32::from(recv_vfd_id))
338*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::WriteResponse)?;
339*bb4ee6a4SAndroid Build Coastguard Worker }
340*bb4ee6a4SAndroid Build Coastguard Worker
341*bb4ee6a4SAndroid Build Coastguard Worker writer.write_all(data).map_err(WlError::WriteResponse)
342*bb4ee6a4SAndroid Build Coastguard Worker }
343*bb4ee6a4SAndroid Build Coastguard Worker
encode_vfd_hup(writer: &mut Writer, vfd_id: u32) -> WlResult<()>344*bb4ee6a4SAndroid Build Coastguard Worker fn encode_vfd_hup(writer: &mut Writer, vfd_id: u32) -> WlResult<()> {
345*bb4ee6a4SAndroid Build Coastguard Worker let ctrl_vfd_new = CtrlVfd {
346*bb4ee6a4SAndroid Build Coastguard Worker hdr: CtrlHeader {
347*bb4ee6a4SAndroid Build Coastguard Worker type_: Le32::from(VIRTIO_WL_CMD_VFD_HUP),
348*bb4ee6a4SAndroid Build Coastguard Worker flags: Le32::from(0),
349*bb4ee6a4SAndroid Build Coastguard Worker },
350*bb4ee6a4SAndroid Build Coastguard Worker id: Le32::from(vfd_id),
351*bb4ee6a4SAndroid Build Coastguard Worker };
352*bb4ee6a4SAndroid Build Coastguard Worker
353*bb4ee6a4SAndroid Build Coastguard Worker writer
354*bb4ee6a4SAndroid Build Coastguard Worker .write_obj(ctrl_vfd_new)
355*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::WriteResponse)
356*bb4ee6a4SAndroid Build Coastguard Worker }
357*bb4ee6a4SAndroid Build Coastguard Worker
encode_resp(writer: &mut Writer, resp: WlResp) -> WlResult<()>358*bb4ee6a4SAndroid Build Coastguard Worker fn encode_resp(writer: &mut Writer, resp: WlResp) -> WlResult<()> {
359*bb4ee6a4SAndroid Build Coastguard Worker match resp {
360*bb4ee6a4SAndroid Build Coastguard Worker WlResp::VfdNew {
361*bb4ee6a4SAndroid Build Coastguard Worker id,
362*bb4ee6a4SAndroid Build Coastguard Worker flags,
363*bb4ee6a4SAndroid Build Coastguard Worker pfn,
364*bb4ee6a4SAndroid Build Coastguard Worker size,
365*bb4ee6a4SAndroid Build Coastguard Worker resp,
366*bb4ee6a4SAndroid Build Coastguard Worker } => encode_vfd_new(writer, resp, id, flags, pfn, size),
367*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
368*bb4ee6a4SAndroid Build Coastguard Worker WlResp::VfdNewDmabuf {
369*bb4ee6a4SAndroid Build Coastguard Worker id,
370*bb4ee6a4SAndroid Build Coastguard Worker flags,
371*bb4ee6a4SAndroid Build Coastguard Worker pfn,
372*bb4ee6a4SAndroid Build Coastguard Worker size,
373*bb4ee6a4SAndroid Build Coastguard Worker desc,
374*bb4ee6a4SAndroid Build Coastguard Worker } => encode_vfd_new_dmabuf(writer, id, flags, pfn, size, desc),
375*bb4ee6a4SAndroid Build Coastguard Worker WlResp::VfdRecv { id, data, vfds } => encode_vfd_recv(writer, id, data, vfds),
376*bb4ee6a4SAndroid Build Coastguard Worker WlResp::VfdHup { id } => encode_vfd_hup(writer, id),
377*bb4ee6a4SAndroid Build Coastguard Worker r => writer
378*bb4ee6a4SAndroid Build Coastguard Worker .write_obj(Le32::from(r.get_code()))
379*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::WriteResponse),
380*bb4ee6a4SAndroid Build Coastguard Worker }
381*bb4ee6a4SAndroid Build Coastguard Worker }
382*bb4ee6a4SAndroid Build Coastguard Worker
383*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
384*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
385*bb4ee6a4SAndroid Build Coastguard Worker #[derive(ThisError, Debug)]
386*bb4ee6a4SAndroid Build Coastguard Worker enum WlError {
387*bb4ee6a4SAndroid Build Coastguard Worker #[error("overflow in calculation")]
388*bb4ee6a4SAndroid Build Coastguard Worker CheckedOffset,
389*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to synchronize DMABuf access: {0}")]
390*bb4ee6a4SAndroid Build Coastguard Worker DmabufSync(io::Error),
391*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create shared memory from descriptor: {0}")]
392*bb4ee6a4SAndroid Build Coastguard Worker FromSharedMemory(Error),
393*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to get seals: {0}")]
394*bb4ee6a4SAndroid Build Coastguard Worker GetSeals(Error),
395*bb4ee6a4SAndroid Build Coastguard Worker #[error("gralloc error: {0}")]
396*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
397*bb4ee6a4SAndroid Build Coastguard Worker GrallocError(#[from] RutabagaError),
398*bb4ee6a4SAndroid Build Coastguard Worker #[error("access violation in guest memory: {0}")]
399*bb4ee6a4SAndroid Build Coastguard Worker GuestMemory(#[from] GuestMemoryError),
400*bb4ee6a4SAndroid Build Coastguard Worker #[error("invalid string: {0}")]
401*bb4ee6a4SAndroid Build Coastguard Worker InvalidString(std::str::Utf8Error),
402*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create shared memory allocation: {0}")]
403*bb4ee6a4SAndroid Build Coastguard Worker NewAlloc(Error),
404*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create pipe: {0}")]
405*bb4ee6a4SAndroid Build Coastguard Worker NewPipe(Error),
406*bb4ee6a4SAndroid Build Coastguard Worker #[error("error parsing descriptor: {0}")]
407*bb4ee6a4SAndroid Build Coastguard Worker ParseDesc(io::Error),
408*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to read a pipe: {0}")]
409*bb4ee6a4SAndroid Build Coastguard Worker ReadPipe(io::Error),
410*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to recv on a socket: {0}")]
411*bb4ee6a4SAndroid Build Coastguard Worker RecvVfd(io::Error),
412*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to send on a socket: {0}")]
413*bb4ee6a4SAndroid Build Coastguard Worker SendVfd(io::Error),
414*bb4ee6a4SAndroid Build Coastguard Worker #[error("shmem mapper failure: {0}")]
415*bb4ee6a4SAndroid Build Coastguard Worker ShmemMapperError(anyhow::Error),
416*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to connect socket: {0}")]
417*bb4ee6a4SAndroid Build Coastguard Worker SocketConnect(io::Error),
418*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to set socket as non-blocking: {0}")]
419*bb4ee6a4SAndroid Build Coastguard Worker SocketNonBlock(io::Error),
420*bb4ee6a4SAndroid Build Coastguard Worker #[error("unknown socket name: {0}")]
421*bb4ee6a4SAndroid Build Coastguard Worker UnknownSocketName(String),
422*bb4ee6a4SAndroid Build Coastguard Worker #[error("invalid response from parent VM")]
423*bb4ee6a4SAndroid Build Coastguard Worker VmBadResponse,
424*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to control parent VM: {0}")]
425*bb4ee6a4SAndroid Build Coastguard Worker VmControl(TubeError),
426*bb4ee6a4SAndroid Build Coastguard Worker #[error("access violating in guest volatile memory: {0}")]
427*bb4ee6a4SAndroid Build Coastguard Worker VolatileMemory(#[from] VolatileMemoryError),
428*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to listen to descriptor on wait context: {0}")]
429*bb4ee6a4SAndroid Build Coastguard Worker WaitContextAdd(Error),
430*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to write to a pipe: {0}")]
431*bb4ee6a4SAndroid Build Coastguard Worker WritePipe(io::Error),
432*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to write response: {0}")]
433*bb4ee6a4SAndroid Build Coastguard Worker WriteResponse(io::Error),
434*bb4ee6a4SAndroid Build Coastguard Worker }
435*bb4ee6a4SAndroid Build Coastguard Worker
436*bb4ee6a4SAndroid Build Coastguard Worker type WlResult<T> = result::Result<T, WlError>;
437*bb4ee6a4SAndroid Build Coastguard Worker
438*bb4ee6a4SAndroid Build Coastguard Worker pub const WL_SHMEM_ID: u8 = 0;
439*bb4ee6a4SAndroid Build Coastguard Worker pub const WL_SHMEM_SIZE: u64 = 1 << 32;
440*bb4ee6a4SAndroid Build Coastguard Worker
441*bb4ee6a4SAndroid Build Coastguard Worker struct VmRequesterState {
442*bb4ee6a4SAndroid Build Coastguard Worker mapper: Box<dyn SharedMemoryMapper>,
443*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
444*bb4ee6a4SAndroid Build Coastguard Worker gralloc: RutabagaGralloc,
445*bb4ee6a4SAndroid Build Coastguard Worker
446*bb4ee6a4SAndroid Build Coastguard Worker // Allocator for shm address space
447*bb4ee6a4SAndroid Build Coastguard Worker address_allocator: AddressAllocator,
448*bb4ee6a4SAndroid Build Coastguard Worker
449*bb4ee6a4SAndroid Build Coastguard Worker // Map of existing mappings in the shm address space
450*bb4ee6a4SAndroid Build Coastguard Worker allocs: BTreeMap<u64 /* offset */, Alloc>,
451*bb4ee6a4SAndroid Build Coastguard Worker
452*bb4ee6a4SAndroid Build Coastguard Worker // The id for the next shmem allocation
453*bb4ee6a4SAndroid Build Coastguard Worker next_alloc: usize,
454*bb4ee6a4SAndroid Build Coastguard Worker }
455*bb4ee6a4SAndroid Build Coastguard Worker
456*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)]
457*bb4ee6a4SAndroid Build Coastguard Worker struct VmRequester {
458*bb4ee6a4SAndroid Build Coastguard Worker state: Rc<RefCell<VmRequesterState>>,
459*bb4ee6a4SAndroid Build Coastguard Worker }
460*bb4ee6a4SAndroid Build Coastguard Worker
461*bb4ee6a4SAndroid Build Coastguard Worker // The following are wrappers to avoid base dependencies in the rutabaga crate
462*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
to_safe_descriptor(r: RutabagaDescriptor) -> SafeDescriptor463*bb4ee6a4SAndroid Build Coastguard Worker fn to_safe_descriptor(r: RutabagaDescriptor) -> SafeDescriptor {
464*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
465*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we own the SafeDescriptor at this point.
466*bb4ee6a4SAndroid Build Coastguard Worker unsafe { base::FromRawDescriptor::from_raw_descriptor(r.into_raw_descriptor()) }
467*bb4ee6a4SAndroid Build Coastguard Worker }
468*bb4ee6a4SAndroid Build Coastguard Worker
469*bb4ee6a4SAndroid Build Coastguard Worker impl VmRequester {
new( mapper: Box<dyn SharedMemoryMapper>, #[cfg(feature = "minigbm")] gralloc: RutabagaGralloc, ) -> VmRequester470*bb4ee6a4SAndroid Build Coastguard Worker fn new(
471*bb4ee6a4SAndroid Build Coastguard Worker mapper: Box<dyn SharedMemoryMapper>,
472*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")] gralloc: RutabagaGralloc,
473*bb4ee6a4SAndroid Build Coastguard Worker ) -> VmRequester {
474*bb4ee6a4SAndroid Build Coastguard Worker VmRequester {
475*bb4ee6a4SAndroid Build Coastguard Worker state: Rc::new(RefCell::new(VmRequesterState {
476*bb4ee6a4SAndroid Build Coastguard Worker mapper,
477*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
478*bb4ee6a4SAndroid Build Coastguard Worker gralloc,
479*bb4ee6a4SAndroid Build Coastguard Worker address_allocator: AddressAllocator::new(
480*bb4ee6a4SAndroid Build Coastguard Worker AddressRange::from_start_and_size(0, WL_SHMEM_SIZE).unwrap(),
481*bb4ee6a4SAndroid Build Coastguard Worker Some(pagesize() as u64),
482*bb4ee6a4SAndroid Build Coastguard Worker None,
483*bb4ee6a4SAndroid Build Coastguard Worker )
484*bb4ee6a4SAndroid Build Coastguard Worker .expect("failed to create allocator"),
485*bb4ee6a4SAndroid Build Coastguard Worker allocs: BTreeMap::new(),
486*bb4ee6a4SAndroid Build Coastguard Worker next_alloc: 0,
487*bb4ee6a4SAndroid Build Coastguard Worker })),
488*bb4ee6a4SAndroid Build Coastguard Worker }
489*bb4ee6a4SAndroid Build Coastguard Worker }
490*bb4ee6a4SAndroid Build Coastguard Worker
unregister_memory(&self, offset: u64) -> WlResult<()>491*bb4ee6a4SAndroid Build Coastguard Worker fn unregister_memory(&self, offset: u64) -> WlResult<()> {
492*bb4ee6a4SAndroid Build Coastguard Worker let mut state = self.state.borrow_mut();
493*bb4ee6a4SAndroid Build Coastguard Worker state
494*bb4ee6a4SAndroid Build Coastguard Worker .mapper
495*bb4ee6a4SAndroid Build Coastguard Worker .remove_mapping(offset)
496*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ShmemMapperError)?;
497*bb4ee6a4SAndroid Build Coastguard Worker let alloc = state
498*bb4ee6a4SAndroid Build Coastguard Worker .allocs
499*bb4ee6a4SAndroid Build Coastguard Worker .remove(&offset)
500*bb4ee6a4SAndroid Build Coastguard Worker .context("unknown offset")
501*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ShmemMapperError)?;
502*bb4ee6a4SAndroid Build Coastguard Worker state
503*bb4ee6a4SAndroid Build Coastguard Worker .address_allocator
504*bb4ee6a4SAndroid Build Coastguard Worker .release(alloc)
505*bb4ee6a4SAndroid Build Coastguard Worker .expect("corrupt address space");
506*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
507*bb4ee6a4SAndroid Build Coastguard Worker }
508*bb4ee6a4SAndroid Build Coastguard Worker
509*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
allocate_and_register_gpu_memory( &self, width: u32, height: u32, format: u32, ) -> WlResult<(u64, SafeDescriptor, ImageMemoryRequirements)>510*bb4ee6a4SAndroid Build Coastguard Worker fn allocate_and_register_gpu_memory(
511*bb4ee6a4SAndroid Build Coastguard Worker &self,
512*bb4ee6a4SAndroid Build Coastguard Worker width: u32,
513*bb4ee6a4SAndroid Build Coastguard Worker height: u32,
514*bb4ee6a4SAndroid Build Coastguard Worker format: u32,
515*bb4ee6a4SAndroid Build Coastguard Worker ) -> WlResult<(u64, SafeDescriptor, ImageMemoryRequirements)> {
516*bb4ee6a4SAndroid Build Coastguard Worker let mut state = self.state.borrow_mut();
517*bb4ee6a4SAndroid Build Coastguard Worker
518*bb4ee6a4SAndroid Build Coastguard Worker let img = ImageAllocationInfo {
519*bb4ee6a4SAndroid Build Coastguard Worker width,
520*bb4ee6a4SAndroid Build Coastguard Worker height,
521*bb4ee6a4SAndroid Build Coastguard Worker drm_format: DrmFormat::from(format),
522*bb4ee6a4SAndroid Build Coastguard Worker // Linear layout is a requirement as virtio wayland guest expects
523*bb4ee6a4SAndroid Build Coastguard Worker // this for CPU access to the buffer. Scanout and texturing are
524*bb4ee6a4SAndroid Build Coastguard Worker // optional as the consumer (wayland compositor) is expected to
525*bb4ee6a4SAndroid Build Coastguard Worker // fall-back to a less efficient mechanisms for presentation if
526*bb4ee6a4SAndroid Build Coastguard Worker // neccesary. In practice, linear buffers for commonly used formats
527*bb4ee6a4SAndroid Build Coastguard Worker // will also support scanout and texturing.
528*bb4ee6a4SAndroid Build Coastguard Worker flags: RutabagaGrallocFlags::empty().use_linear(true),
529*bb4ee6a4SAndroid Build Coastguard Worker };
530*bb4ee6a4SAndroid Build Coastguard Worker
531*bb4ee6a4SAndroid Build Coastguard Worker let reqs = state
532*bb4ee6a4SAndroid Build Coastguard Worker .gralloc
533*bb4ee6a4SAndroid Build Coastguard Worker .get_image_memory_requirements(img)
534*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::GrallocError)?;
535*bb4ee6a4SAndroid Build Coastguard Worker let handle = state
536*bb4ee6a4SAndroid Build Coastguard Worker .gralloc
537*bb4ee6a4SAndroid Build Coastguard Worker .allocate_memory(reqs)
538*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::GrallocError)?;
539*bb4ee6a4SAndroid Build Coastguard Worker drop(state);
540*bb4ee6a4SAndroid Build Coastguard Worker
541*bb4ee6a4SAndroid Build Coastguard Worker let safe_descriptor = to_safe_descriptor(handle.os_handle);
542*bb4ee6a4SAndroid Build Coastguard Worker self.register_memory(
543*bb4ee6a4SAndroid Build Coastguard Worker safe_descriptor
544*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
545*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to dup gfx handle")
546*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ShmemMapperError)?,
547*bb4ee6a4SAndroid Build Coastguard Worker reqs.size,
548*bb4ee6a4SAndroid Build Coastguard Worker Protection::read_write(),
549*bb4ee6a4SAndroid Build Coastguard Worker )
550*bb4ee6a4SAndroid Build Coastguard Worker .map(|info| (info, safe_descriptor, reqs))
551*bb4ee6a4SAndroid Build Coastguard Worker }
552*bb4ee6a4SAndroid Build Coastguard Worker
register_shmem(&self, shm: &SharedMemory) -> WlResult<u64>553*bb4ee6a4SAndroid Build Coastguard Worker fn register_shmem(&self, shm: &SharedMemory) -> WlResult<u64> {
554*bb4ee6a4SAndroid Build Coastguard Worker let prot = match FileFlags::from_file(shm) {
555*bb4ee6a4SAndroid Build Coastguard Worker Ok(FileFlags::Read) => Protection::read(),
556*bb4ee6a4SAndroid Build Coastguard Worker Ok(FileFlags::Write) => Protection::write(),
557*bb4ee6a4SAndroid Build Coastguard Worker Ok(FileFlags::ReadWrite) => {
558*bb4ee6a4SAndroid Build Coastguard Worker let seals = shm.get_seals().map_err(WlError::GetSeals)?;
559*bb4ee6a4SAndroid Build Coastguard Worker if seals.write_seal() {
560*bb4ee6a4SAndroid Build Coastguard Worker Protection::read()
561*bb4ee6a4SAndroid Build Coastguard Worker } else {
562*bb4ee6a4SAndroid Build Coastguard Worker Protection::read_write()
563*bb4ee6a4SAndroid Build Coastguard Worker }
564*bb4ee6a4SAndroid Build Coastguard Worker }
565*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
566*bb4ee6a4SAndroid Build Coastguard Worker return Err(WlError::ShmemMapperError(anyhow!(
567*bb4ee6a4SAndroid Build Coastguard Worker "failed to get file descriptor flags with error: {:?}",
568*bb4ee6a4SAndroid Build Coastguard Worker e
569*bb4ee6a4SAndroid Build Coastguard Worker )))
570*bb4ee6a4SAndroid Build Coastguard Worker }
571*bb4ee6a4SAndroid Build Coastguard Worker };
572*bb4ee6a4SAndroid Build Coastguard Worker self.register_memory(
573*bb4ee6a4SAndroid Build Coastguard Worker SafeDescriptor::try_from(shm as &dyn AsRawDescriptor)
574*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to create safe descriptor")
575*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ShmemMapperError)?,
576*bb4ee6a4SAndroid Build Coastguard Worker shm.size(),
577*bb4ee6a4SAndroid Build Coastguard Worker prot,
578*bb4ee6a4SAndroid Build Coastguard Worker )
579*bb4ee6a4SAndroid Build Coastguard Worker }
580*bb4ee6a4SAndroid Build Coastguard Worker
register_memory( &self, descriptor: SafeDescriptor, size: u64, prot: Protection, ) -> WlResult<u64>581*bb4ee6a4SAndroid Build Coastguard Worker fn register_memory(
582*bb4ee6a4SAndroid Build Coastguard Worker &self,
583*bb4ee6a4SAndroid Build Coastguard Worker descriptor: SafeDescriptor,
584*bb4ee6a4SAndroid Build Coastguard Worker size: u64,
585*bb4ee6a4SAndroid Build Coastguard Worker prot: Protection,
586*bb4ee6a4SAndroid Build Coastguard Worker ) -> WlResult<u64> {
587*bb4ee6a4SAndroid Build Coastguard Worker let mut state = self.state.borrow_mut();
588*bb4ee6a4SAndroid Build Coastguard Worker let size = round_up_to_page_size(size as usize) as u64;
589*bb4ee6a4SAndroid Build Coastguard Worker
590*bb4ee6a4SAndroid Build Coastguard Worker let source = VmMemorySource::Descriptor {
591*bb4ee6a4SAndroid Build Coastguard Worker descriptor,
592*bb4ee6a4SAndroid Build Coastguard Worker offset: 0,
593*bb4ee6a4SAndroid Build Coastguard Worker size,
594*bb4ee6a4SAndroid Build Coastguard Worker };
595*bb4ee6a4SAndroid Build Coastguard Worker let alloc = Alloc::Anon(state.next_alloc);
596*bb4ee6a4SAndroid Build Coastguard Worker state.next_alloc += 1;
597*bb4ee6a4SAndroid Build Coastguard Worker let offset = state
598*bb4ee6a4SAndroid Build Coastguard Worker .address_allocator
599*bb4ee6a4SAndroid Build Coastguard Worker .allocate(size, alloc, "virtio-wl".to_owned())
600*bb4ee6a4SAndroid Build Coastguard Worker .context("failed to allocate offset")
601*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ShmemMapperError)?;
602*bb4ee6a4SAndroid Build Coastguard Worker
603*bb4ee6a4SAndroid Build Coastguard Worker match state
604*bb4ee6a4SAndroid Build Coastguard Worker .mapper
605*bb4ee6a4SAndroid Build Coastguard Worker .add_mapping(source, offset, prot, MemCacheType::CacheCoherent)
606*bb4ee6a4SAndroid Build Coastguard Worker {
607*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) => {
608*bb4ee6a4SAndroid Build Coastguard Worker state.allocs.insert(offset, alloc);
609*bb4ee6a4SAndroid Build Coastguard Worker Ok(offset)
610*bb4ee6a4SAndroid Build Coastguard Worker }
611*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
612*bb4ee6a4SAndroid Build Coastguard Worker // We just allocated it ourselves, it must exist.
613*bb4ee6a4SAndroid Build Coastguard Worker state
614*bb4ee6a4SAndroid Build Coastguard Worker .address_allocator
615*bb4ee6a4SAndroid Build Coastguard Worker .release(alloc)
616*bb4ee6a4SAndroid Build Coastguard Worker .expect("corrupt address space");
617*bb4ee6a4SAndroid Build Coastguard Worker Err(WlError::ShmemMapperError(e))
618*bb4ee6a4SAndroid Build Coastguard Worker }
619*bb4ee6a4SAndroid Build Coastguard Worker }
620*bb4ee6a4SAndroid Build Coastguard Worker }
621*bb4ee6a4SAndroid Build Coastguard Worker }
622*bb4ee6a4SAndroid Build Coastguard Worker
623*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
624*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default, AsBytes, FromZeroes, FromBytes)]
625*bb4ee6a4SAndroid Build Coastguard Worker struct CtrlHeader {
626*bb4ee6a4SAndroid Build Coastguard Worker type_: Le32,
627*bb4ee6a4SAndroid Build Coastguard Worker flags: Le32,
628*bb4ee6a4SAndroid Build Coastguard Worker }
629*bb4ee6a4SAndroid Build Coastguard Worker
630*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
631*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default, FromZeroes, FromBytes, AsBytes)]
632*bb4ee6a4SAndroid Build Coastguard Worker struct CtrlVfdNew {
633*bb4ee6a4SAndroid Build Coastguard Worker hdr: CtrlHeader,
634*bb4ee6a4SAndroid Build Coastguard Worker id: Le32,
635*bb4ee6a4SAndroid Build Coastguard Worker flags: Le32,
636*bb4ee6a4SAndroid Build Coastguard Worker pfn: Le64,
637*bb4ee6a4SAndroid Build Coastguard Worker size: Le32,
638*bb4ee6a4SAndroid Build Coastguard Worker padding: Le32,
639*bb4ee6a4SAndroid Build Coastguard Worker }
640*bb4ee6a4SAndroid Build Coastguard Worker
641*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
642*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default, FromZeroes, FromBytes)]
643*bb4ee6a4SAndroid Build Coastguard Worker struct CtrlVfdNewCtxNamed {
644*bb4ee6a4SAndroid Build Coastguard Worker hdr: CtrlHeader,
645*bb4ee6a4SAndroid Build Coastguard Worker id: Le32,
646*bb4ee6a4SAndroid Build Coastguard Worker flags: Le32, // Ignored.
647*bb4ee6a4SAndroid Build Coastguard Worker pfn: Le64, // Ignored.
648*bb4ee6a4SAndroid Build Coastguard Worker size: Le32, // Ignored.
649*bb4ee6a4SAndroid Build Coastguard Worker name: [u8; 32],
650*bb4ee6a4SAndroid Build Coastguard Worker }
651*bb4ee6a4SAndroid Build Coastguard Worker
652*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
653*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default, AsBytes, FromZeroes, FromBytes)]
654*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
655*bb4ee6a4SAndroid Build Coastguard Worker struct CtrlVfdNewDmabuf {
656*bb4ee6a4SAndroid Build Coastguard Worker hdr: CtrlHeader,
657*bb4ee6a4SAndroid Build Coastguard Worker id: Le32,
658*bb4ee6a4SAndroid Build Coastguard Worker flags: Le32,
659*bb4ee6a4SAndroid Build Coastguard Worker pfn: Le64,
660*bb4ee6a4SAndroid Build Coastguard Worker size: Le32,
661*bb4ee6a4SAndroid Build Coastguard Worker width: Le32,
662*bb4ee6a4SAndroid Build Coastguard Worker height: Le32,
663*bb4ee6a4SAndroid Build Coastguard Worker format: Le32,
664*bb4ee6a4SAndroid Build Coastguard Worker stride0: Le32,
665*bb4ee6a4SAndroid Build Coastguard Worker stride1: Le32,
666*bb4ee6a4SAndroid Build Coastguard Worker stride2: Le32,
667*bb4ee6a4SAndroid Build Coastguard Worker offset0: Le32,
668*bb4ee6a4SAndroid Build Coastguard Worker offset1: Le32,
669*bb4ee6a4SAndroid Build Coastguard Worker offset2: Le32,
670*bb4ee6a4SAndroid Build Coastguard Worker }
671*bb4ee6a4SAndroid Build Coastguard Worker
672*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
673*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
674*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default, AsBytes, FromZeroes, FromBytes)]
675*bb4ee6a4SAndroid Build Coastguard Worker struct CtrlVfdDmabufSync {
676*bb4ee6a4SAndroid Build Coastguard Worker hdr: CtrlHeader,
677*bb4ee6a4SAndroid Build Coastguard Worker id: Le32,
678*bb4ee6a4SAndroid Build Coastguard Worker flags: Le32,
679*bb4ee6a4SAndroid Build Coastguard Worker }
680*bb4ee6a4SAndroid Build Coastguard Worker
681*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
682*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, AsBytes, FromZeroes, FromBytes)]
683*bb4ee6a4SAndroid Build Coastguard Worker struct CtrlVfdRecv {
684*bb4ee6a4SAndroid Build Coastguard Worker hdr: CtrlHeader,
685*bb4ee6a4SAndroid Build Coastguard Worker id: Le32,
686*bb4ee6a4SAndroid Build Coastguard Worker vfd_count: Le32,
687*bb4ee6a4SAndroid Build Coastguard Worker }
688*bb4ee6a4SAndroid Build Coastguard Worker
689*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
690*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default, AsBytes, FromZeroes, FromBytes)]
691*bb4ee6a4SAndroid Build Coastguard Worker struct CtrlVfd {
692*bb4ee6a4SAndroid Build Coastguard Worker hdr: CtrlHeader,
693*bb4ee6a4SAndroid Build Coastguard Worker id: Le32,
694*bb4ee6a4SAndroid Build Coastguard Worker }
695*bb4ee6a4SAndroid Build Coastguard Worker
696*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
697*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default, AsBytes, FromZeroes, FromBytes)]
698*bb4ee6a4SAndroid Build Coastguard Worker struct CtrlVfdSend {
699*bb4ee6a4SAndroid Build Coastguard Worker hdr: CtrlHeader,
700*bb4ee6a4SAndroid Build Coastguard Worker id: Le32,
701*bb4ee6a4SAndroid Build Coastguard Worker vfd_count: Le32,
702*bb4ee6a4SAndroid Build Coastguard Worker // Remainder is an array of vfd_count IDs followed by data.
703*bb4ee6a4SAndroid Build Coastguard Worker }
704*bb4ee6a4SAndroid Build Coastguard Worker
705*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
706*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Default, AsBytes, FromZeroes, FromBytes)]
707*bb4ee6a4SAndroid Build Coastguard Worker struct CtrlVfdSendVfd {
708*bb4ee6a4SAndroid Build Coastguard Worker kind: Le32,
709*bb4ee6a4SAndroid Build Coastguard Worker id: Le32,
710*bb4ee6a4SAndroid Build Coastguard Worker }
711*bb4ee6a4SAndroid Build Coastguard Worker
712*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
713*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, FromZeroes, FromBytes)]
714*bb4ee6a4SAndroid Build Coastguard Worker union CtrlVfdSendVfdV2Payload {
715*bb4ee6a4SAndroid Build Coastguard Worker id: Le32,
716*bb4ee6a4SAndroid Build Coastguard Worker seqno: Le64,
717*bb4ee6a4SAndroid Build Coastguard Worker }
718*bb4ee6a4SAndroid Build Coastguard Worker
719*bb4ee6a4SAndroid Build Coastguard Worker #[repr(C)]
720*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, FromZeroes, FromBytes)]
721*bb4ee6a4SAndroid Build Coastguard Worker struct CtrlVfdSendVfdV2 {
722*bb4ee6a4SAndroid Build Coastguard Worker kind: Le32,
723*bb4ee6a4SAndroid Build Coastguard Worker payload: CtrlVfdSendVfdV2Payload,
724*bb4ee6a4SAndroid Build Coastguard Worker }
725*bb4ee6a4SAndroid Build Coastguard Worker
726*bb4ee6a4SAndroid Build Coastguard Worker impl CtrlVfdSendVfdV2 {
id(&self) -> Le32727*bb4ee6a4SAndroid Build Coastguard Worker fn id(&self) -> Le32 {
728*bb4ee6a4SAndroid Build Coastguard Worker assert!(
729*bb4ee6a4SAndroid Build Coastguard Worker self.kind == VIRTIO_WL_CTRL_VFD_SEND_KIND_LOCAL
730*bb4ee6a4SAndroid Build Coastguard Worker || self.kind == VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU
731*bb4ee6a4SAndroid Build Coastguard Worker );
732*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: trivially safe given we assert kind
733*bb4ee6a4SAndroid Build Coastguard Worker unsafe { self.payload.id }
734*bb4ee6a4SAndroid Build Coastguard Worker }
735*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
seqno(&self) -> Le64736*bb4ee6a4SAndroid Build Coastguard Worker fn seqno(&self) -> Le64 {
737*bb4ee6a4SAndroid Build Coastguard Worker assert!(self.kind == VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU_FENCE);
738*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: trivially safe given we assert kind
739*bb4ee6a4SAndroid Build Coastguard Worker unsafe { self.payload.seqno }
740*bb4ee6a4SAndroid Build Coastguard Worker }
741*bb4ee6a4SAndroid Build Coastguard Worker }
742*bb4ee6a4SAndroid Build Coastguard Worker
743*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
744*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
745*bb4ee6a4SAndroid Build Coastguard Worker enum WlResp<'a> {
746*bb4ee6a4SAndroid Build Coastguard Worker Ok,
747*bb4ee6a4SAndroid Build Coastguard Worker VfdNew {
748*bb4ee6a4SAndroid Build Coastguard Worker id: u32,
749*bb4ee6a4SAndroid Build Coastguard Worker flags: u32,
750*bb4ee6a4SAndroid Build Coastguard Worker pfn: u64,
751*bb4ee6a4SAndroid Build Coastguard Worker size: u32,
752*bb4ee6a4SAndroid Build Coastguard Worker // The VfdNew variant can be either a response or a command depending on this `resp`. This
753*bb4ee6a4SAndroid Build Coastguard Worker // is important for the `get_code` method.
754*bb4ee6a4SAndroid Build Coastguard Worker resp: bool,
755*bb4ee6a4SAndroid Build Coastguard Worker },
756*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
757*bb4ee6a4SAndroid Build Coastguard Worker VfdNewDmabuf {
758*bb4ee6a4SAndroid Build Coastguard Worker id: u32,
759*bb4ee6a4SAndroid Build Coastguard Worker flags: u32,
760*bb4ee6a4SAndroid Build Coastguard Worker pfn: u64,
761*bb4ee6a4SAndroid Build Coastguard Worker size: u32,
762*bb4ee6a4SAndroid Build Coastguard Worker desc: GpuMemoryDesc,
763*bb4ee6a4SAndroid Build Coastguard Worker },
764*bb4ee6a4SAndroid Build Coastguard Worker VfdRecv {
765*bb4ee6a4SAndroid Build Coastguard Worker id: u32,
766*bb4ee6a4SAndroid Build Coastguard Worker data: &'a [u8],
767*bb4ee6a4SAndroid Build Coastguard Worker vfds: &'a [u32],
768*bb4ee6a4SAndroid Build Coastguard Worker },
769*bb4ee6a4SAndroid Build Coastguard Worker VfdHup {
770*bb4ee6a4SAndroid Build Coastguard Worker id: u32,
771*bb4ee6a4SAndroid Build Coastguard Worker },
772*bb4ee6a4SAndroid Build Coastguard Worker Err(Box<dyn StdError>),
773*bb4ee6a4SAndroid Build Coastguard Worker OutOfMemory,
774*bb4ee6a4SAndroid Build Coastguard Worker InvalidId,
775*bb4ee6a4SAndroid Build Coastguard Worker InvalidType,
776*bb4ee6a4SAndroid Build Coastguard Worker InvalidFlags,
777*bb4ee6a4SAndroid Build Coastguard Worker InvalidCommand,
778*bb4ee6a4SAndroid Build Coastguard Worker }
779*bb4ee6a4SAndroid Build Coastguard Worker
780*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> WlResp<'a> {
get_code(&self) -> u32781*bb4ee6a4SAndroid Build Coastguard Worker fn get_code(&self) -> u32 {
782*bb4ee6a4SAndroid Build Coastguard Worker match *self {
783*bb4ee6a4SAndroid Build Coastguard Worker WlResp::Ok => VIRTIO_WL_RESP_OK,
784*bb4ee6a4SAndroid Build Coastguard Worker WlResp::VfdNew { resp, .. } => {
785*bb4ee6a4SAndroid Build Coastguard Worker if resp {
786*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_RESP_VFD_NEW
787*bb4ee6a4SAndroid Build Coastguard Worker } else {
788*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CMD_VFD_NEW
789*bb4ee6a4SAndroid Build Coastguard Worker }
790*bb4ee6a4SAndroid Build Coastguard Worker }
791*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
792*bb4ee6a4SAndroid Build Coastguard Worker WlResp::VfdNewDmabuf { .. } => VIRTIO_WL_RESP_VFD_NEW_DMABUF,
793*bb4ee6a4SAndroid Build Coastguard Worker WlResp::VfdRecv { .. } => VIRTIO_WL_CMD_VFD_RECV,
794*bb4ee6a4SAndroid Build Coastguard Worker WlResp::VfdHup { .. } => VIRTIO_WL_CMD_VFD_HUP,
795*bb4ee6a4SAndroid Build Coastguard Worker WlResp::Err(_) => VIRTIO_WL_RESP_ERR,
796*bb4ee6a4SAndroid Build Coastguard Worker WlResp::OutOfMemory => VIRTIO_WL_RESP_OUT_OF_MEMORY,
797*bb4ee6a4SAndroid Build Coastguard Worker WlResp::InvalidId => VIRTIO_WL_RESP_INVALID_ID,
798*bb4ee6a4SAndroid Build Coastguard Worker WlResp::InvalidType => VIRTIO_WL_RESP_INVALID_TYPE,
799*bb4ee6a4SAndroid Build Coastguard Worker WlResp::InvalidFlags => VIRTIO_WL_RESP_INVALID_FLAGS,
800*bb4ee6a4SAndroid Build Coastguard Worker WlResp::InvalidCommand => VIRTIO_WL_RESP_INVALID_CMD,
801*bb4ee6a4SAndroid Build Coastguard Worker }
802*bb4ee6a4SAndroid Build Coastguard Worker }
803*bb4ee6a4SAndroid Build Coastguard Worker }
804*bb4ee6a4SAndroid Build Coastguard Worker
805*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Default)]
806*bb4ee6a4SAndroid Build Coastguard Worker struct WlVfd {
807*bb4ee6a4SAndroid Build Coastguard Worker socket: Option<ScmSocket<UnixStream>>,
808*bb4ee6a4SAndroid Build Coastguard Worker guest_shared_memory: Option<SharedMemory>,
809*bb4ee6a4SAndroid Build Coastguard Worker remote_pipe: Option<File>,
810*bb4ee6a4SAndroid Build Coastguard Worker local_pipe: Option<(u32 /* flags */, File)>,
811*bb4ee6a4SAndroid Build Coastguard Worker slot: Option<(u64 /* offset */, VmRequester)>,
812*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
813*bb4ee6a4SAndroid Build Coastguard Worker is_dmabuf: bool,
814*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
815*bb4ee6a4SAndroid Build Coastguard Worker map_info: u32,
816*bb4ee6a4SAndroid Build Coastguard Worker fence: Option<File>,
817*bb4ee6a4SAndroid Build Coastguard Worker is_fence: bool,
818*bb4ee6a4SAndroid Build Coastguard Worker }
819*bb4ee6a4SAndroid Build Coastguard Worker
820*bb4ee6a4SAndroid Build Coastguard Worker impl fmt::Debug for WlVfd {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result821*bb4ee6a4SAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
822*bb4ee6a4SAndroid Build Coastguard Worker write!(f, "WlVfd {{")?;
823*bb4ee6a4SAndroid Build Coastguard Worker if let Some(s) = &self.socket {
824*bb4ee6a4SAndroid Build Coastguard Worker write!(f, " socket: {}", s.as_raw_descriptor())?;
825*bb4ee6a4SAndroid Build Coastguard Worker }
826*bb4ee6a4SAndroid Build Coastguard Worker if let Some((offset, _)) = &self.slot {
827*bb4ee6a4SAndroid Build Coastguard Worker write!(f, " offset: {}", offset)?;
828*bb4ee6a4SAndroid Build Coastguard Worker }
829*bb4ee6a4SAndroid Build Coastguard Worker if let Some(s) = &self.remote_pipe {
830*bb4ee6a4SAndroid Build Coastguard Worker write!(f, " remote: {}", s.as_raw_descriptor())?;
831*bb4ee6a4SAndroid Build Coastguard Worker }
832*bb4ee6a4SAndroid Build Coastguard Worker if let Some((_, s)) = &self.local_pipe {
833*bb4ee6a4SAndroid Build Coastguard Worker write!(f, " local: {}", s.as_raw_descriptor())?;
834*bb4ee6a4SAndroid Build Coastguard Worker }
835*bb4ee6a4SAndroid Build Coastguard Worker write!(f, " }}")
836*bb4ee6a4SAndroid Build Coastguard Worker }
837*bb4ee6a4SAndroid Build Coastguard Worker }
838*bb4ee6a4SAndroid Build Coastguard Worker
839*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
flush_shared_memory(shared_memory: &SharedMemory) -> Result<()>840*bb4ee6a4SAndroid Build Coastguard Worker fn flush_shared_memory(shared_memory: &SharedMemory) -> Result<()> {
841*bb4ee6a4SAndroid Build Coastguard Worker let mmap = match MemoryMappingBuilder::new(shared_memory.size as usize)
842*bb4ee6a4SAndroid Build Coastguard Worker .from_shared_memory(shared_memory)
843*bb4ee6a4SAndroid Build Coastguard Worker .build()
844*bb4ee6a4SAndroid Build Coastguard Worker {
845*bb4ee6a4SAndroid Build Coastguard Worker Ok(v) => v,
846*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => return Err(Error::new(EINVAL)),
847*bb4ee6a4SAndroid Build Coastguard Worker };
848*bb4ee6a4SAndroid Build Coastguard Worker if let Err(err) = mmap.flush_all() {
849*bb4ee6a4SAndroid Build Coastguard Worker base::error!("failed to flush shared memory: {}", err);
850*bb4ee6a4SAndroid Build Coastguard Worker return match err {
851*bb4ee6a4SAndroid Build Coastguard Worker MmapError::NotImplemented(_) => Err(Error::new(ENOSYS)),
852*bb4ee6a4SAndroid Build Coastguard Worker _ => Err(Error::new(EINVAL)),
853*bb4ee6a4SAndroid Build Coastguard Worker };
854*bb4ee6a4SAndroid Build Coastguard Worker }
855*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
856*bb4ee6a4SAndroid Build Coastguard Worker }
857*bb4ee6a4SAndroid Build Coastguard Worker
858*bb4ee6a4SAndroid Build Coastguard Worker impl WlVfd {
connect<P: AsRef<Path>>(path: P) -> WlResult<WlVfd>859*bb4ee6a4SAndroid Build Coastguard Worker fn connect<P: AsRef<Path>>(path: P) -> WlResult<WlVfd> {
860*bb4ee6a4SAndroid Build Coastguard Worker let socket = UnixStream::connect(path).map_err(WlError::SocketConnect)?;
861*bb4ee6a4SAndroid Build Coastguard Worker let mut vfd = WlVfd::default();
862*bb4ee6a4SAndroid Build Coastguard Worker vfd.socket = Some(socket.try_into().map_err(WlError::SocketConnect)?);
863*bb4ee6a4SAndroid Build Coastguard Worker Ok(vfd)
864*bb4ee6a4SAndroid Build Coastguard Worker }
865*bb4ee6a4SAndroid Build Coastguard Worker
allocate(vm: VmRequester, size: u64) -> WlResult<WlVfd>866*bb4ee6a4SAndroid Build Coastguard Worker fn allocate(vm: VmRequester, size: u64) -> WlResult<WlVfd> {
867*bb4ee6a4SAndroid Build Coastguard Worker let size_page_aligned = round_up_to_page_size(size as usize) as u64;
868*bb4ee6a4SAndroid Build Coastguard Worker let vfd_shm =
869*bb4ee6a4SAndroid Build Coastguard Worker SharedMemory::new("virtwl_alloc", size_page_aligned).map_err(WlError::NewAlloc)?;
870*bb4ee6a4SAndroid Build Coastguard Worker
871*bb4ee6a4SAndroid Build Coastguard Worker let offset = vm.register_shmem(&vfd_shm)?;
872*bb4ee6a4SAndroid Build Coastguard Worker
873*bb4ee6a4SAndroid Build Coastguard Worker let mut vfd = WlVfd::default();
874*bb4ee6a4SAndroid Build Coastguard Worker vfd.guest_shared_memory = Some(vfd_shm);
875*bb4ee6a4SAndroid Build Coastguard Worker vfd.slot = Some((offset, vm));
876*bb4ee6a4SAndroid Build Coastguard Worker Ok(vfd)
877*bb4ee6a4SAndroid Build Coastguard Worker }
878*bb4ee6a4SAndroid Build Coastguard Worker
879*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
dmabuf( vm: VmRequester, width: u32, height: u32, format: u32, ) -> WlResult<(WlVfd, GpuMemoryDesc)>880*bb4ee6a4SAndroid Build Coastguard Worker fn dmabuf(
881*bb4ee6a4SAndroid Build Coastguard Worker vm: VmRequester,
882*bb4ee6a4SAndroid Build Coastguard Worker width: u32,
883*bb4ee6a4SAndroid Build Coastguard Worker height: u32,
884*bb4ee6a4SAndroid Build Coastguard Worker format: u32,
885*bb4ee6a4SAndroid Build Coastguard Worker ) -> WlResult<(WlVfd, GpuMemoryDesc)> {
886*bb4ee6a4SAndroid Build Coastguard Worker let (offset, desc, reqs) = vm.allocate_and_register_gpu_memory(width, height, format)?;
887*bb4ee6a4SAndroid Build Coastguard Worker let mut vfd = WlVfd::default();
888*bb4ee6a4SAndroid Build Coastguard Worker let vfd_shm =
889*bb4ee6a4SAndroid Build Coastguard Worker SharedMemory::from_safe_descriptor(desc, reqs.size).map_err(WlError::NewAlloc)?;
890*bb4ee6a4SAndroid Build Coastguard Worker
891*bb4ee6a4SAndroid Build Coastguard Worker let mut desc = GpuMemoryDesc::default();
892*bb4ee6a4SAndroid Build Coastguard Worker for i in 0..3 {
893*bb4ee6a4SAndroid Build Coastguard Worker desc.planes[i] = GpuMemoryPlaneDesc {
894*bb4ee6a4SAndroid Build Coastguard Worker stride: reqs.strides[i],
895*bb4ee6a4SAndroid Build Coastguard Worker offset: reqs.offsets[i],
896*bb4ee6a4SAndroid Build Coastguard Worker }
897*bb4ee6a4SAndroid Build Coastguard Worker }
898*bb4ee6a4SAndroid Build Coastguard Worker
899*bb4ee6a4SAndroid Build Coastguard Worker vfd.guest_shared_memory = Some(vfd_shm);
900*bb4ee6a4SAndroid Build Coastguard Worker vfd.slot = Some((offset, vm));
901*bb4ee6a4SAndroid Build Coastguard Worker vfd.is_dmabuf = true;
902*bb4ee6a4SAndroid Build Coastguard Worker vfd.map_info = reqs.map_info;
903*bb4ee6a4SAndroid Build Coastguard Worker Ok((vfd, desc))
904*bb4ee6a4SAndroid Build Coastguard Worker }
905*bb4ee6a4SAndroid Build Coastguard Worker
906*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
dmabuf_sync(&self, flags: u32) -> WlResult<()>907*bb4ee6a4SAndroid Build Coastguard Worker fn dmabuf_sync(&self, flags: u32) -> WlResult<()> {
908*bb4ee6a4SAndroid Build Coastguard Worker if !self.is_dmabuf {
909*bb4ee6a4SAndroid Build Coastguard Worker return Err(WlError::DmabufSync(io::Error::from_raw_os_error(EINVAL)));
910*bb4ee6a4SAndroid Build Coastguard Worker }
911*bb4ee6a4SAndroid Build Coastguard Worker
912*bb4ee6a4SAndroid Build Coastguard Worker match &self.guest_shared_memory {
913*bb4ee6a4SAndroid Build Coastguard Worker Some(descriptor) => {
914*bb4ee6a4SAndroid Build Coastguard Worker let sync = dma_buf_sync {
915*bb4ee6a4SAndroid Build Coastguard Worker flags: flags as u64,
916*bb4ee6a4SAndroid Build Coastguard Worker };
917*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
918*bb4ee6a4SAndroid Build Coastguard Worker // Safe as descriptor is a valid dmabuf and incorrect flags will return an error.
919*bb4ee6a4SAndroid Build Coastguard Worker if unsafe { ioctl_with_ref(descriptor, DMA_BUF_IOCTL_SYNC, &sync) } < 0 {
920*bb4ee6a4SAndroid Build Coastguard Worker return Err(WlError::DmabufSync(io::Error::last_os_error()));
921*bb4ee6a4SAndroid Build Coastguard Worker }
922*bb4ee6a4SAndroid Build Coastguard Worker
923*bb4ee6a4SAndroid Build Coastguard Worker // virtio-wl kernel driver always maps dmabufs with WB memory type, regardless of
924*bb4ee6a4SAndroid Build Coastguard Worker // the host memory type (which is wrong). However, to avoid changing the protocol,
925*bb4ee6a4SAndroid Build Coastguard Worker // assume that all guest writes are cached and ensure clflush-like ops on all mapped
926*bb4ee6a4SAndroid Build Coastguard Worker // cachelines if the host mapping is not cached.
927*bb4ee6a4SAndroid Build Coastguard Worker const END_WRITE_MASK: u32 = DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_END;
928*bb4ee6a4SAndroid Build Coastguard Worker if (flags & END_WRITE_MASK) == END_WRITE_MASK
929*bb4ee6a4SAndroid Build Coastguard Worker && (self.map_info & RUTABAGA_MAP_CACHE_MASK) != RUTABAGA_MAP_CACHE_CACHED
930*bb4ee6a4SAndroid Build Coastguard Worker {
931*bb4ee6a4SAndroid Build Coastguard Worker if let Err(err) = flush_shared_memory(descriptor) {
932*bb4ee6a4SAndroid Build Coastguard Worker base::warn!("failed to flush cached dmabuf mapping: {:?}", err);
933*bb4ee6a4SAndroid Build Coastguard Worker return Err(WlError::DmabufSync(io::Error::from_raw_os_error(
934*bb4ee6a4SAndroid Build Coastguard Worker err.errno(),
935*bb4ee6a4SAndroid Build Coastguard Worker )));
936*bb4ee6a4SAndroid Build Coastguard Worker }
937*bb4ee6a4SAndroid Build Coastguard Worker }
938*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
939*bb4ee6a4SAndroid Build Coastguard Worker }
940*bb4ee6a4SAndroid Build Coastguard Worker None => Err(WlError::DmabufSync(io::Error::from_raw_os_error(EBADF))),
941*bb4ee6a4SAndroid Build Coastguard Worker }
942*bb4ee6a4SAndroid Build Coastguard Worker }
943*bb4ee6a4SAndroid Build Coastguard Worker
pipe_remote_read_local_write() -> WlResult<WlVfd>944*bb4ee6a4SAndroid Build Coastguard Worker fn pipe_remote_read_local_write() -> WlResult<WlVfd> {
945*bb4ee6a4SAndroid Build Coastguard Worker let (read_pipe, write_pipe) = pipe().map_err(WlError::NewPipe)?;
946*bb4ee6a4SAndroid Build Coastguard Worker let mut vfd = WlVfd::default();
947*bb4ee6a4SAndroid Build Coastguard Worker vfd.remote_pipe = Some(read_pipe);
948*bb4ee6a4SAndroid Build Coastguard Worker vfd.local_pipe = Some((VIRTIO_WL_VFD_WRITE, write_pipe));
949*bb4ee6a4SAndroid Build Coastguard Worker Ok(vfd)
950*bb4ee6a4SAndroid Build Coastguard Worker }
951*bb4ee6a4SAndroid Build Coastguard Worker
pipe_remote_write_local_read() -> WlResult<WlVfd>952*bb4ee6a4SAndroid Build Coastguard Worker fn pipe_remote_write_local_read() -> WlResult<WlVfd> {
953*bb4ee6a4SAndroid Build Coastguard Worker let (read_pipe, write_pipe) = pipe().map_err(WlError::NewPipe)?;
954*bb4ee6a4SAndroid Build Coastguard Worker let mut vfd = WlVfd::default();
955*bb4ee6a4SAndroid Build Coastguard Worker vfd.remote_pipe = Some(write_pipe);
956*bb4ee6a4SAndroid Build Coastguard Worker vfd.local_pipe = Some((VIRTIO_WL_VFD_READ, read_pipe));
957*bb4ee6a4SAndroid Build Coastguard Worker Ok(vfd)
958*bb4ee6a4SAndroid Build Coastguard Worker }
959*bb4ee6a4SAndroid Build Coastguard Worker
from_file(vm: VmRequester, mut descriptor: File) -> WlResult<WlVfd>960*bb4ee6a4SAndroid Build Coastguard Worker fn from_file(vm: VmRequester, mut descriptor: File) -> WlResult<WlVfd> {
961*bb4ee6a4SAndroid Build Coastguard Worker // We need to determine if the given file is more like shared memory or a pipe/socket. A
962*bb4ee6a4SAndroid Build Coastguard Worker // quick and easy check is to seek to the end of the file. If it works we assume it's not a
963*bb4ee6a4SAndroid Build Coastguard Worker // pipe/socket because those have no end. We can even use that seek location as an indicator
964*bb4ee6a4SAndroid Build Coastguard Worker // for how big the shared memory chunk to map into guest memory is. If seeking to the end
965*bb4ee6a4SAndroid Build Coastguard Worker // fails, we assume it's a socket or pipe with read/write semantics.
966*bb4ee6a4SAndroid Build Coastguard Worker if descriptor.seek(SeekFrom::End(0)).is_ok() {
967*bb4ee6a4SAndroid Build Coastguard Worker let shm = SharedMemory::from_file(descriptor).map_err(WlError::FromSharedMemory)?;
968*bb4ee6a4SAndroid Build Coastguard Worker let offset = vm.register_shmem(&shm)?;
969*bb4ee6a4SAndroid Build Coastguard Worker
970*bb4ee6a4SAndroid Build Coastguard Worker let mut vfd = WlVfd::default();
971*bb4ee6a4SAndroid Build Coastguard Worker vfd.guest_shared_memory = Some(shm);
972*bb4ee6a4SAndroid Build Coastguard Worker vfd.slot = Some((offset, vm));
973*bb4ee6a4SAndroid Build Coastguard Worker Ok(vfd)
974*bb4ee6a4SAndroid Build Coastguard Worker } else if is_fence(&descriptor) {
975*bb4ee6a4SAndroid Build Coastguard Worker let mut vfd = WlVfd::default();
976*bb4ee6a4SAndroid Build Coastguard Worker vfd.is_fence = true;
977*bb4ee6a4SAndroid Build Coastguard Worker vfd.fence = Some(descriptor);
978*bb4ee6a4SAndroid Build Coastguard Worker Ok(vfd)
979*bb4ee6a4SAndroid Build Coastguard Worker } else {
980*bb4ee6a4SAndroid Build Coastguard Worker let flags = match FileFlags::from_file(&descriptor) {
981*bb4ee6a4SAndroid Build Coastguard Worker Ok(FileFlags::Read) => VIRTIO_WL_VFD_READ,
982*bb4ee6a4SAndroid Build Coastguard Worker Ok(FileFlags::Write) => VIRTIO_WL_VFD_WRITE,
983*bb4ee6a4SAndroid Build Coastguard Worker Ok(FileFlags::ReadWrite) => VIRTIO_WL_VFD_READ | VIRTIO_WL_VFD_WRITE,
984*bb4ee6a4SAndroid Build Coastguard Worker _ => 0,
985*bb4ee6a4SAndroid Build Coastguard Worker };
986*bb4ee6a4SAndroid Build Coastguard Worker let mut vfd = WlVfd::default();
987*bb4ee6a4SAndroid Build Coastguard Worker vfd.local_pipe = Some((flags, descriptor));
988*bb4ee6a4SAndroid Build Coastguard Worker Ok(vfd)
989*bb4ee6a4SAndroid Build Coastguard Worker }
990*bb4ee6a4SAndroid Build Coastguard Worker }
991*bb4ee6a4SAndroid Build Coastguard Worker
flags(&self, use_transition_flags: bool) -> u32992*bb4ee6a4SAndroid Build Coastguard Worker fn flags(&self, use_transition_flags: bool) -> u32 {
993*bb4ee6a4SAndroid Build Coastguard Worker let mut flags = 0;
994*bb4ee6a4SAndroid Build Coastguard Worker if use_transition_flags {
995*bb4ee6a4SAndroid Build Coastguard Worker if self.socket.is_some() {
996*bb4ee6a4SAndroid Build Coastguard Worker flags |= VIRTIO_WL_VFD_WRITE | VIRTIO_WL_VFD_READ;
997*bb4ee6a4SAndroid Build Coastguard Worker }
998*bb4ee6a4SAndroid Build Coastguard Worker if let Some((f, _)) = self.local_pipe {
999*bb4ee6a4SAndroid Build Coastguard Worker flags |= f;
1000*bb4ee6a4SAndroid Build Coastguard Worker }
1001*bb4ee6a4SAndroid Build Coastguard Worker if self.is_fence {
1002*bb4ee6a4SAndroid Build Coastguard Worker flags |= VIRTIO_WL_VFD_FENCE;
1003*bb4ee6a4SAndroid Build Coastguard Worker }
1004*bb4ee6a4SAndroid Build Coastguard Worker } else {
1005*bb4ee6a4SAndroid Build Coastguard Worker if self.socket.is_some() {
1006*bb4ee6a4SAndroid Build Coastguard Worker flags |= VIRTIO_WL_VFD_CONTROL;
1007*bb4ee6a4SAndroid Build Coastguard Worker }
1008*bb4ee6a4SAndroid Build Coastguard Worker if self.slot.is_some() {
1009*bb4ee6a4SAndroid Build Coastguard Worker flags |= VIRTIO_WL_VFD_WRITE | VIRTIO_WL_VFD_MAP
1010*bb4ee6a4SAndroid Build Coastguard Worker }
1011*bb4ee6a4SAndroid Build Coastguard Worker }
1012*bb4ee6a4SAndroid Build Coastguard Worker flags
1013*bb4ee6a4SAndroid Build Coastguard Worker }
1014*bb4ee6a4SAndroid Build Coastguard Worker
1015*bb4ee6a4SAndroid Build Coastguard Worker // Offset within the shared memory region this VFD was mapped at.
offset(&self) -> Option<u64>1016*bb4ee6a4SAndroid Build Coastguard Worker fn offset(&self) -> Option<u64> {
1017*bb4ee6a4SAndroid Build Coastguard Worker self.slot.as_ref().map(|s| s.0)
1018*bb4ee6a4SAndroid Build Coastguard Worker }
1019*bb4ee6a4SAndroid Build Coastguard Worker
1020*bb4ee6a4SAndroid Build Coastguard Worker // Size in bytes of the shared memory VFD.
size(&self) -> Option<u64>1021*bb4ee6a4SAndroid Build Coastguard Worker fn size(&self) -> Option<u64> {
1022*bb4ee6a4SAndroid Build Coastguard Worker self.guest_shared_memory.as_ref().map(|shm| shm.size())
1023*bb4ee6a4SAndroid Build Coastguard Worker }
1024*bb4ee6a4SAndroid Build Coastguard Worker
1025*bb4ee6a4SAndroid Build Coastguard Worker // The descriptor that gets sent if this VFD is sent over a socket.
send_descriptor(&self) -> Option<RawDescriptor>1026*bb4ee6a4SAndroid Build Coastguard Worker fn send_descriptor(&self) -> Option<RawDescriptor> {
1027*bb4ee6a4SAndroid Build Coastguard Worker self.guest_shared_memory
1028*bb4ee6a4SAndroid Build Coastguard Worker .as_ref()
1029*bb4ee6a4SAndroid Build Coastguard Worker .map(|shm| shm.as_raw_descriptor())
1030*bb4ee6a4SAndroid Build Coastguard Worker .or(self.socket.as_ref().map(|s| s.as_raw_descriptor()))
1031*bb4ee6a4SAndroid Build Coastguard Worker .or(self.remote_pipe.as_ref().map(|p| p.as_raw_descriptor()))
1032*bb4ee6a4SAndroid Build Coastguard Worker .or(self.fence.as_ref().map(|f| f.as_raw_descriptor()))
1033*bb4ee6a4SAndroid Build Coastguard Worker }
1034*bb4ee6a4SAndroid Build Coastguard Worker
1035*bb4ee6a4SAndroid Build Coastguard Worker // The FD that is used for polling for events on this VFD.
wait_descriptor(&self) -> Option<&dyn AsRawDescriptor>1036*bb4ee6a4SAndroid Build Coastguard Worker fn wait_descriptor(&self) -> Option<&dyn AsRawDescriptor> {
1037*bb4ee6a4SAndroid Build Coastguard Worker self.socket
1038*bb4ee6a4SAndroid Build Coastguard Worker .as_ref()
1039*bb4ee6a4SAndroid Build Coastguard Worker .map(|s| s as &dyn AsRawDescriptor)
1040*bb4ee6a4SAndroid Build Coastguard Worker .or_else(|| {
1041*bb4ee6a4SAndroid Build Coastguard Worker self.local_pipe
1042*bb4ee6a4SAndroid Build Coastguard Worker .as_ref()
1043*bb4ee6a4SAndroid Build Coastguard Worker .map(|(_, p)| p as &dyn AsRawDescriptor)
1044*bb4ee6a4SAndroid Build Coastguard Worker })
1045*bb4ee6a4SAndroid Build Coastguard Worker .or_else(|| self.fence.as_ref().map(|f| f as &dyn AsRawDescriptor))
1046*bb4ee6a4SAndroid Build Coastguard Worker }
1047*bb4ee6a4SAndroid Build Coastguard Worker
1048*bb4ee6a4SAndroid Build Coastguard Worker // Sends data/files from the guest to the host over this VFD.
send(&mut self, rds: &[RawDescriptor], data: &mut Reader) -> WlResult<WlResp>1049*bb4ee6a4SAndroid Build Coastguard Worker fn send(&mut self, rds: &[RawDescriptor], data: &mut Reader) -> WlResult<WlResp> {
1050*bb4ee6a4SAndroid Build Coastguard Worker if let Some(socket) = &self.socket {
1051*bb4ee6a4SAndroid Build Coastguard Worker socket
1052*bb4ee6a4SAndroid Build Coastguard Worker .send_vectored_with_fds(&data.get_remaining(), rds)
1053*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::SendVfd)?;
1054*bb4ee6a4SAndroid Build Coastguard Worker // All remaining data in `data` is now considered consumed.
1055*bb4ee6a4SAndroid Build Coastguard Worker data.consume(usize::MAX);
1056*bb4ee6a4SAndroid Build Coastguard Worker Ok(WlResp::Ok)
1057*bb4ee6a4SAndroid Build Coastguard Worker } else if let Some((_, local_pipe)) = &mut self.local_pipe {
1058*bb4ee6a4SAndroid Build Coastguard Worker // Impossible to send descriptors over a simple pipe.
1059*bb4ee6a4SAndroid Build Coastguard Worker if !rds.is_empty() {
1060*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidType);
1061*bb4ee6a4SAndroid Build Coastguard Worker }
1062*bb4ee6a4SAndroid Build Coastguard Worker data.read_to(local_pipe, usize::MAX)
1063*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::WritePipe)?;
1064*bb4ee6a4SAndroid Build Coastguard Worker Ok(WlResp::Ok)
1065*bb4ee6a4SAndroid Build Coastguard Worker } else {
1066*bb4ee6a4SAndroid Build Coastguard Worker Ok(WlResp::InvalidType)
1067*bb4ee6a4SAndroid Build Coastguard Worker }
1068*bb4ee6a4SAndroid Build Coastguard Worker }
1069*bb4ee6a4SAndroid Build Coastguard Worker
1070*bb4ee6a4SAndroid Build Coastguard Worker // Receives data/files from the host for this VFD and queues it for the guest.
recv(&mut self, in_file_queue: &mut Vec<File>) -> WlResult<Vec<u8>>1071*bb4ee6a4SAndroid Build Coastguard Worker fn recv(&mut self, in_file_queue: &mut Vec<File>) -> WlResult<Vec<u8>> {
1072*bb4ee6a4SAndroid Build Coastguard Worker if let Some(socket) = self.socket.take() {
1073*bb4ee6a4SAndroid Build Coastguard Worker let mut buf = vec![0; IN_BUFFER_LEN];
1074*bb4ee6a4SAndroid Build Coastguard Worker // If any errors happen, the socket will get dropped, preventing more reading.
1075*bb4ee6a4SAndroid Build Coastguard Worker let (len, descriptors) = socket
1076*bb4ee6a4SAndroid Build Coastguard Worker .recv_with_fds(&mut buf, VIRTWL_SEND_MAX_ALLOCS)
1077*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::RecvVfd)?;
1078*bb4ee6a4SAndroid Build Coastguard Worker // If any data gets read, the put the socket back for future recv operations.
1079*bb4ee6a4SAndroid Build Coastguard Worker if len != 0 || !descriptors.is_empty() {
1080*bb4ee6a4SAndroid Build Coastguard Worker buf.truncate(len);
1081*bb4ee6a4SAndroid Build Coastguard Worker buf.shrink_to_fit();
1082*bb4ee6a4SAndroid Build Coastguard Worker self.socket = Some(socket);
1083*bb4ee6a4SAndroid Build Coastguard Worker in_file_queue.extend(descriptors.into_iter().map(File::from));
1084*bb4ee6a4SAndroid Build Coastguard Worker return Ok(buf);
1085*bb4ee6a4SAndroid Build Coastguard Worker }
1086*bb4ee6a4SAndroid Build Coastguard Worker Ok(Vec::new())
1087*bb4ee6a4SAndroid Build Coastguard Worker } else if let Some((flags, mut local_pipe)) = self.local_pipe.take() {
1088*bb4ee6a4SAndroid Build Coastguard Worker let mut buf = vec![0; IN_BUFFER_LEN];
1089*bb4ee6a4SAndroid Build Coastguard Worker let len = local_pipe.read(&mut buf[..]).map_err(WlError::ReadPipe)?;
1090*bb4ee6a4SAndroid Build Coastguard Worker if len != 0 {
1091*bb4ee6a4SAndroid Build Coastguard Worker buf.truncate(len);
1092*bb4ee6a4SAndroid Build Coastguard Worker buf.shrink_to_fit();
1093*bb4ee6a4SAndroid Build Coastguard Worker self.local_pipe = Some((flags, local_pipe));
1094*bb4ee6a4SAndroid Build Coastguard Worker return Ok(buf);
1095*bb4ee6a4SAndroid Build Coastguard Worker }
1096*bb4ee6a4SAndroid Build Coastguard Worker Ok(Vec::new())
1097*bb4ee6a4SAndroid Build Coastguard Worker } else {
1098*bb4ee6a4SAndroid Build Coastguard Worker Ok(Vec::new())
1099*bb4ee6a4SAndroid Build Coastguard Worker }
1100*bb4ee6a4SAndroid Build Coastguard Worker }
1101*bb4ee6a4SAndroid Build Coastguard Worker
1102*bb4ee6a4SAndroid Build Coastguard Worker // Called after this VFD is sent over a socket to ensure the local end of the VFD receives hang
1103*bb4ee6a4SAndroid Build Coastguard Worker // up events.
close_remote(&mut self)1104*bb4ee6a4SAndroid Build Coastguard Worker fn close_remote(&mut self) {
1105*bb4ee6a4SAndroid Build Coastguard Worker self.remote_pipe = None;
1106*bb4ee6a4SAndroid Build Coastguard Worker }
1107*bb4ee6a4SAndroid Build Coastguard Worker
close(&mut self) -> WlResult<()>1108*bb4ee6a4SAndroid Build Coastguard Worker fn close(&mut self) -> WlResult<()> {
1109*bb4ee6a4SAndroid Build Coastguard Worker if let Some((offset, vm)) = self.slot.take() {
1110*bb4ee6a4SAndroid Build Coastguard Worker vm.unregister_memory(offset)?;
1111*bb4ee6a4SAndroid Build Coastguard Worker }
1112*bb4ee6a4SAndroid Build Coastguard Worker self.socket = None;
1113*bb4ee6a4SAndroid Build Coastguard Worker self.remote_pipe = None;
1114*bb4ee6a4SAndroid Build Coastguard Worker self.local_pipe = None;
1115*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
1116*bb4ee6a4SAndroid Build Coastguard Worker }
1117*bb4ee6a4SAndroid Build Coastguard Worker }
1118*bb4ee6a4SAndroid Build Coastguard Worker
1119*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for WlVfd {
drop(&mut self)1120*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) {
1121*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.close();
1122*bb4ee6a4SAndroid Build Coastguard Worker }
1123*bb4ee6a4SAndroid Build Coastguard Worker }
1124*bb4ee6a4SAndroid Build Coastguard Worker
1125*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
1126*bb4ee6a4SAndroid Build Coastguard Worker enum WlRecv {
1127*bb4ee6a4SAndroid Build Coastguard Worker Vfd { id: u32 },
1128*bb4ee6a4SAndroid Build Coastguard Worker Data { buf: Vec<u8> },
1129*bb4ee6a4SAndroid Build Coastguard Worker Hup,
1130*bb4ee6a4SAndroid Build Coastguard Worker }
1131*bb4ee6a4SAndroid Build Coastguard Worker
1132*bb4ee6a4SAndroid Build Coastguard Worker pub struct WlState {
1133*bb4ee6a4SAndroid Build Coastguard Worker wayland_paths: BTreeMap<String, PathBuf>,
1134*bb4ee6a4SAndroid Build Coastguard Worker vm: VmRequester,
1135*bb4ee6a4SAndroid Build Coastguard Worker resource_bridge: Option<Tube>,
1136*bb4ee6a4SAndroid Build Coastguard Worker use_transition_flags: bool,
1137*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx: WaitContext<u32>,
1138*bb4ee6a4SAndroid Build Coastguard Worker vfds: BTreeMap<u32, WlVfd>,
1139*bb4ee6a4SAndroid Build Coastguard Worker next_vfd_id: u32,
1140*bb4ee6a4SAndroid Build Coastguard Worker in_file_queue: Vec<File>,
1141*bb4ee6a4SAndroid Build Coastguard Worker in_queue: VecDeque<(u32 /* vfd_id */, WlRecv)>,
1142*bb4ee6a4SAndroid Build Coastguard Worker current_recv_vfd: Option<u32>,
1143*bb4ee6a4SAndroid Build Coastguard Worker recv_vfds: Vec<u32>,
1144*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
1145*bb4ee6a4SAndroid Build Coastguard Worker signaled_fence: Option<SafeDescriptor>,
1146*bb4ee6a4SAndroid Build Coastguard Worker use_send_vfd_v2: bool,
1147*bb4ee6a4SAndroid Build Coastguard Worker address_offset: Option<u64>,
1148*bb4ee6a4SAndroid Build Coastguard Worker }
1149*bb4ee6a4SAndroid Build Coastguard Worker
1150*bb4ee6a4SAndroid Build Coastguard Worker impl WlState {
1151*bb4ee6a4SAndroid Build Coastguard Worker /// Create a new `WlState` instance for running a virtio-wl device.
new( wayland_paths: BTreeMap<String, PathBuf>, mapper: Box<dyn SharedMemoryMapper>, use_transition_flags: bool, use_send_vfd_v2: bool, resource_bridge: Option<Tube>, #[cfg(feature = "minigbm")] gralloc: RutabagaGralloc, address_offset: Option<u64>, ) -> WlState1152*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(
1153*bb4ee6a4SAndroid Build Coastguard Worker wayland_paths: BTreeMap<String, PathBuf>,
1154*bb4ee6a4SAndroid Build Coastguard Worker mapper: Box<dyn SharedMemoryMapper>,
1155*bb4ee6a4SAndroid Build Coastguard Worker use_transition_flags: bool,
1156*bb4ee6a4SAndroid Build Coastguard Worker use_send_vfd_v2: bool,
1157*bb4ee6a4SAndroid Build Coastguard Worker resource_bridge: Option<Tube>,
1158*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")] gralloc: RutabagaGralloc,
1159*bb4ee6a4SAndroid Build Coastguard Worker address_offset: Option<u64>,
1160*bb4ee6a4SAndroid Build Coastguard Worker ) -> WlState {
1161*bb4ee6a4SAndroid Build Coastguard Worker WlState {
1162*bb4ee6a4SAndroid Build Coastguard Worker wayland_paths,
1163*bb4ee6a4SAndroid Build Coastguard Worker vm: VmRequester::new(
1164*bb4ee6a4SAndroid Build Coastguard Worker mapper,
1165*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
1166*bb4ee6a4SAndroid Build Coastguard Worker gralloc,
1167*bb4ee6a4SAndroid Build Coastguard Worker ),
1168*bb4ee6a4SAndroid Build Coastguard Worker resource_bridge,
1169*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx: WaitContext::new().expect("failed to create WaitContext"),
1170*bb4ee6a4SAndroid Build Coastguard Worker use_transition_flags,
1171*bb4ee6a4SAndroid Build Coastguard Worker vfds: BTreeMap::new(),
1172*bb4ee6a4SAndroid Build Coastguard Worker next_vfd_id: NEXT_VFD_ID_BASE,
1173*bb4ee6a4SAndroid Build Coastguard Worker in_file_queue: Vec::new(),
1174*bb4ee6a4SAndroid Build Coastguard Worker in_queue: VecDeque::new(),
1175*bb4ee6a4SAndroid Build Coastguard Worker current_recv_vfd: None,
1176*bb4ee6a4SAndroid Build Coastguard Worker recv_vfds: Vec::new(),
1177*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
1178*bb4ee6a4SAndroid Build Coastguard Worker signaled_fence: None,
1179*bb4ee6a4SAndroid Build Coastguard Worker use_send_vfd_v2,
1180*bb4ee6a4SAndroid Build Coastguard Worker address_offset,
1181*bb4ee6a4SAndroid Build Coastguard Worker }
1182*bb4ee6a4SAndroid Build Coastguard Worker }
1183*bb4ee6a4SAndroid Build Coastguard Worker
1184*bb4ee6a4SAndroid Build Coastguard Worker /// This is a hack so that we can drive the inner WaitContext from an async fn. The proper
1185*bb4ee6a4SAndroid Build Coastguard Worker /// long-term solution is to replace the WaitContext completely by spawning async workers
1186*bb4ee6a4SAndroid Build Coastguard Worker /// instead.
wait_ctx(&self) -> &WaitContext<u32>1187*bb4ee6a4SAndroid Build Coastguard Worker pub fn wait_ctx(&self) -> &WaitContext<u32> {
1188*bb4ee6a4SAndroid Build Coastguard Worker &self.wait_ctx
1189*bb4ee6a4SAndroid Build Coastguard Worker }
1190*bb4ee6a4SAndroid Build Coastguard Worker
new_pipe(&mut self, id: u32, flags: u32) -> WlResult<WlResp>1191*bb4ee6a4SAndroid Build Coastguard Worker fn new_pipe(&mut self, id: u32, flags: u32) -> WlResult<WlResp> {
1192*bb4ee6a4SAndroid Build Coastguard Worker if id & VFD_ID_HOST_MASK != 0 {
1193*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidId);
1194*bb4ee6a4SAndroid Build Coastguard Worker }
1195*bb4ee6a4SAndroid Build Coastguard Worker
1196*bb4ee6a4SAndroid Build Coastguard Worker if flags & !(VIRTIO_WL_VFD_WRITE | VIRTIO_WL_VFD_READ) != 0 {
1197*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidFlags);
1198*bb4ee6a4SAndroid Build Coastguard Worker }
1199*bb4ee6a4SAndroid Build Coastguard Worker
1200*bb4ee6a4SAndroid Build Coastguard Worker if flags & VIRTIO_WL_VFD_WRITE != 0 && flags & VIRTIO_WL_VFD_READ != 0 {
1201*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidFlags);
1202*bb4ee6a4SAndroid Build Coastguard Worker }
1203*bb4ee6a4SAndroid Build Coastguard Worker
1204*bb4ee6a4SAndroid Build Coastguard Worker match self.vfds.entry(id) {
1205*bb4ee6a4SAndroid Build Coastguard Worker Entry::Vacant(entry) => {
1206*bb4ee6a4SAndroid Build Coastguard Worker let vfd = if flags & VIRTIO_WL_VFD_WRITE != 0 {
1207*bb4ee6a4SAndroid Build Coastguard Worker WlVfd::pipe_remote_read_local_write()?
1208*bb4ee6a4SAndroid Build Coastguard Worker } else if flags & VIRTIO_WL_VFD_READ != 0 {
1209*bb4ee6a4SAndroid Build Coastguard Worker WlVfd::pipe_remote_write_local_read()?
1210*bb4ee6a4SAndroid Build Coastguard Worker } else {
1211*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidFlags);
1212*bb4ee6a4SAndroid Build Coastguard Worker };
1213*bb4ee6a4SAndroid Build Coastguard Worker self.wait_ctx
1214*bb4ee6a4SAndroid Build Coastguard Worker .add(vfd.wait_descriptor().unwrap(), id)
1215*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::WaitContextAdd)?;
1216*bb4ee6a4SAndroid Build Coastguard Worker let resp = WlResp::VfdNew {
1217*bb4ee6a4SAndroid Build Coastguard Worker id,
1218*bb4ee6a4SAndroid Build Coastguard Worker flags: 0,
1219*bb4ee6a4SAndroid Build Coastguard Worker pfn: 0,
1220*bb4ee6a4SAndroid Build Coastguard Worker size: 0,
1221*bb4ee6a4SAndroid Build Coastguard Worker resp: true,
1222*bb4ee6a4SAndroid Build Coastguard Worker };
1223*bb4ee6a4SAndroid Build Coastguard Worker entry.insert(vfd);
1224*bb4ee6a4SAndroid Build Coastguard Worker Ok(resp)
1225*bb4ee6a4SAndroid Build Coastguard Worker }
1226*bb4ee6a4SAndroid Build Coastguard Worker Entry::Occupied(_) => Ok(WlResp::InvalidId),
1227*bb4ee6a4SAndroid Build Coastguard Worker }
1228*bb4ee6a4SAndroid Build Coastguard Worker }
1229*bb4ee6a4SAndroid Build Coastguard Worker
new_alloc(&mut self, id: u32, flags: u32, size: u32) -> WlResult<WlResp>1230*bb4ee6a4SAndroid Build Coastguard Worker fn new_alloc(&mut self, id: u32, flags: u32, size: u32) -> WlResult<WlResp> {
1231*bb4ee6a4SAndroid Build Coastguard Worker if id & VFD_ID_HOST_MASK != 0 {
1232*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidId);
1233*bb4ee6a4SAndroid Build Coastguard Worker }
1234*bb4ee6a4SAndroid Build Coastguard Worker
1235*bb4ee6a4SAndroid Build Coastguard Worker if self.use_transition_flags {
1236*bb4ee6a4SAndroid Build Coastguard Worker if flags != 0 {
1237*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidFlags);
1238*bb4ee6a4SAndroid Build Coastguard Worker }
1239*bb4ee6a4SAndroid Build Coastguard Worker } else if flags & !(VIRTIO_WL_VFD_WRITE | VIRTIO_WL_VFD_MAP) != 0 {
1240*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::Err(Box::from("invalid flags")));
1241*bb4ee6a4SAndroid Build Coastguard Worker }
1242*bb4ee6a4SAndroid Build Coastguard Worker
1243*bb4ee6a4SAndroid Build Coastguard Worker if self.vfds.contains_key(&id) {
1244*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidId);
1245*bb4ee6a4SAndroid Build Coastguard Worker }
1246*bb4ee6a4SAndroid Build Coastguard Worker let vfd = WlVfd::allocate(self.vm.clone(), size as u64)?;
1247*bb4ee6a4SAndroid Build Coastguard Worker let resp = WlResp::VfdNew {
1248*bb4ee6a4SAndroid Build Coastguard Worker id,
1249*bb4ee6a4SAndroid Build Coastguard Worker flags,
1250*bb4ee6a4SAndroid Build Coastguard Worker pfn: self.compute_pfn(&vfd.offset()),
1251*bb4ee6a4SAndroid Build Coastguard Worker size: vfd.size().unwrap_or_default() as u32,
1252*bb4ee6a4SAndroid Build Coastguard Worker resp: true,
1253*bb4ee6a4SAndroid Build Coastguard Worker };
1254*bb4ee6a4SAndroid Build Coastguard Worker self.vfds.insert(id, vfd);
1255*bb4ee6a4SAndroid Build Coastguard Worker Ok(resp)
1256*bb4ee6a4SAndroid Build Coastguard Worker }
1257*bb4ee6a4SAndroid Build Coastguard Worker
1258*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
new_dmabuf(&mut self, id: u32, width: u32, height: u32, format: u32) -> WlResult<WlResp>1259*bb4ee6a4SAndroid Build Coastguard Worker fn new_dmabuf(&mut self, id: u32, width: u32, height: u32, format: u32) -> WlResult<WlResp> {
1260*bb4ee6a4SAndroid Build Coastguard Worker if id & VFD_ID_HOST_MASK != 0 {
1261*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidId);
1262*bb4ee6a4SAndroid Build Coastguard Worker }
1263*bb4ee6a4SAndroid Build Coastguard Worker
1264*bb4ee6a4SAndroid Build Coastguard Worker if self.vfds.contains_key(&id) {
1265*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidId);
1266*bb4ee6a4SAndroid Build Coastguard Worker }
1267*bb4ee6a4SAndroid Build Coastguard Worker let (vfd, desc) = WlVfd::dmabuf(self.vm.clone(), width, height, format)?;
1268*bb4ee6a4SAndroid Build Coastguard Worker let resp = WlResp::VfdNewDmabuf {
1269*bb4ee6a4SAndroid Build Coastguard Worker id,
1270*bb4ee6a4SAndroid Build Coastguard Worker flags: 0,
1271*bb4ee6a4SAndroid Build Coastguard Worker pfn: self.compute_pfn(&vfd.offset()),
1272*bb4ee6a4SAndroid Build Coastguard Worker size: vfd.size().unwrap_or_default() as u32,
1273*bb4ee6a4SAndroid Build Coastguard Worker desc,
1274*bb4ee6a4SAndroid Build Coastguard Worker };
1275*bb4ee6a4SAndroid Build Coastguard Worker self.vfds.insert(id, vfd);
1276*bb4ee6a4SAndroid Build Coastguard Worker Ok(resp)
1277*bb4ee6a4SAndroid Build Coastguard Worker }
1278*bb4ee6a4SAndroid Build Coastguard Worker
1279*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
dmabuf_sync(&mut self, vfd_id: u32, flags: u32) -> WlResult<WlResp>1280*bb4ee6a4SAndroid Build Coastguard Worker fn dmabuf_sync(&mut self, vfd_id: u32, flags: u32) -> WlResult<WlResp> {
1281*bb4ee6a4SAndroid Build Coastguard Worker if flags & !(VIRTIO_WL_VFD_DMABUF_SYNC_VALID_FLAG_MASK) != 0 {
1282*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidFlags);
1283*bb4ee6a4SAndroid Build Coastguard Worker }
1284*bb4ee6a4SAndroid Build Coastguard Worker
1285*bb4ee6a4SAndroid Build Coastguard Worker match self.vfds.get_mut(&vfd_id) {
1286*bb4ee6a4SAndroid Build Coastguard Worker Some(vfd) => {
1287*bb4ee6a4SAndroid Build Coastguard Worker vfd.dmabuf_sync(flags)?;
1288*bb4ee6a4SAndroid Build Coastguard Worker Ok(WlResp::Ok)
1289*bb4ee6a4SAndroid Build Coastguard Worker }
1290*bb4ee6a4SAndroid Build Coastguard Worker None => Ok(WlResp::InvalidId),
1291*bb4ee6a4SAndroid Build Coastguard Worker }
1292*bb4ee6a4SAndroid Build Coastguard Worker }
1293*bb4ee6a4SAndroid Build Coastguard Worker
new_context(&mut self, id: u32, name: &str) -> WlResult<WlResp>1294*bb4ee6a4SAndroid Build Coastguard Worker fn new_context(&mut self, id: u32, name: &str) -> WlResult<WlResp> {
1295*bb4ee6a4SAndroid Build Coastguard Worker if id & VFD_ID_HOST_MASK != 0 {
1296*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidId);
1297*bb4ee6a4SAndroid Build Coastguard Worker }
1298*bb4ee6a4SAndroid Build Coastguard Worker
1299*bb4ee6a4SAndroid Build Coastguard Worker let flags = if self.use_transition_flags {
1300*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_VFD_WRITE | VIRTIO_WL_VFD_READ
1301*bb4ee6a4SAndroid Build Coastguard Worker } else {
1302*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_VFD_CONTROL
1303*bb4ee6a4SAndroid Build Coastguard Worker };
1304*bb4ee6a4SAndroid Build Coastguard Worker
1305*bb4ee6a4SAndroid Build Coastguard Worker match self.vfds.entry(id) {
1306*bb4ee6a4SAndroid Build Coastguard Worker Entry::Vacant(entry) => {
1307*bb4ee6a4SAndroid Build Coastguard Worker let vfd = entry.insert(WlVfd::connect(
1308*bb4ee6a4SAndroid Build Coastguard Worker self.wayland_paths
1309*bb4ee6a4SAndroid Build Coastguard Worker .get(name)
1310*bb4ee6a4SAndroid Build Coastguard Worker .ok_or_else(|| WlError::UnknownSocketName(name.to_string()))?,
1311*bb4ee6a4SAndroid Build Coastguard Worker )?);
1312*bb4ee6a4SAndroid Build Coastguard Worker self.wait_ctx
1313*bb4ee6a4SAndroid Build Coastguard Worker .add(vfd.wait_descriptor().unwrap(), id)
1314*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::WaitContextAdd)?;
1315*bb4ee6a4SAndroid Build Coastguard Worker Ok(WlResp::VfdNew {
1316*bb4ee6a4SAndroid Build Coastguard Worker id,
1317*bb4ee6a4SAndroid Build Coastguard Worker flags,
1318*bb4ee6a4SAndroid Build Coastguard Worker pfn: 0,
1319*bb4ee6a4SAndroid Build Coastguard Worker size: 0,
1320*bb4ee6a4SAndroid Build Coastguard Worker resp: true,
1321*bb4ee6a4SAndroid Build Coastguard Worker })
1322*bb4ee6a4SAndroid Build Coastguard Worker }
1323*bb4ee6a4SAndroid Build Coastguard Worker Entry::Occupied(_) => Ok(WlResp::InvalidId),
1324*bb4ee6a4SAndroid Build Coastguard Worker }
1325*bb4ee6a4SAndroid Build Coastguard Worker }
1326*bb4ee6a4SAndroid Build Coastguard Worker
process_wait_context(&mut self)1327*bb4ee6a4SAndroid Build Coastguard Worker fn process_wait_context(&mut self) {
1328*bb4ee6a4SAndroid Build Coastguard Worker let events = match self.wait_ctx.wait_timeout(Duration::from_secs(0)) {
1329*bb4ee6a4SAndroid Build Coastguard Worker Ok(v) => v,
1330*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
1331*bb4ee6a4SAndroid Build Coastguard Worker error!("failed waiting for vfd evens: {}", e);
1332*bb4ee6a4SAndroid Build Coastguard Worker return;
1333*bb4ee6a4SAndroid Build Coastguard Worker }
1334*bb4ee6a4SAndroid Build Coastguard Worker };
1335*bb4ee6a4SAndroid Build Coastguard Worker
1336*bb4ee6a4SAndroid Build Coastguard Worker for event in events.iter().filter(|e| e.is_readable) {
1337*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.recv(event.token) {
1338*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to recv from vfd: {}", e)
1339*bb4ee6a4SAndroid Build Coastguard Worker }
1340*bb4ee6a4SAndroid Build Coastguard Worker }
1341*bb4ee6a4SAndroid Build Coastguard Worker
1342*bb4ee6a4SAndroid Build Coastguard Worker for event in events.iter().filter(|e| e.is_hungup) {
1343*bb4ee6a4SAndroid Build Coastguard Worker if !event.is_readable {
1344*bb4ee6a4SAndroid Build Coastguard Worker let vfd_id = event.token;
1345*bb4ee6a4SAndroid Build Coastguard Worker if let Some(descriptor) =
1346*bb4ee6a4SAndroid Build Coastguard Worker self.vfds.get(&vfd_id).and_then(|vfd| vfd.wait_descriptor())
1347*bb4ee6a4SAndroid Build Coastguard Worker {
1348*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.wait_ctx.delete(descriptor) {
1349*bb4ee6a4SAndroid Build Coastguard Worker warn!("failed to remove hungup vfd from poll context: {}", e);
1350*bb4ee6a4SAndroid Build Coastguard Worker }
1351*bb4ee6a4SAndroid Build Coastguard Worker }
1352*bb4ee6a4SAndroid Build Coastguard Worker self.in_queue.push_back((vfd_id, WlRecv::Hup));
1353*bb4ee6a4SAndroid Build Coastguard Worker }
1354*bb4ee6a4SAndroid Build Coastguard Worker }
1355*bb4ee6a4SAndroid Build Coastguard Worker }
1356*bb4ee6a4SAndroid Build Coastguard Worker
close(&mut self, vfd_id: u32) -> WlResult<WlResp>1357*bb4ee6a4SAndroid Build Coastguard Worker fn close(&mut self, vfd_id: u32) -> WlResult<WlResp> {
1358*bb4ee6a4SAndroid Build Coastguard Worker let mut to_delete = BTreeSet::new();
1359*bb4ee6a4SAndroid Build Coastguard Worker for (dest_vfd_id, q) in &self.in_queue {
1360*bb4ee6a4SAndroid Build Coastguard Worker if *dest_vfd_id == vfd_id {
1361*bb4ee6a4SAndroid Build Coastguard Worker if let WlRecv::Vfd { id } = q {
1362*bb4ee6a4SAndroid Build Coastguard Worker to_delete.insert(*id);
1363*bb4ee6a4SAndroid Build Coastguard Worker }
1364*bb4ee6a4SAndroid Build Coastguard Worker }
1365*bb4ee6a4SAndroid Build Coastguard Worker }
1366*bb4ee6a4SAndroid Build Coastguard Worker for vfd_id in to_delete {
1367*bb4ee6a4SAndroid Build Coastguard Worker // Sorry sub-error, we can't have cascading errors leaving us in an inconsistent state.
1368*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.close(vfd_id);
1369*bb4ee6a4SAndroid Build Coastguard Worker }
1370*bb4ee6a4SAndroid Build Coastguard Worker match self.vfds.remove(&vfd_id) {
1371*bb4ee6a4SAndroid Build Coastguard Worker Some(mut vfd) => {
1372*bb4ee6a4SAndroid Build Coastguard Worker self.in_queue.retain(|&(id, _)| id != vfd_id);
1373*bb4ee6a4SAndroid Build Coastguard Worker vfd.close()?;
1374*bb4ee6a4SAndroid Build Coastguard Worker Ok(WlResp::Ok)
1375*bb4ee6a4SAndroid Build Coastguard Worker }
1376*bb4ee6a4SAndroid Build Coastguard Worker None => Ok(WlResp::InvalidId),
1377*bb4ee6a4SAndroid Build Coastguard Worker }
1378*bb4ee6a4SAndroid Build Coastguard Worker }
1379*bb4ee6a4SAndroid Build Coastguard Worker
1380*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
get_info(&mut self, request: ResourceRequest) -> Option<SafeDescriptor>1381*bb4ee6a4SAndroid Build Coastguard Worker fn get_info(&mut self, request: ResourceRequest) -> Option<SafeDescriptor> {
1382*bb4ee6a4SAndroid Build Coastguard Worker let sock = self.resource_bridge.as_ref().unwrap();
1383*bb4ee6a4SAndroid Build Coastguard Worker match get_resource_info(sock, request) {
1384*bb4ee6a4SAndroid Build Coastguard Worker Ok(ResourceInfo::Buffer(BufferInfo { handle, .. })) => Some(handle),
1385*bb4ee6a4SAndroid Build Coastguard Worker Ok(ResourceInfo::Fence { handle }) => Some(handle),
1386*bb4ee6a4SAndroid Build Coastguard Worker Err(ResourceBridgeError::InvalidResource(req)) => {
1387*bb4ee6a4SAndroid Build Coastguard Worker warn!("attempt to send non-existent gpu resource {}", req);
1388*bb4ee6a4SAndroid Build Coastguard Worker None
1389*bb4ee6a4SAndroid Build Coastguard Worker }
1390*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
1391*bb4ee6a4SAndroid Build Coastguard Worker error!("{}", e);
1392*bb4ee6a4SAndroid Build Coastguard Worker // If there was an error with the resource bridge, it can no longer be
1393*bb4ee6a4SAndroid Build Coastguard Worker // trusted to continue to function.
1394*bb4ee6a4SAndroid Build Coastguard Worker self.resource_bridge = None;
1395*bb4ee6a4SAndroid Build Coastguard Worker None
1396*bb4ee6a4SAndroid Build Coastguard Worker }
1397*bb4ee6a4SAndroid Build Coastguard Worker }
1398*bb4ee6a4SAndroid Build Coastguard Worker }
1399*bb4ee6a4SAndroid Build Coastguard Worker
send( &mut self, vfd_id: u32, vfd_count: usize, foreign_id: bool, reader: &mut Reader, ) -> WlResult<WlResp>1400*bb4ee6a4SAndroid Build Coastguard Worker fn send(
1401*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
1402*bb4ee6a4SAndroid Build Coastguard Worker vfd_id: u32,
1403*bb4ee6a4SAndroid Build Coastguard Worker vfd_count: usize,
1404*bb4ee6a4SAndroid Build Coastguard Worker foreign_id: bool,
1405*bb4ee6a4SAndroid Build Coastguard Worker reader: &mut Reader,
1406*bb4ee6a4SAndroid Build Coastguard Worker ) -> WlResult<WlResp> {
1407*bb4ee6a4SAndroid Build Coastguard Worker // First stage gathers and normalizes all id information from guest memory.
1408*bb4ee6a4SAndroid Build Coastguard Worker let mut send_vfd_ids = [CtrlVfdSendVfdV2 {
1409*bb4ee6a4SAndroid Build Coastguard Worker kind: Le32::from(0),
1410*bb4ee6a4SAndroid Build Coastguard Worker payload: CtrlVfdSendVfdV2Payload { id: Le32::from(0) },
1411*bb4ee6a4SAndroid Build Coastguard Worker }; VIRTWL_SEND_MAX_ALLOCS];
1412*bb4ee6a4SAndroid Build Coastguard Worker for vfd_id in send_vfd_ids.iter_mut().take(vfd_count) {
1413*bb4ee6a4SAndroid Build Coastguard Worker *vfd_id = if foreign_id {
1414*bb4ee6a4SAndroid Build Coastguard Worker if self.use_send_vfd_v2 {
1415*bb4ee6a4SAndroid Build Coastguard Worker reader.read_obj().map_err(WlError::ParseDesc)?
1416*bb4ee6a4SAndroid Build Coastguard Worker } else {
1417*bb4ee6a4SAndroid Build Coastguard Worker let vfd: CtrlVfdSendVfd = reader.read_obj().map_err(WlError::ParseDesc)?;
1418*bb4ee6a4SAndroid Build Coastguard Worker CtrlVfdSendVfdV2 {
1419*bb4ee6a4SAndroid Build Coastguard Worker kind: vfd.kind,
1420*bb4ee6a4SAndroid Build Coastguard Worker payload: CtrlVfdSendVfdV2Payload { id: vfd.id },
1421*bb4ee6a4SAndroid Build Coastguard Worker }
1422*bb4ee6a4SAndroid Build Coastguard Worker }
1423*bb4ee6a4SAndroid Build Coastguard Worker } else {
1424*bb4ee6a4SAndroid Build Coastguard Worker CtrlVfdSendVfdV2 {
1425*bb4ee6a4SAndroid Build Coastguard Worker kind: Le32::from(VIRTIO_WL_CTRL_VFD_SEND_KIND_LOCAL),
1426*bb4ee6a4SAndroid Build Coastguard Worker payload: CtrlVfdSendVfdV2Payload {
1427*bb4ee6a4SAndroid Build Coastguard Worker id: reader.read_obj().map_err(WlError::ParseDesc)?,
1428*bb4ee6a4SAndroid Build Coastguard Worker },
1429*bb4ee6a4SAndroid Build Coastguard Worker }
1430*bb4ee6a4SAndroid Build Coastguard Worker };
1431*bb4ee6a4SAndroid Build Coastguard Worker }
1432*bb4ee6a4SAndroid Build Coastguard Worker
1433*bb4ee6a4SAndroid Build Coastguard Worker // Next stage collects corresponding file descriptors for each id.
1434*bb4ee6a4SAndroid Build Coastguard Worker let mut rds = [0; VIRTWL_SEND_MAX_ALLOCS];
1435*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
1436*bb4ee6a4SAndroid Build Coastguard Worker let mut bridged_files = Vec::new();
1437*bb4ee6a4SAndroid Build Coastguard Worker for (&send_vfd_id, descriptor) in send_vfd_ids[..vfd_count].iter().zip(rds.iter_mut()) {
1438*bb4ee6a4SAndroid Build Coastguard Worker match send_vfd_id.kind.to_native() {
1439*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CTRL_VFD_SEND_KIND_LOCAL => {
1440*bb4ee6a4SAndroid Build Coastguard Worker match self.vfds.get(&send_vfd_id.id().to_native()) {
1441*bb4ee6a4SAndroid Build Coastguard Worker Some(vfd) => match vfd.send_descriptor() {
1442*bb4ee6a4SAndroid Build Coastguard Worker Some(vfd_fd) => *descriptor = vfd_fd,
1443*bb4ee6a4SAndroid Build Coastguard Worker None => return Ok(WlResp::InvalidType),
1444*bb4ee6a4SAndroid Build Coastguard Worker },
1445*bb4ee6a4SAndroid Build Coastguard Worker None => {
1446*bb4ee6a4SAndroid Build Coastguard Worker warn!(
1447*bb4ee6a4SAndroid Build Coastguard Worker "attempt to send non-existant vfd 0x{:08x}",
1448*bb4ee6a4SAndroid Build Coastguard Worker send_vfd_id.id().to_native()
1449*bb4ee6a4SAndroid Build Coastguard Worker );
1450*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidId);
1451*bb4ee6a4SAndroid Build Coastguard Worker }
1452*bb4ee6a4SAndroid Build Coastguard Worker }
1453*bb4ee6a4SAndroid Build Coastguard Worker }
1454*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
1455*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU if self.resource_bridge.is_some() => {
1456*bb4ee6a4SAndroid Build Coastguard Worker match self.get_info(ResourceRequest::GetBuffer {
1457*bb4ee6a4SAndroid Build Coastguard Worker id: send_vfd_id.id().to_native(),
1458*bb4ee6a4SAndroid Build Coastguard Worker }) {
1459*bb4ee6a4SAndroid Build Coastguard Worker Some(handle) => {
1460*bb4ee6a4SAndroid Build Coastguard Worker *descriptor = handle.as_raw_descriptor();
1461*bb4ee6a4SAndroid Build Coastguard Worker bridged_files.push(handle.into());
1462*bb4ee6a4SAndroid Build Coastguard Worker }
1463*bb4ee6a4SAndroid Build Coastguard Worker None => return Ok(WlResp::InvalidId),
1464*bb4ee6a4SAndroid Build Coastguard Worker }
1465*bb4ee6a4SAndroid Build Coastguard Worker }
1466*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
1467*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU_FENCE if self.resource_bridge.is_some() => {
1468*bb4ee6a4SAndroid Build Coastguard Worker match self.get_info(ResourceRequest::GetFence {
1469*bb4ee6a4SAndroid Build Coastguard Worker seqno: send_vfd_id.seqno().to_native(),
1470*bb4ee6a4SAndroid Build Coastguard Worker }) {
1471*bb4ee6a4SAndroid Build Coastguard Worker Some(handle) => {
1472*bb4ee6a4SAndroid Build Coastguard Worker *descriptor = handle.as_raw_descriptor();
1473*bb4ee6a4SAndroid Build Coastguard Worker bridged_files.push(handle.into());
1474*bb4ee6a4SAndroid Build Coastguard Worker }
1475*bb4ee6a4SAndroid Build Coastguard Worker None => return Ok(WlResp::InvalidId),
1476*bb4ee6a4SAndroid Build Coastguard Worker }
1477*bb4ee6a4SAndroid Build Coastguard Worker }
1478*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
1479*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU_SIGNALED_FENCE
1480*bb4ee6a4SAndroid Build Coastguard Worker if self.resource_bridge.is_some() =>
1481*bb4ee6a4SAndroid Build Coastguard Worker {
1482*bb4ee6a4SAndroid Build Coastguard Worker if self.signaled_fence.is_none() {
1483*bb4ee6a4SAndroid Build Coastguard Worker // If the guest is sending a signaled fence, we know a fence
1484*bb4ee6a4SAndroid Build Coastguard Worker // with seqno 0 must already be signaled.
1485*bb4ee6a4SAndroid Build Coastguard Worker match self.get_info(ResourceRequest::GetFence { seqno: 0 }) {
1486*bb4ee6a4SAndroid Build Coastguard Worker Some(handle) => self.signaled_fence = Some(handle),
1487*bb4ee6a4SAndroid Build Coastguard Worker None => return Ok(WlResp::InvalidId),
1488*bb4ee6a4SAndroid Build Coastguard Worker }
1489*bb4ee6a4SAndroid Build Coastguard Worker }
1490*bb4ee6a4SAndroid Build Coastguard Worker match self.signaled_fence.as_ref().unwrap().try_clone() {
1491*bb4ee6a4SAndroid Build Coastguard Worker Ok(dup) => {
1492*bb4ee6a4SAndroid Build Coastguard Worker *descriptor = dup.into_raw_descriptor();
1493*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
1494*bb4ee6a4SAndroid Build Coastguard Worker // Safe because the fd comes from a valid SafeDescriptor.
1495*bb4ee6a4SAndroid Build Coastguard Worker let file: File = unsafe {
1496*bb4ee6a4SAndroid Build Coastguard Worker base::FromRawDescriptor::from_raw_descriptor(*descriptor)
1497*bb4ee6a4SAndroid Build Coastguard Worker };
1498*bb4ee6a4SAndroid Build Coastguard Worker bridged_files.push(file);
1499*bb4ee6a4SAndroid Build Coastguard Worker }
1500*bb4ee6a4SAndroid Build Coastguard Worker Err(_) => return Ok(WlResp::InvalidId),
1501*bb4ee6a4SAndroid Build Coastguard Worker }
1502*bb4ee6a4SAndroid Build Coastguard Worker }
1503*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU
1504*bb4ee6a4SAndroid Build Coastguard Worker | VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU_FENCE
1505*bb4ee6a4SAndroid Build Coastguard Worker | VIRTIO_WL_CTRL_VFD_SEND_KIND_VIRTGPU_SIGNALED_FENCE => {
1506*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.resource_bridge.as_ref();
1507*bb4ee6a4SAndroid Build Coastguard Worker warn!("attempt to send foreign resource kind but feature is disabled");
1508*bb4ee6a4SAndroid Build Coastguard Worker }
1509*bb4ee6a4SAndroid Build Coastguard Worker kind => {
1510*bb4ee6a4SAndroid Build Coastguard Worker warn!("attempt to send unknown foreign resource kind: {}", kind);
1511*bb4ee6a4SAndroid Build Coastguard Worker return Ok(WlResp::InvalidId);
1512*bb4ee6a4SAndroid Build Coastguard Worker }
1513*bb4ee6a4SAndroid Build Coastguard Worker }
1514*bb4ee6a4SAndroid Build Coastguard Worker }
1515*bb4ee6a4SAndroid Build Coastguard Worker
1516*bb4ee6a4SAndroid Build Coastguard Worker // Final stage sends file descriptors and data to the target vfd's socket.
1517*bb4ee6a4SAndroid Build Coastguard Worker match self.vfds.get_mut(&vfd_id) {
1518*bb4ee6a4SAndroid Build Coastguard Worker Some(vfd) => match vfd.send(&rds[..vfd_count], reader)? {
1519*bb4ee6a4SAndroid Build Coastguard Worker WlResp::Ok => {}
1520*bb4ee6a4SAndroid Build Coastguard Worker _ => return Ok(WlResp::InvalidType),
1521*bb4ee6a4SAndroid Build Coastguard Worker },
1522*bb4ee6a4SAndroid Build Coastguard Worker None => return Ok(WlResp::InvalidId),
1523*bb4ee6a4SAndroid Build Coastguard Worker }
1524*bb4ee6a4SAndroid Build Coastguard Worker // The vfds with remote FDs need to be closed so that the local side can receive
1525*bb4ee6a4SAndroid Build Coastguard Worker // hangup events.
1526*bb4ee6a4SAndroid Build Coastguard Worker for &send_vfd_id in &send_vfd_ids[..vfd_count] {
1527*bb4ee6a4SAndroid Build Coastguard Worker if send_vfd_id.kind == VIRTIO_WL_CTRL_VFD_SEND_KIND_LOCAL {
1528*bb4ee6a4SAndroid Build Coastguard Worker if let Some(vfd) = self.vfds.get_mut(&send_vfd_id.id().into()) {
1529*bb4ee6a4SAndroid Build Coastguard Worker vfd.close_remote();
1530*bb4ee6a4SAndroid Build Coastguard Worker }
1531*bb4ee6a4SAndroid Build Coastguard Worker }
1532*bb4ee6a4SAndroid Build Coastguard Worker }
1533*bb4ee6a4SAndroid Build Coastguard Worker Ok(WlResp::Ok)
1534*bb4ee6a4SAndroid Build Coastguard Worker }
1535*bb4ee6a4SAndroid Build Coastguard Worker
recv(&mut self, vfd_id: u32) -> WlResult<()>1536*bb4ee6a4SAndroid Build Coastguard Worker fn recv(&mut self, vfd_id: u32) -> WlResult<()> {
1537*bb4ee6a4SAndroid Build Coastguard Worker let buf = match self.vfds.get_mut(&vfd_id) {
1538*bb4ee6a4SAndroid Build Coastguard Worker Some(vfd) => {
1539*bb4ee6a4SAndroid Build Coastguard Worker if vfd.is_fence {
1540*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.wait_ctx.delete(vfd.wait_descriptor().unwrap()) {
1541*bb4ee6a4SAndroid Build Coastguard Worker warn!("failed to remove hungup vfd from poll context: {}", e);
1542*bb4ee6a4SAndroid Build Coastguard Worker }
1543*bb4ee6a4SAndroid Build Coastguard Worker self.in_queue.push_back((vfd_id, WlRecv::Hup));
1544*bb4ee6a4SAndroid Build Coastguard Worker return Ok(());
1545*bb4ee6a4SAndroid Build Coastguard Worker } else {
1546*bb4ee6a4SAndroid Build Coastguard Worker vfd.recv(&mut self.in_file_queue)?
1547*bb4ee6a4SAndroid Build Coastguard Worker }
1548*bb4ee6a4SAndroid Build Coastguard Worker }
1549*bb4ee6a4SAndroid Build Coastguard Worker None => return Ok(()),
1550*bb4ee6a4SAndroid Build Coastguard Worker };
1551*bb4ee6a4SAndroid Build Coastguard Worker
1552*bb4ee6a4SAndroid Build Coastguard Worker if self.in_file_queue.is_empty() && buf.is_empty() {
1553*bb4ee6a4SAndroid Build Coastguard Worker self.in_queue.push_back((vfd_id, WlRecv::Hup));
1554*bb4ee6a4SAndroid Build Coastguard Worker return Ok(());
1555*bb4ee6a4SAndroid Build Coastguard Worker }
1556*bb4ee6a4SAndroid Build Coastguard Worker for file in self.in_file_queue.drain(..) {
1557*bb4ee6a4SAndroid Build Coastguard Worker let vfd = WlVfd::from_file(self.vm.clone(), file)?;
1558*bb4ee6a4SAndroid Build Coastguard Worker if let Some(wait_descriptor) = vfd.wait_descriptor() {
1559*bb4ee6a4SAndroid Build Coastguard Worker self.wait_ctx
1560*bb4ee6a4SAndroid Build Coastguard Worker .add(wait_descriptor, self.next_vfd_id)
1561*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::WaitContextAdd)?;
1562*bb4ee6a4SAndroid Build Coastguard Worker }
1563*bb4ee6a4SAndroid Build Coastguard Worker // Only necessary if we somehow wrap the id counter. The try_insert
1564*bb4ee6a4SAndroid Build Coastguard Worker // API would be nicer, but that's currently experimental.
1565*bb4ee6a4SAndroid Build Coastguard Worker while self.vfds.contains_key(&self.next_vfd_id) {
1566*bb4ee6a4SAndroid Build Coastguard Worker self.next_vfd_id += 1;
1567*bb4ee6a4SAndroid Build Coastguard Worker }
1568*bb4ee6a4SAndroid Build Coastguard Worker self.vfds.insert(self.next_vfd_id, vfd);
1569*bb4ee6a4SAndroid Build Coastguard Worker self.in_queue.push_back((
1570*bb4ee6a4SAndroid Build Coastguard Worker vfd_id,
1571*bb4ee6a4SAndroid Build Coastguard Worker WlRecv::Vfd {
1572*bb4ee6a4SAndroid Build Coastguard Worker id: self.next_vfd_id,
1573*bb4ee6a4SAndroid Build Coastguard Worker },
1574*bb4ee6a4SAndroid Build Coastguard Worker ));
1575*bb4ee6a4SAndroid Build Coastguard Worker self.next_vfd_id += 1;
1576*bb4ee6a4SAndroid Build Coastguard Worker }
1577*bb4ee6a4SAndroid Build Coastguard Worker self.in_queue.push_back((vfd_id, WlRecv::Data { buf }));
1578*bb4ee6a4SAndroid Build Coastguard Worker
1579*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
1580*bb4ee6a4SAndroid Build Coastguard Worker }
1581*bb4ee6a4SAndroid Build Coastguard Worker
execute(&mut self, reader: &mut Reader) -> WlResult<WlResp>1582*bb4ee6a4SAndroid Build Coastguard Worker fn execute(&mut self, reader: &mut Reader) -> WlResult<WlResp> {
1583*bb4ee6a4SAndroid Build Coastguard Worker let type_: Le32 = reader.peek_obj::<Le32>().map_err(WlError::ParseDesc)?;
1584*bb4ee6a4SAndroid Build Coastguard Worker match type_.into() {
1585*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CMD_VFD_NEW => {
1586*bb4ee6a4SAndroid Build Coastguard Worker let ctrl = reader
1587*bb4ee6a4SAndroid Build Coastguard Worker .read_obj::<CtrlVfdNew>()
1588*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ParseDesc)?;
1589*bb4ee6a4SAndroid Build Coastguard Worker self.new_alloc(ctrl.id.into(), ctrl.flags.into(), ctrl.size.into())
1590*bb4ee6a4SAndroid Build Coastguard Worker }
1591*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CMD_VFD_CLOSE => {
1592*bb4ee6a4SAndroid Build Coastguard Worker let ctrl = reader.read_obj::<CtrlVfd>().map_err(WlError::ParseDesc)?;
1593*bb4ee6a4SAndroid Build Coastguard Worker self.close(ctrl.id.into())
1594*bb4ee6a4SAndroid Build Coastguard Worker }
1595*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CMD_VFD_SEND => {
1596*bb4ee6a4SAndroid Build Coastguard Worker let ctrl = reader
1597*bb4ee6a4SAndroid Build Coastguard Worker .read_obj::<CtrlVfdSend>()
1598*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ParseDesc)?;
1599*bb4ee6a4SAndroid Build Coastguard Worker let foreign_id = false;
1600*bb4ee6a4SAndroid Build Coastguard Worker self.send(
1601*bb4ee6a4SAndroid Build Coastguard Worker ctrl.id.into(),
1602*bb4ee6a4SAndroid Build Coastguard Worker ctrl.vfd_count.to_native() as usize,
1603*bb4ee6a4SAndroid Build Coastguard Worker foreign_id,
1604*bb4ee6a4SAndroid Build Coastguard Worker reader,
1605*bb4ee6a4SAndroid Build Coastguard Worker )
1606*bb4ee6a4SAndroid Build Coastguard Worker }
1607*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "gpu")]
1608*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CMD_VFD_SEND_FOREIGN_ID => {
1609*bb4ee6a4SAndroid Build Coastguard Worker let ctrl = reader
1610*bb4ee6a4SAndroid Build Coastguard Worker .read_obj::<CtrlVfdSend>()
1611*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ParseDesc)?;
1612*bb4ee6a4SAndroid Build Coastguard Worker let foreign_id = true;
1613*bb4ee6a4SAndroid Build Coastguard Worker self.send(
1614*bb4ee6a4SAndroid Build Coastguard Worker ctrl.id.into(),
1615*bb4ee6a4SAndroid Build Coastguard Worker ctrl.vfd_count.to_native() as usize,
1616*bb4ee6a4SAndroid Build Coastguard Worker foreign_id,
1617*bb4ee6a4SAndroid Build Coastguard Worker reader,
1618*bb4ee6a4SAndroid Build Coastguard Worker )
1619*bb4ee6a4SAndroid Build Coastguard Worker }
1620*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CMD_VFD_NEW_CTX => {
1621*bb4ee6a4SAndroid Build Coastguard Worker let ctrl = reader.read_obj::<CtrlVfd>().map_err(WlError::ParseDesc)?;
1622*bb4ee6a4SAndroid Build Coastguard Worker self.new_context(ctrl.id.into(), "")
1623*bb4ee6a4SAndroid Build Coastguard Worker }
1624*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CMD_VFD_NEW_PIPE => {
1625*bb4ee6a4SAndroid Build Coastguard Worker let ctrl = reader
1626*bb4ee6a4SAndroid Build Coastguard Worker .read_obj::<CtrlVfdNew>()
1627*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ParseDesc)?;
1628*bb4ee6a4SAndroid Build Coastguard Worker self.new_pipe(ctrl.id.into(), ctrl.flags.into())
1629*bb4ee6a4SAndroid Build Coastguard Worker }
1630*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
1631*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CMD_VFD_NEW_DMABUF => {
1632*bb4ee6a4SAndroid Build Coastguard Worker let ctrl = reader
1633*bb4ee6a4SAndroid Build Coastguard Worker .read_obj::<CtrlVfdNewDmabuf>()
1634*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ParseDesc)?;
1635*bb4ee6a4SAndroid Build Coastguard Worker self.new_dmabuf(
1636*bb4ee6a4SAndroid Build Coastguard Worker ctrl.id.into(),
1637*bb4ee6a4SAndroid Build Coastguard Worker ctrl.width.into(),
1638*bb4ee6a4SAndroid Build Coastguard Worker ctrl.height.into(),
1639*bb4ee6a4SAndroid Build Coastguard Worker ctrl.format.into(),
1640*bb4ee6a4SAndroid Build Coastguard Worker )
1641*bb4ee6a4SAndroid Build Coastguard Worker }
1642*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
1643*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CMD_VFD_DMABUF_SYNC => {
1644*bb4ee6a4SAndroid Build Coastguard Worker let ctrl = reader
1645*bb4ee6a4SAndroid Build Coastguard Worker .read_obj::<CtrlVfdDmabufSync>()
1646*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ParseDesc)?;
1647*bb4ee6a4SAndroid Build Coastguard Worker self.dmabuf_sync(ctrl.id.into(), ctrl.flags.into())
1648*bb4ee6a4SAndroid Build Coastguard Worker }
1649*bb4ee6a4SAndroid Build Coastguard Worker VIRTIO_WL_CMD_VFD_NEW_CTX_NAMED => {
1650*bb4ee6a4SAndroid Build Coastguard Worker let ctrl = reader
1651*bb4ee6a4SAndroid Build Coastguard Worker .read_obj::<CtrlVfdNewCtxNamed>()
1652*bb4ee6a4SAndroid Build Coastguard Worker .map_err(WlError::ParseDesc)?;
1653*bb4ee6a4SAndroid Build Coastguard Worker let name_len = ctrl
1654*bb4ee6a4SAndroid Build Coastguard Worker .name
1655*bb4ee6a4SAndroid Build Coastguard Worker .iter()
1656*bb4ee6a4SAndroid Build Coastguard Worker .position(|x| x == &0)
1657*bb4ee6a4SAndroid Build Coastguard Worker .unwrap_or(ctrl.name.len());
1658*bb4ee6a4SAndroid Build Coastguard Worker let name =
1659*bb4ee6a4SAndroid Build Coastguard Worker std::str::from_utf8(&ctrl.name[..name_len]).map_err(WlError::InvalidString)?;
1660*bb4ee6a4SAndroid Build Coastguard Worker self.new_context(ctrl.id.into(), name)
1661*bb4ee6a4SAndroid Build Coastguard Worker }
1662*bb4ee6a4SAndroid Build Coastguard Worker op_type => {
1663*bb4ee6a4SAndroid Build Coastguard Worker warn!("unexpected command {}", op_type);
1664*bb4ee6a4SAndroid Build Coastguard Worker Ok(WlResp::InvalidCommand)
1665*bb4ee6a4SAndroid Build Coastguard Worker }
1666*bb4ee6a4SAndroid Build Coastguard Worker }
1667*bb4ee6a4SAndroid Build Coastguard Worker }
1668*bb4ee6a4SAndroid Build Coastguard Worker
next_recv(&self) -> Option<WlResp>1669*bb4ee6a4SAndroid Build Coastguard Worker fn next_recv(&self) -> Option<WlResp> {
1670*bb4ee6a4SAndroid Build Coastguard Worker if let Some(q) = self.in_queue.front() {
1671*bb4ee6a4SAndroid Build Coastguard Worker match *q {
1672*bb4ee6a4SAndroid Build Coastguard Worker (vfd_id, WlRecv::Vfd { id }) => {
1673*bb4ee6a4SAndroid Build Coastguard Worker if self.current_recv_vfd.is_none() || self.current_recv_vfd == Some(vfd_id) {
1674*bb4ee6a4SAndroid Build Coastguard Worker match self.vfds.get(&id) {
1675*bb4ee6a4SAndroid Build Coastguard Worker Some(vfd) => Some(WlResp::VfdNew {
1676*bb4ee6a4SAndroid Build Coastguard Worker id,
1677*bb4ee6a4SAndroid Build Coastguard Worker flags: vfd.flags(self.use_transition_flags),
1678*bb4ee6a4SAndroid Build Coastguard Worker pfn: self.compute_pfn(&vfd.offset()),
1679*bb4ee6a4SAndroid Build Coastguard Worker size: vfd.size().unwrap_or_default() as u32,
1680*bb4ee6a4SAndroid Build Coastguard Worker resp: false,
1681*bb4ee6a4SAndroid Build Coastguard Worker }),
1682*bb4ee6a4SAndroid Build Coastguard Worker _ => Some(WlResp::VfdNew {
1683*bb4ee6a4SAndroid Build Coastguard Worker id,
1684*bb4ee6a4SAndroid Build Coastguard Worker flags: 0,
1685*bb4ee6a4SAndroid Build Coastguard Worker pfn: 0,
1686*bb4ee6a4SAndroid Build Coastguard Worker size: 0,
1687*bb4ee6a4SAndroid Build Coastguard Worker resp: false,
1688*bb4ee6a4SAndroid Build Coastguard Worker }),
1689*bb4ee6a4SAndroid Build Coastguard Worker }
1690*bb4ee6a4SAndroid Build Coastguard Worker } else {
1691*bb4ee6a4SAndroid Build Coastguard Worker Some(WlResp::VfdRecv {
1692*bb4ee6a4SAndroid Build Coastguard Worker id: self.current_recv_vfd.unwrap(),
1693*bb4ee6a4SAndroid Build Coastguard Worker data: &[],
1694*bb4ee6a4SAndroid Build Coastguard Worker vfds: &self.recv_vfds[..],
1695*bb4ee6a4SAndroid Build Coastguard Worker })
1696*bb4ee6a4SAndroid Build Coastguard Worker }
1697*bb4ee6a4SAndroid Build Coastguard Worker }
1698*bb4ee6a4SAndroid Build Coastguard Worker (vfd_id, WlRecv::Data { ref buf }) => {
1699*bb4ee6a4SAndroid Build Coastguard Worker if self.current_recv_vfd.is_none() || self.current_recv_vfd == Some(vfd_id) {
1700*bb4ee6a4SAndroid Build Coastguard Worker Some(WlResp::VfdRecv {
1701*bb4ee6a4SAndroid Build Coastguard Worker id: vfd_id,
1702*bb4ee6a4SAndroid Build Coastguard Worker data: &buf[..],
1703*bb4ee6a4SAndroid Build Coastguard Worker vfds: &self.recv_vfds[..],
1704*bb4ee6a4SAndroid Build Coastguard Worker })
1705*bb4ee6a4SAndroid Build Coastguard Worker } else {
1706*bb4ee6a4SAndroid Build Coastguard Worker Some(WlResp::VfdRecv {
1707*bb4ee6a4SAndroid Build Coastguard Worker id: self.current_recv_vfd.unwrap(),
1708*bb4ee6a4SAndroid Build Coastguard Worker data: &[],
1709*bb4ee6a4SAndroid Build Coastguard Worker vfds: &self.recv_vfds[..],
1710*bb4ee6a4SAndroid Build Coastguard Worker })
1711*bb4ee6a4SAndroid Build Coastguard Worker }
1712*bb4ee6a4SAndroid Build Coastguard Worker }
1713*bb4ee6a4SAndroid Build Coastguard Worker (vfd_id, WlRecv::Hup) => Some(WlResp::VfdHup { id: vfd_id }),
1714*bb4ee6a4SAndroid Build Coastguard Worker }
1715*bb4ee6a4SAndroid Build Coastguard Worker } else {
1716*bb4ee6a4SAndroid Build Coastguard Worker None
1717*bb4ee6a4SAndroid Build Coastguard Worker }
1718*bb4ee6a4SAndroid Build Coastguard Worker }
1719*bb4ee6a4SAndroid Build Coastguard Worker
pop_recv(&mut self)1720*bb4ee6a4SAndroid Build Coastguard Worker fn pop_recv(&mut self) {
1721*bb4ee6a4SAndroid Build Coastguard Worker if let Some(q) = self.in_queue.front() {
1722*bb4ee6a4SAndroid Build Coastguard Worker match *q {
1723*bb4ee6a4SAndroid Build Coastguard Worker (vfd_id, WlRecv::Vfd { id }) => {
1724*bb4ee6a4SAndroid Build Coastguard Worker if self.current_recv_vfd.is_none() || self.current_recv_vfd == Some(vfd_id) {
1725*bb4ee6a4SAndroid Build Coastguard Worker self.recv_vfds.push(id);
1726*bb4ee6a4SAndroid Build Coastguard Worker self.current_recv_vfd = Some(vfd_id);
1727*bb4ee6a4SAndroid Build Coastguard Worker } else {
1728*bb4ee6a4SAndroid Build Coastguard Worker self.recv_vfds.clear();
1729*bb4ee6a4SAndroid Build Coastguard Worker self.current_recv_vfd = None;
1730*bb4ee6a4SAndroid Build Coastguard Worker return;
1731*bb4ee6a4SAndroid Build Coastguard Worker }
1732*bb4ee6a4SAndroid Build Coastguard Worker }
1733*bb4ee6a4SAndroid Build Coastguard Worker (vfd_id, WlRecv::Data { .. }) => {
1734*bb4ee6a4SAndroid Build Coastguard Worker self.recv_vfds.clear();
1735*bb4ee6a4SAndroid Build Coastguard Worker self.current_recv_vfd = None;
1736*bb4ee6a4SAndroid Build Coastguard Worker if !(self.current_recv_vfd.is_none() || self.current_recv_vfd == Some(vfd_id)) {
1737*bb4ee6a4SAndroid Build Coastguard Worker return;
1738*bb4ee6a4SAndroid Build Coastguard Worker }
1739*bb4ee6a4SAndroid Build Coastguard Worker }
1740*bb4ee6a4SAndroid Build Coastguard Worker (_, WlRecv::Hup) => {
1741*bb4ee6a4SAndroid Build Coastguard Worker self.recv_vfds.clear();
1742*bb4ee6a4SAndroid Build Coastguard Worker self.current_recv_vfd = None;
1743*bb4ee6a4SAndroid Build Coastguard Worker }
1744*bb4ee6a4SAndroid Build Coastguard Worker }
1745*bb4ee6a4SAndroid Build Coastguard Worker }
1746*bb4ee6a4SAndroid Build Coastguard Worker self.in_queue.pop_front();
1747*bb4ee6a4SAndroid Build Coastguard Worker }
1748*bb4ee6a4SAndroid Build Coastguard Worker
compute_pfn(&self, offset: &Option<u64>) -> u641749*bb4ee6a4SAndroid Build Coastguard Worker fn compute_pfn(&self, offset: &Option<u64>) -> u64 {
1750*bb4ee6a4SAndroid Build Coastguard Worker let addr = match (offset, self.address_offset) {
1751*bb4ee6a4SAndroid Build Coastguard Worker (Some(o), Some(address_offset)) => o + address_offset,
1752*bb4ee6a4SAndroid Build Coastguard Worker (Some(o), None) => *o,
1753*bb4ee6a4SAndroid Build Coastguard Worker // without shmem, 0 is the special address for "no_pfn"
1754*bb4ee6a4SAndroid Build Coastguard Worker (None, Some(_)) => 0,
1755*bb4ee6a4SAndroid Build Coastguard Worker // with shmem, WL_SHMEM_SIZE is the special address for "no_pfn"
1756*bb4ee6a4SAndroid Build Coastguard Worker (None, None) => WL_SHMEM_SIZE,
1757*bb4ee6a4SAndroid Build Coastguard Worker };
1758*bb4ee6a4SAndroid Build Coastguard Worker addr >> VIRTIO_WL_PFN_SHIFT
1759*bb4ee6a4SAndroid Build Coastguard Worker }
1760*bb4ee6a4SAndroid Build Coastguard Worker }
1761*bb4ee6a4SAndroid Build Coastguard Worker
1762*bb4ee6a4SAndroid Build Coastguard Worker #[derive(ThisError, Debug, PartialEq, Eq)]
1763*bb4ee6a4SAndroid Build Coastguard Worker #[error("no descriptors available in queue")]
1764*bb4ee6a4SAndroid Build Coastguard Worker pub struct DescriptorsExhausted;
1765*bb4ee6a4SAndroid Build Coastguard Worker
1766*bb4ee6a4SAndroid Build Coastguard Worker /// Handle incoming events and forward them to the VM over the input queue.
process_in_queue( in_queue: &mut Queue, state: &mut WlState, ) -> ::std::result::Result<(), DescriptorsExhausted>1767*bb4ee6a4SAndroid Build Coastguard Worker pub fn process_in_queue(
1768*bb4ee6a4SAndroid Build Coastguard Worker in_queue: &mut Queue,
1769*bb4ee6a4SAndroid Build Coastguard Worker state: &mut WlState,
1770*bb4ee6a4SAndroid Build Coastguard Worker ) -> ::std::result::Result<(), DescriptorsExhausted> {
1771*bb4ee6a4SAndroid Build Coastguard Worker state.process_wait_context();
1772*bb4ee6a4SAndroid Build Coastguard Worker
1773*bb4ee6a4SAndroid Build Coastguard Worker let mut needs_interrupt = false;
1774*bb4ee6a4SAndroid Build Coastguard Worker let mut exhausted_queue = false;
1775*bb4ee6a4SAndroid Build Coastguard Worker loop {
1776*bb4ee6a4SAndroid Build Coastguard Worker let mut desc = if let Some(d) = in_queue.peek() {
1777*bb4ee6a4SAndroid Build Coastguard Worker d
1778*bb4ee6a4SAndroid Build Coastguard Worker } else {
1779*bb4ee6a4SAndroid Build Coastguard Worker exhausted_queue = true;
1780*bb4ee6a4SAndroid Build Coastguard Worker break;
1781*bb4ee6a4SAndroid Build Coastguard Worker };
1782*bb4ee6a4SAndroid Build Coastguard Worker
1783*bb4ee6a4SAndroid Build Coastguard Worker let mut should_pop = false;
1784*bb4ee6a4SAndroid Build Coastguard Worker if let Some(in_resp) = state.next_recv() {
1785*bb4ee6a4SAndroid Build Coastguard Worker match encode_resp(&mut desc.writer, in_resp) {
1786*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) => {
1787*bb4ee6a4SAndroid Build Coastguard Worker should_pop = true;
1788*bb4ee6a4SAndroid Build Coastguard Worker }
1789*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
1790*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to encode response to descriptor chain: {}", e);
1791*bb4ee6a4SAndroid Build Coastguard Worker }
1792*bb4ee6a4SAndroid Build Coastguard Worker }
1793*bb4ee6a4SAndroid Build Coastguard Worker let bytes_written = desc.writer.bytes_written() as u32;
1794*bb4ee6a4SAndroid Build Coastguard Worker needs_interrupt = true;
1795*bb4ee6a4SAndroid Build Coastguard Worker let desc = desc.pop();
1796*bb4ee6a4SAndroid Build Coastguard Worker in_queue.add_used(desc, bytes_written);
1797*bb4ee6a4SAndroid Build Coastguard Worker } else {
1798*bb4ee6a4SAndroid Build Coastguard Worker break;
1799*bb4ee6a4SAndroid Build Coastguard Worker }
1800*bb4ee6a4SAndroid Build Coastguard Worker if should_pop {
1801*bb4ee6a4SAndroid Build Coastguard Worker state.pop_recv();
1802*bb4ee6a4SAndroid Build Coastguard Worker }
1803*bb4ee6a4SAndroid Build Coastguard Worker }
1804*bb4ee6a4SAndroid Build Coastguard Worker
1805*bb4ee6a4SAndroid Build Coastguard Worker if needs_interrupt {
1806*bb4ee6a4SAndroid Build Coastguard Worker in_queue.trigger_interrupt();
1807*bb4ee6a4SAndroid Build Coastguard Worker }
1808*bb4ee6a4SAndroid Build Coastguard Worker
1809*bb4ee6a4SAndroid Build Coastguard Worker if exhausted_queue {
1810*bb4ee6a4SAndroid Build Coastguard Worker Err(DescriptorsExhausted)
1811*bb4ee6a4SAndroid Build Coastguard Worker } else {
1812*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
1813*bb4ee6a4SAndroid Build Coastguard Worker }
1814*bb4ee6a4SAndroid Build Coastguard Worker }
1815*bb4ee6a4SAndroid Build Coastguard Worker
1816*bb4ee6a4SAndroid Build Coastguard Worker /// Handle messages from the output queue and forward them to the display sever, if necessary.
process_out_queue(out_queue: &mut Queue, state: &mut WlState)1817*bb4ee6a4SAndroid Build Coastguard Worker pub fn process_out_queue(out_queue: &mut Queue, state: &mut WlState) {
1818*bb4ee6a4SAndroid Build Coastguard Worker let mut needs_interrupt = false;
1819*bb4ee6a4SAndroid Build Coastguard Worker while let Some(mut desc) = out_queue.pop() {
1820*bb4ee6a4SAndroid Build Coastguard Worker let resp = match state.execute(&mut desc.reader) {
1821*bb4ee6a4SAndroid Build Coastguard Worker Ok(r) => r,
1822*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => WlResp::Err(Box::new(e)),
1823*bb4ee6a4SAndroid Build Coastguard Worker };
1824*bb4ee6a4SAndroid Build Coastguard Worker
1825*bb4ee6a4SAndroid Build Coastguard Worker match encode_resp(&mut desc.writer, resp) {
1826*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) => {}
1827*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
1828*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to encode response to descriptor chain: {}", e);
1829*bb4ee6a4SAndroid Build Coastguard Worker }
1830*bb4ee6a4SAndroid Build Coastguard Worker }
1831*bb4ee6a4SAndroid Build Coastguard Worker
1832*bb4ee6a4SAndroid Build Coastguard Worker let len = desc.writer.bytes_written() as u32;
1833*bb4ee6a4SAndroid Build Coastguard Worker out_queue.add_used(desc, len);
1834*bb4ee6a4SAndroid Build Coastguard Worker needs_interrupt = true;
1835*bb4ee6a4SAndroid Build Coastguard Worker }
1836*bb4ee6a4SAndroid Build Coastguard Worker
1837*bb4ee6a4SAndroid Build Coastguard Worker if needs_interrupt {
1838*bb4ee6a4SAndroid Build Coastguard Worker out_queue.trigger_interrupt();
1839*bb4ee6a4SAndroid Build Coastguard Worker }
1840*bb4ee6a4SAndroid Build Coastguard Worker }
1841*bb4ee6a4SAndroid Build Coastguard Worker
1842*bb4ee6a4SAndroid Build Coastguard Worker struct Worker {
1843*bb4ee6a4SAndroid Build Coastguard Worker interrupt: Interrupt,
1844*bb4ee6a4SAndroid Build Coastguard Worker in_queue: Queue,
1845*bb4ee6a4SAndroid Build Coastguard Worker out_queue: Queue,
1846*bb4ee6a4SAndroid Build Coastguard Worker state: WlState,
1847*bb4ee6a4SAndroid Build Coastguard Worker }
1848*bb4ee6a4SAndroid Build Coastguard Worker
1849*bb4ee6a4SAndroid Build Coastguard Worker impl Worker {
new( interrupt: Interrupt, in_queue: Queue, out_queue: Queue, wayland_paths: BTreeMap<String, PathBuf>, mapper: Box<dyn SharedMemoryMapper>, use_transition_flags: bool, use_send_vfd_v2: bool, resource_bridge: Option<Tube>, #[cfg(feature = "minigbm")] gralloc: RutabagaGralloc, address_offset: Option<u64>, ) -> Worker1850*bb4ee6a4SAndroid Build Coastguard Worker fn new(
1851*bb4ee6a4SAndroid Build Coastguard Worker interrupt: Interrupt,
1852*bb4ee6a4SAndroid Build Coastguard Worker in_queue: Queue,
1853*bb4ee6a4SAndroid Build Coastguard Worker out_queue: Queue,
1854*bb4ee6a4SAndroid Build Coastguard Worker wayland_paths: BTreeMap<String, PathBuf>,
1855*bb4ee6a4SAndroid Build Coastguard Worker mapper: Box<dyn SharedMemoryMapper>,
1856*bb4ee6a4SAndroid Build Coastguard Worker use_transition_flags: bool,
1857*bb4ee6a4SAndroid Build Coastguard Worker use_send_vfd_v2: bool,
1858*bb4ee6a4SAndroid Build Coastguard Worker resource_bridge: Option<Tube>,
1859*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")] gralloc: RutabagaGralloc,
1860*bb4ee6a4SAndroid Build Coastguard Worker address_offset: Option<u64>,
1861*bb4ee6a4SAndroid Build Coastguard Worker ) -> Worker {
1862*bb4ee6a4SAndroid Build Coastguard Worker Worker {
1863*bb4ee6a4SAndroid Build Coastguard Worker interrupt,
1864*bb4ee6a4SAndroid Build Coastguard Worker in_queue,
1865*bb4ee6a4SAndroid Build Coastguard Worker out_queue,
1866*bb4ee6a4SAndroid Build Coastguard Worker state: WlState::new(
1867*bb4ee6a4SAndroid Build Coastguard Worker wayland_paths,
1868*bb4ee6a4SAndroid Build Coastguard Worker mapper,
1869*bb4ee6a4SAndroid Build Coastguard Worker use_transition_flags,
1870*bb4ee6a4SAndroid Build Coastguard Worker use_send_vfd_v2,
1871*bb4ee6a4SAndroid Build Coastguard Worker resource_bridge,
1872*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
1873*bb4ee6a4SAndroid Build Coastguard Worker gralloc,
1874*bb4ee6a4SAndroid Build Coastguard Worker address_offset,
1875*bb4ee6a4SAndroid Build Coastguard Worker ),
1876*bb4ee6a4SAndroid Build Coastguard Worker }
1877*bb4ee6a4SAndroid Build Coastguard Worker }
1878*bb4ee6a4SAndroid Build Coastguard Worker
run(mut self, kill_evt: Event) -> anyhow::Result<Vec<Queue>>1879*bb4ee6a4SAndroid Build Coastguard Worker fn run(mut self, kill_evt: Event) -> anyhow::Result<Vec<Queue>> {
1880*bb4ee6a4SAndroid Build Coastguard Worker #[derive(EventToken)]
1881*bb4ee6a4SAndroid Build Coastguard Worker enum Token {
1882*bb4ee6a4SAndroid Build Coastguard Worker InQueue,
1883*bb4ee6a4SAndroid Build Coastguard Worker OutQueue,
1884*bb4ee6a4SAndroid Build Coastguard Worker Kill,
1885*bb4ee6a4SAndroid Build Coastguard Worker State,
1886*bb4ee6a4SAndroid Build Coastguard Worker InterruptResample,
1887*bb4ee6a4SAndroid Build Coastguard Worker }
1888*bb4ee6a4SAndroid Build Coastguard Worker
1889*bb4ee6a4SAndroid Build Coastguard Worker let wait_ctx: WaitContext<Token> = WaitContext::build_with(&[
1890*bb4ee6a4SAndroid Build Coastguard Worker (self.in_queue.event(), Token::InQueue),
1891*bb4ee6a4SAndroid Build Coastguard Worker (self.out_queue.event(), Token::OutQueue),
1892*bb4ee6a4SAndroid Build Coastguard Worker (&kill_evt, Token::Kill),
1893*bb4ee6a4SAndroid Build Coastguard Worker (&self.state.wait_ctx, Token::State),
1894*bb4ee6a4SAndroid Build Coastguard Worker ])
1895*bb4ee6a4SAndroid Build Coastguard Worker .context("failed creating WaitContext")?;
1896*bb4ee6a4SAndroid Build Coastguard Worker
1897*bb4ee6a4SAndroid Build Coastguard Worker if let Some(resample_evt) = self.interrupt.get_resample_evt() {
1898*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx
1899*bb4ee6a4SAndroid Build Coastguard Worker .add(resample_evt, Token::InterruptResample)
1900*bb4ee6a4SAndroid Build Coastguard Worker .context("failed adding resample event to WaitContext.")?;
1901*bb4ee6a4SAndroid Build Coastguard Worker }
1902*bb4ee6a4SAndroid Build Coastguard Worker
1903*bb4ee6a4SAndroid Build Coastguard Worker let mut watching_state_ctx = true;
1904*bb4ee6a4SAndroid Build Coastguard Worker 'wait: loop {
1905*bb4ee6a4SAndroid Build Coastguard Worker let events = match wait_ctx.wait() {
1906*bb4ee6a4SAndroid Build Coastguard Worker Ok(v) => v,
1907*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
1908*bb4ee6a4SAndroid Build Coastguard Worker error!("failed waiting for events: {}", e);
1909*bb4ee6a4SAndroid Build Coastguard Worker break;
1910*bb4ee6a4SAndroid Build Coastguard Worker }
1911*bb4ee6a4SAndroid Build Coastguard Worker };
1912*bb4ee6a4SAndroid Build Coastguard Worker
1913*bb4ee6a4SAndroid Build Coastguard Worker for event in &events {
1914*bb4ee6a4SAndroid Build Coastguard Worker match event.token {
1915*bb4ee6a4SAndroid Build Coastguard Worker Token::InQueue => {
1916*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.in_queue.event().wait();
1917*bb4ee6a4SAndroid Build Coastguard Worker if !watching_state_ctx {
1918*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) =
1919*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx.modify(&self.state.wait_ctx, EventType::Read, Token::State)
1920*bb4ee6a4SAndroid Build Coastguard Worker {
1921*bb4ee6a4SAndroid Build Coastguard Worker error!("Failed to modify wait_ctx descriptor for WlState: {}", e);
1922*bb4ee6a4SAndroid Build Coastguard Worker break;
1923*bb4ee6a4SAndroid Build Coastguard Worker }
1924*bb4ee6a4SAndroid Build Coastguard Worker watching_state_ctx = true;
1925*bb4ee6a4SAndroid Build Coastguard Worker }
1926*bb4ee6a4SAndroid Build Coastguard Worker }
1927*bb4ee6a4SAndroid Build Coastguard Worker Token::OutQueue => {
1928*bb4ee6a4SAndroid Build Coastguard Worker let _ = self.out_queue.event().wait();
1929*bb4ee6a4SAndroid Build Coastguard Worker process_out_queue(&mut self.out_queue, &mut self.state);
1930*bb4ee6a4SAndroid Build Coastguard Worker }
1931*bb4ee6a4SAndroid Build Coastguard Worker Token::Kill => break 'wait,
1932*bb4ee6a4SAndroid Build Coastguard Worker Token::State => {
1933*bb4ee6a4SAndroid Build Coastguard Worker if let Err(DescriptorsExhausted) =
1934*bb4ee6a4SAndroid Build Coastguard Worker process_in_queue(&mut self.in_queue, &mut self.state)
1935*bb4ee6a4SAndroid Build Coastguard Worker {
1936*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) =
1937*bb4ee6a4SAndroid Build Coastguard Worker wait_ctx.modify(&self.state.wait_ctx, EventType::None, Token::State)
1938*bb4ee6a4SAndroid Build Coastguard Worker {
1939*bb4ee6a4SAndroid Build Coastguard Worker error!(
1940*bb4ee6a4SAndroid Build Coastguard Worker "Failed to stop watching wait_ctx descriptor for WlState: {}",
1941*bb4ee6a4SAndroid Build Coastguard Worker e
1942*bb4ee6a4SAndroid Build Coastguard Worker );
1943*bb4ee6a4SAndroid Build Coastguard Worker break;
1944*bb4ee6a4SAndroid Build Coastguard Worker }
1945*bb4ee6a4SAndroid Build Coastguard Worker watching_state_ctx = false;
1946*bb4ee6a4SAndroid Build Coastguard Worker }
1947*bb4ee6a4SAndroid Build Coastguard Worker }
1948*bb4ee6a4SAndroid Build Coastguard Worker Token::InterruptResample => {
1949*bb4ee6a4SAndroid Build Coastguard Worker self.interrupt.interrupt_resample();
1950*bb4ee6a4SAndroid Build Coastguard Worker }
1951*bb4ee6a4SAndroid Build Coastguard Worker }
1952*bb4ee6a4SAndroid Build Coastguard Worker }
1953*bb4ee6a4SAndroid Build Coastguard Worker }
1954*bb4ee6a4SAndroid Build Coastguard Worker
1955*bb4ee6a4SAndroid Build Coastguard Worker let in_queue = self.in_queue;
1956*bb4ee6a4SAndroid Build Coastguard Worker let out_queue = self.out_queue;
1957*bb4ee6a4SAndroid Build Coastguard Worker
1958*bb4ee6a4SAndroid Build Coastguard Worker Ok(vec![in_queue, out_queue])
1959*bb4ee6a4SAndroid Build Coastguard Worker }
1960*bb4ee6a4SAndroid Build Coastguard Worker }
1961*bb4ee6a4SAndroid Build Coastguard Worker
1962*bb4ee6a4SAndroid Build Coastguard Worker pub struct Wl {
1963*bb4ee6a4SAndroid Build Coastguard Worker worker_thread: Option<WorkerThread<anyhow::Result<Vec<Queue>>>>,
1964*bb4ee6a4SAndroid Build Coastguard Worker wayland_paths: BTreeMap<String, PathBuf>,
1965*bb4ee6a4SAndroid Build Coastguard Worker mapper: Option<Box<dyn SharedMemoryMapper>>,
1966*bb4ee6a4SAndroid Build Coastguard Worker resource_bridge: Option<Tube>,
1967*bb4ee6a4SAndroid Build Coastguard Worker base_features: u64,
1968*bb4ee6a4SAndroid Build Coastguard Worker acked_features: u64,
1969*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
1970*bb4ee6a4SAndroid Build Coastguard Worker gralloc: Option<RutabagaGralloc>,
1971*bb4ee6a4SAndroid Build Coastguard Worker address_offset: Option<u64>,
1972*bb4ee6a4SAndroid Build Coastguard Worker }
1973*bb4ee6a4SAndroid Build Coastguard Worker
1974*bb4ee6a4SAndroid Build Coastguard Worker impl Wl {
new( base_features: u64, wayland_paths: BTreeMap<String, PathBuf>, resource_bridge: Option<Tube>, ) -> Result<Wl>1975*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(
1976*bb4ee6a4SAndroid Build Coastguard Worker base_features: u64,
1977*bb4ee6a4SAndroid Build Coastguard Worker wayland_paths: BTreeMap<String, PathBuf>,
1978*bb4ee6a4SAndroid Build Coastguard Worker resource_bridge: Option<Tube>,
1979*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<Wl> {
1980*bb4ee6a4SAndroid Build Coastguard Worker Ok(Wl {
1981*bb4ee6a4SAndroid Build Coastguard Worker worker_thread: None,
1982*bb4ee6a4SAndroid Build Coastguard Worker wayland_paths,
1983*bb4ee6a4SAndroid Build Coastguard Worker mapper: None,
1984*bb4ee6a4SAndroid Build Coastguard Worker resource_bridge,
1985*bb4ee6a4SAndroid Build Coastguard Worker base_features,
1986*bb4ee6a4SAndroid Build Coastguard Worker acked_features: 0,
1987*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
1988*bb4ee6a4SAndroid Build Coastguard Worker gralloc: None,
1989*bb4ee6a4SAndroid Build Coastguard Worker address_offset: None,
1990*bb4ee6a4SAndroid Build Coastguard Worker })
1991*bb4ee6a4SAndroid Build Coastguard Worker }
1992*bb4ee6a4SAndroid Build Coastguard Worker }
1993*bb4ee6a4SAndroid Build Coastguard Worker
1994*bb4ee6a4SAndroid Build Coastguard Worker impl VirtioDevice for Wl {
keep_rds(&self) -> Vec<RawDescriptor>1995*bb4ee6a4SAndroid Build Coastguard Worker fn keep_rds(&self) -> Vec<RawDescriptor> {
1996*bb4ee6a4SAndroid Build Coastguard Worker let mut keep_rds = Vec::new();
1997*bb4ee6a4SAndroid Build Coastguard Worker
1998*bb4ee6a4SAndroid Build Coastguard Worker if let Some(mapper) = &self.mapper {
1999*bb4ee6a4SAndroid Build Coastguard Worker if let Some(raw_descriptor) = mapper.as_raw_descriptor() {
2000*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(raw_descriptor);
2001*bb4ee6a4SAndroid Build Coastguard Worker }
2002*bb4ee6a4SAndroid Build Coastguard Worker }
2003*bb4ee6a4SAndroid Build Coastguard Worker if let Some(resource_bridge) = &self.resource_bridge {
2004*bb4ee6a4SAndroid Build Coastguard Worker keep_rds.push(resource_bridge.as_raw_descriptor());
2005*bb4ee6a4SAndroid Build Coastguard Worker }
2006*bb4ee6a4SAndroid Build Coastguard Worker keep_rds
2007*bb4ee6a4SAndroid Build Coastguard Worker }
2008*bb4ee6a4SAndroid Build Coastguard Worker
2009*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
on_device_sandboxed(&mut self)2010*bb4ee6a4SAndroid Build Coastguard Worker fn on_device_sandboxed(&mut self) {
2011*bb4ee6a4SAndroid Build Coastguard Worker // Gralloc initialization can cause some GPU drivers to create their own threads
2012*bb4ee6a4SAndroid Build Coastguard Worker // and that must be done after sandboxing.
2013*bb4ee6a4SAndroid Build Coastguard Worker match RutabagaGralloc::new(RutabagaGrallocBackendFlags::new()) {
2014*bb4ee6a4SAndroid Build Coastguard Worker Ok(g) => self.gralloc = Some(g),
2015*bb4ee6a4SAndroid Build Coastguard Worker Err(e) => {
2016*bb4ee6a4SAndroid Build Coastguard Worker error!("failed to initialize gralloc {:?}", e);
2017*bb4ee6a4SAndroid Build Coastguard Worker }
2018*bb4ee6a4SAndroid Build Coastguard Worker };
2019*bb4ee6a4SAndroid Build Coastguard Worker }
2020*bb4ee6a4SAndroid Build Coastguard Worker
device_type(&self) -> DeviceType2021*bb4ee6a4SAndroid Build Coastguard Worker fn device_type(&self) -> DeviceType {
2022*bb4ee6a4SAndroid Build Coastguard Worker DeviceType::Wl
2023*bb4ee6a4SAndroid Build Coastguard Worker }
2024*bb4ee6a4SAndroid Build Coastguard Worker
queue_max_sizes(&self) -> &[u16]2025*bb4ee6a4SAndroid Build Coastguard Worker fn queue_max_sizes(&self) -> &[u16] {
2026*bb4ee6a4SAndroid Build Coastguard Worker QUEUE_SIZES
2027*bb4ee6a4SAndroid Build Coastguard Worker }
2028*bb4ee6a4SAndroid Build Coastguard Worker
features(&self) -> u642029*bb4ee6a4SAndroid Build Coastguard Worker fn features(&self) -> u64 {
2030*bb4ee6a4SAndroid Build Coastguard Worker self.base_features
2031*bb4ee6a4SAndroid Build Coastguard Worker | 1 << VIRTIO_WL_F_TRANS_FLAGS
2032*bb4ee6a4SAndroid Build Coastguard Worker | 1 << VIRTIO_WL_F_SEND_FENCES
2033*bb4ee6a4SAndroid Build Coastguard Worker | 1 << VIRTIO_WL_F_USE_SHMEM
2034*bb4ee6a4SAndroid Build Coastguard Worker }
2035*bb4ee6a4SAndroid Build Coastguard Worker
ack_features(&mut self, value: u64)2036*bb4ee6a4SAndroid Build Coastguard Worker fn ack_features(&mut self, value: u64) {
2037*bb4ee6a4SAndroid Build Coastguard Worker self.acked_features |= value;
2038*bb4ee6a4SAndroid Build Coastguard Worker }
2039*bb4ee6a4SAndroid Build Coastguard Worker
activate( &mut self, _mem: GuestMemory, interrupt: Interrupt, mut queues: BTreeMap<usize, Queue>, ) -> anyhow::Result<()>2040*bb4ee6a4SAndroid Build Coastguard Worker fn activate(
2041*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
2042*bb4ee6a4SAndroid Build Coastguard Worker _mem: GuestMemory,
2043*bb4ee6a4SAndroid Build Coastguard Worker interrupt: Interrupt,
2044*bb4ee6a4SAndroid Build Coastguard Worker mut queues: BTreeMap<usize, Queue>,
2045*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> {
2046*bb4ee6a4SAndroid Build Coastguard Worker if queues.len() != QUEUE_SIZES.len() {
2047*bb4ee6a4SAndroid Build Coastguard Worker return Err(anyhow!(
2048*bb4ee6a4SAndroid Build Coastguard Worker "expected {} queues, got {}",
2049*bb4ee6a4SAndroid Build Coastguard Worker QUEUE_SIZES.len(),
2050*bb4ee6a4SAndroid Build Coastguard Worker queues.len()
2051*bb4ee6a4SAndroid Build Coastguard Worker ));
2052*bb4ee6a4SAndroid Build Coastguard Worker }
2053*bb4ee6a4SAndroid Build Coastguard Worker
2054*bb4ee6a4SAndroid Build Coastguard Worker let mapper = self.mapper.take().context("missing mapper")?;
2055*bb4ee6a4SAndroid Build Coastguard Worker
2056*bb4ee6a4SAndroid Build Coastguard Worker let wayland_paths = self.wayland_paths.clone();
2057*bb4ee6a4SAndroid Build Coastguard Worker let use_transition_flags = self.acked_features & (1 << VIRTIO_WL_F_TRANS_FLAGS) != 0;
2058*bb4ee6a4SAndroid Build Coastguard Worker let use_send_vfd_v2 = self.acked_features & (1 << VIRTIO_WL_F_SEND_FENCES) != 0;
2059*bb4ee6a4SAndroid Build Coastguard Worker let use_shmem = self.acked_features & (1 << VIRTIO_WL_F_USE_SHMEM) != 0;
2060*bb4ee6a4SAndroid Build Coastguard Worker let resource_bridge = self.resource_bridge.take();
2061*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
2062*bb4ee6a4SAndroid Build Coastguard Worker let gralloc = self
2063*bb4ee6a4SAndroid Build Coastguard Worker .gralloc
2064*bb4ee6a4SAndroid Build Coastguard Worker .take()
2065*bb4ee6a4SAndroid Build Coastguard Worker .expect("gralloc already passed to worker");
2066*bb4ee6a4SAndroid Build Coastguard Worker let address_offset = if !use_shmem {
2067*bb4ee6a4SAndroid Build Coastguard Worker self.address_offset
2068*bb4ee6a4SAndroid Build Coastguard Worker } else {
2069*bb4ee6a4SAndroid Build Coastguard Worker None
2070*bb4ee6a4SAndroid Build Coastguard Worker };
2071*bb4ee6a4SAndroid Build Coastguard Worker
2072*bb4ee6a4SAndroid Build Coastguard Worker self.worker_thread = Some(WorkerThread::start("v_wl", move |kill_evt| {
2073*bb4ee6a4SAndroid Build Coastguard Worker Worker::new(
2074*bb4ee6a4SAndroid Build Coastguard Worker interrupt,
2075*bb4ee6a4SAndroid Build Coastguard Worker queues.pop_first().unwrap().1,
2076*bb4ee6a4SAndroid Build Coastguard Worker queues.pop_first().unwrap().1,
2077*bb4ee6a4SAndroid Build Coastguard Worker wayland_paths,
2078*bb4ee6a4SAndroid Build Coastguard Worker mapper,
2079*bb4ee6a4SAndroid Build Coastguard Worker use_transition_flags,
2080*bb4ee6a4SAndroid Build Coastguard Worker use_send_vfd_v2,
2081*bb4ee6a4SAndroid Build Coastguard Worker resource_bridge,
2082*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "minigbm")]
2083*bb4ee6a4SAndroid Build Coastguard Worker gralloc,
2084*bb4ee6a4SAndroid Build Coastguard Worker address_offset,
2085*bb4ee6a4SAndroid Build Coastguard Worker )
2086*bb4ee6a4SAndroid Build Coastguard Worker .run(kill_evt)
2087*bb4ee6a4SAndroid Build Coastguard Worker }));
2088*bb4ee6a4SAndroid Build Coastguard Worker
2089*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
2090*bb4ee6a4SAndroid Build Coastguard Worker }
2091*bb4ee6a4SAndroid Build Coastguard Worker
get_shared_memory_region(&self) -> Option<SharedMemoryRegion>2092*bb4ee6a4SAndroid Build Coastguard Worker fn get_shared_memory_region(&self) -> Option<SharedMemoryRegion> {
2093*bb4ee6a4SAndroid Build Coastguard Worker Some(SharedMemoryRegion {
2094*bb4ee6a4SAndroid Build Coastguard Worker id: WL_SHMEM_ID,
2095*bb4ee6a4SAndroid Build Coastguard Worker length: WL_SHMEM_SIZE,
2096*bb4ee6a4SAndroid Build Coastguard Worker })
2097*bb4ee6a4SAndroid Build Coastguard Worker }
2098*bb4ee6a4SAndroid Build Coastguard Worker
set_shared_memory_region_base(&mut self, shmem_base: GuestAddress)2099*bb4ee6a4SAndroid Build Coastguard Worker fn set_shared_memory_region_base(&mut self, shmem_base: GuestAddress) {
2100*bb4ee6a4SAndroid Build Coastguard Worker self.address_offset = Some(shmem_base.0);
2101*bb4ee6a4SAndroid Build Coastguard Worker }
2102*bb4ee6a4SAndroid Build Coastguard Worker
set_shared_memory_mapper(&mut self, mapper: Box<dyn SharedMemoryMapper>)2103*bb4ee6a4SAndroid Build Coastguard Worker fn set_shared_memory_mapper(&mut self, mapper: Box<dyn SharedMemoryMapper>) {
2104*bb4ee6a4SAndroid Build Coastguard Worker self.mapper = Some(mapper);
2105*bb4ee6a4SAndroid Build Coastguard Worker }
2106*bb4ee6a4SAndroid Build Coastguard Worker
virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>>2107*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_sleep(&mut self) -> anyhow::Result<Option<BTreeMap<usize, Queue>>> {
2108*bb4ee6a4SAndroid Build Coastguard Worker if let Some(worker_thread) = self.worker_thread.take() {
2109*bb4ee6a4SAndroid Build Coastguard Worker let queues = worker_thread.stop()?;
2110*bb4ee6a4SAndroid Build Coastguard Worker return Ok(Some(BTreeMap::from_iter(queues.into_iter().enumerate())));
2111*bb4ee6a4SAndroid Build Coastguard Worker }
2112*bb4ee6a4SAndroid Build Coastguard Worker Ok(None)
2113*bb4ee6a4SAndroid Build Coastguard Worker }
2114*bb4ee6a4SAndroid Build Coastguard Worker
virtio_wake( &mut self, device_state: Option<(GuestMemory, Interrupt, BTreeMap<usize, Queue>)>, ) -> anyhow::Result<()>2115*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_wake(
2116*bb4ee6a4SAndroid Build Coastguard Worker &mut self,
2117*bb4ee6a4SAndroid Build Coastguard Worker device_state: Option<(GuestMemory, Interrupt, BTreeMap<usize, Queue>)>,
2118*bb4ee6a4SAndroid Build Coastguard Worker ) -> anyhow::Result<()> {
2119*bb4ee6a4SAndroid Build Coastguard Worker match device_state {
2120*bb4ee6a4SAndroid Build Coastguard Worker None => Ok(()),
2121*bb4ee6a4SAndroid Build Coastguard Worker Some((mem, interrupt, queues)) => {
2122*bb4ee6a4SAndroid Build Coastguard Worker // TODO: activate is just what we want at the moment, but we should probably move
2123*bb4ee6a4SAndroid Build Coastguard Worker // it into a "start workers" function to make it obvious that it isn't strictly
2124*bb4ee6a4SAndroid Build Coastguard Worker // used for activate events.
2125*bb4ee6a4SAndroid Build Coastguard Worker self.activate(mem, interrupt, queues)?;
2126*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
2127*bb4ee6a4SAndroid Build Coastguard Worker }
2128*bb4ee6a4SAndroid Build Coastguard Worker }
2129*bb4ee6a4SAndroid Build Coastguard Worker }
2130*bb4ee6a4SAndroid Build Coastguard Worker
2131*bb4ee6a4SAndroid Build Coastguard Worker // ANDROID: Add empty implementations for successful snapshot taking. Change to full
2132*bb4ee6a4SAndroid Build Coastguard Worker // implementation as part of b/266514618
2133*bb4ee6a4SAndroid Build Coastguard Worker // virtio-wl is not used, but is created. As such, virtio_snapshot/restore will be called when
2134*bb4ee6a4SAndroid Build Coastguard Worker // cuttlefish attempts to take a snapshot.
virtio_snapshot(&mut self) -> anyhow::Result<serde_json::Value>2135*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_snapshot(&mut self) -> anyhow::Result<serde_json::Value> {
2136*bb4ee6a4SAndroid Build Coastguard Worker Ok(serde_json::Value::Null)
2137*bb4ee6a4SAndroid Build Coastguard Worker }
2138*bb4ee6a4SAndroid Build Coastguard Worker
virtio_restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>2139*bb4ee6a4SAndroid Build Coastguard Worker fn virtio_restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> {
2140*bb4ee6a4SAndroid Build Coastguard Worker anyhow::ensure!(
2141*bb4ee6a4SAndroid Build Coastguard Worker data == serde_json::Value::Null,
2142*bb4ee6a4SAndroid Build Coastguard Worker "unexpected snapshot data: should be null, got {}",
2143*bb4ee6a4SAndroid Build Coastguard Worker data,
2144*bb4ee6a4SAndroid Build Coastguard Worker );
2145*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
2146*bb4ee6a4SAndroid Build Coastguard Worker }
2147*bb4ee6a4SAndroid Build Coastguard Worker }
2148