• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Contains constants and struct definitions used for implementing vhost-user
6 //! frontend devices without compile-time dependencies on their corresponding
7 //! backend devices.
8 
9 use data_model::Le16;
10 use data_model::Le32;
11 use data_model::Le64;
12 use zerocopy::AsBytes;
13 use zerocopy::FromBytes;
14 
15 pub mod block {
16     use super::*;
17 
18     pub const VIRTIO_BLK_T_IN: u32 = 0;
19     pub const VIRTIO_BLK_T_OUT: u32 = 1;
20     pub const VIRTIO_BLK_T_FLUSH: u32 = 4;
21     pub const VIRTIO_BLK_T_GET_ID: u32 = 8;
22     pub const VIRTIO_BLK_T_DISCARD: u32 = 11;
23     pub const VIRTIO_BLK_T_WRITE_ZEROES: u32 = 13;
24 
25     pub const VIRTIO_BLK_S_OK: u8 = 0;
26     pub const VIRTIO_BLK_S_IOERR: u8 = 1;
27     pub const VIRTIO_BLK_S_UNSUPP: u8 = 2;
28 
29     pub const VIRTIO_BLK_F_SEG_MAX: u32 = 2;
30     pub const VIRTIO_BLK_F_RO: u32 = 5;
31     pub const VIRTIO_BLK_F_BLK_SIZE: u32 = 6;
32     pub const VIRTIO_BLK_F_FLUSH: u32 = 9;
33     pub const VIRTIO_BLK_F_MQ: u32 = 12;
34     pub const VIRTIO_BLK_F_DISCARD: u32 = 13;
35     pub const VIRTIO_BLK_F_WRITE_ZEROES: u32 = 14;
36 
37     #[derive(Copy, Clone, Debug, Default, AsBytes, FromBytes)]
38     #[repr(C)]
39     pub struct virtio_blk_geometry {
40         cylinders: Le16,
41         heads: u8,
42         sectors: u8,
43     }
44 
45     #[derive(Copy, Clone, Debug, Default, AsBytes, FromBytes)]
46     #[repr(C)]
47     pub struct virtio_blk_topology {
48         physical_block_exp: u8,
49         alignment_offset: u8,
50         min_io_size: Le16,
51         opt_io_size: Le32,
52     }
53 
54     #[derive(Copy, Clone, Debug, Default, AsBytes, FromBytes)]
55     #[repr(C, packed)]
56     pub struct virtio_blk_config {
57         pub capacity: Le64,
58         pub size_max: Le32,
59         pub seg_max: Le32,
60         pub geometry: virtio_blk_geometry,
61         pub blk_size: Le32,
62         pub topology: virtio_blk_topology,
63         pub writeback: u8,
64         pub unused0: u8,
65         pub num_queues: Le16,
66         pub max_discard_sectors: Le32,
67         pub max_discard_seg: Le32,
68         pub discard_sector_alignment: Le32,
69         pub max_write_zeroes_sectors: Le32,
70         pub max_write_zeroes_seg: Le32,
71         pub write_zeroes_may_unmap: u8,
72         pub unused1: [u8; 3],
73     }
74 
75     #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
76     #[repr(C)]
77     pub(crate) struct virtio_blk_req_header {
78         pub req_type: Le32,
79         pub reserved: Le32,
80         pub sector: Le64,
81     }
82 
83     #[derive(Copy, Clone, Debug, Default, FromBytes, AsBytes)]
84     #[repr(C)]
85     pub(crate) struct virtio_blk_discard_write_zeroes {
86         pub sector: Le64,
87         pub num_sectors: Le32,
88         pub flags: Le32,
89     }
90 
91     pub(crate) const VIRTIO_BLK_DISCARD_WRITE_ZEROES_FLAG_UNMAP: u32 = 1 << 0;
92 }
93 
94 pub mod fs {
95     /// The maximum allowable length of the tag used to identify a specific virtio-fs device.
96     pub const FS_MAX_TAG_LEN: usize = 36;
97 
98     // The fs device does not have a fixed number of queues.
99     pub const QUEUE_SIZE: u16 = 1024;
100 }
101 
102 pub mod gpu {
103     use super::*;
104 
105     // First queue is for virtio gpu commands. Second queue is for cursor commands, which we expect
106     // there to be fewer of.
107     pub const QUEUE_SIZES: &[u16] = &[512, 16];
108 
109     pub const VIRTIO_GPU_F_VIRGL: u32 = 0;
110     pub const VIRTIO_GPU_F_EDID: u32 = 1;
111     pub const VIRTIO_GPU_F_RESOURCE_UUID: u32 = 2;
112     pub const VIRTIO_GPU_F_RESOURCE_BLOB: u32 = 3;
113     pub const VIRTIO_GPU_F_CONTEXT_INIT: u32 = 4;
114     /* The following capabilities are not upstreamed. */
115     pub const VIRTIO_GPU_F_RESOURCE_SYNC: u32 = 5;
116     pub const VIRTIO_GPU_F_CREATE_GUEST_HANDLE: u32 = 6;
117 
118     pub const VIRTIO_GPU_SHM_ID_HOST_VISIBLE: u8 = 0x0001;
119 
120     #[derive(Copy, Clone, Debug, Default, AsBytes, FromBytes)]
121     #[repr(C)]
122     pub struct virtio_gpu_config {
123         pub events_read: Le32,
124         pub events_clear: Le32,
125         pub num_scanouts: Le32,
126         pub num_capsets: Le32,
127     }
128 }
129 
130 pub mod snd {
131     use super::*;
132 
133     #[derive(Copy, Clone, Default, AsBytes, FromBytes)]
134     #[repr(C, packed)]
135     pub struct virtio_snd_config {
136         pub jacks: Le32,
137         pub streams: Le32,
138         pub chmaps: Le32,
139     }
140 }
141 
142 pub mod video {
143     use data_model::Le32;
144     use serde::Deserialize;
145     use serde::Serialize;
146     use serde_keyvalue::FromKeyValues;
147     use zerocopy::AsBytes;
148     use zerocopy::FromBytes;
149 
150     // CMD_QUEUE_SIZE = max number of command descriptors for input and output queues
151     // Experimentally, it appears a stream allocates 16 input and 26 output buffers = 42 total
152     // For 8 simultaneous streams, 2 descs per buffer * 42 buffers * 8 streams = 672 descs
153     // Allocate 1024 to give some headroom in case of extra streams/buffers
154     //
155     // TODO(b/204055006): Make cmd queue size dependent of
156     // (max buf cnt for input + max buf cnt for output) * max descs per buffer * max nb of streams
157     const CMD_QUEUE_SIZE: u16 = 1024;
158     pub const CMD_QUEUE_INDEX: usize = 0;
159     // EVENT_QUEUE_SIZE = max number of event descriptors for stream events like resolution changes
160     const EVENT_QUEUE_SIZE: u16 = 256;
161     pub const EVENT_QUEUE_INDEX: usize = 1;
162     pub const QUEUE_SIZES: &[u16] = &[CMD_QUEUE_SIZE, EVENT_QUEUE_SIZE];
163 
164     pub const VIRTIO_VIDEO_F_RESOURCE_GUEST_PAGES: u32 = 0;
165     pub const VIRTIO_VIDEO_F_RESOURCE_NON_CONTIG: u32 = 1;
166     pub const VIRTIO_VIDEO_F_RESOURCE_VIRTIO_OBJECT: u32 = 2;
167 
168     #[derive(Debug, Clone, Copy)]
169     pub enum VideoDeviceType {
170         Decoder,
171         Encoder,
172     }
173 
174     #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize)]
175     #[serde(rename_all = "kebab-case")]
176     pub enum VideoBackendType {
177         #[cfg(feature = "libvda")]
178         Libvda,
179         #[cfg(feature = "libvda")]
180         LibvdaVd,
181         #[cfg(feature = "ffmpeg")]
182         Ffmpeg,
183         #[cfg(feature = "vaapi")]
184         Vaapi,
185     }
186 
187     #[derive(Debug, Serialize, Deserialize, FromKeyValues)]
188     pub struct VideoDeviceConfig {
189         pub backend: VideoBackendType,
190     }
191 
192     /// The same set of virtio features is supported by the ffmpeg decoder and encoder.
ffmpeg_supported_virtio_features() -> u64193     pub fn ffmpeg_supported_virtio_features() -> u64 {
194         1u64 << VIRTIO_VIDEO_F_RESOURCE_GUEST_PAGES
195             | 1u64 << VIRTIO_VIDEO_F_RESOURCE_NON_CONTIG
196             | 1u64 << VIRTIO_VIDEO_F_RESOURCE_VIRTIO_OBJECT
197     }
198 
199     /// The same set of virtio features is supported by the vaapi decoder and encoder.
vaapi_supported_virtio_features() -> u64200     pub fn vaapi_supported_virtio_features() -> u64 {
201         1u64 << VIRTIO_VIDEO_F_RESOURCE_GUEST_PAGES
202             | 1u64 << VIRTIO_VIDEO_F_RESOURCE_NON_CONTIG
203             | 1u64 << VIRTIO_VIDEO_F_RESOURCE_VIRTIO_OBJECT
204     }
205 
206     /// The same set of virtio features is supported by the vda decoder and encoder.
vda_supported_virtio_features() -> u64207     pub fn vda_supported_virtio_features() -> u64 {
208         1u64 << VIRTIO_VIDEO_F_RESOURCE_NON_CONTIG | 1u64 << VIRTIO_VIDEO_F_RESOURCE_VIRTIO_OBJECT
209     }
210 
211     /// Union of the supported features of all decoder and encoder backends.
all_backend_virtio_features() -> u64212     pub fn all_backend_virtio_features() -> u64 {
213         ffmpeg_supported_virtio_features()
214             | vaapi_supported_virtio_features()
215             | vda_supported_virtio_features()
216     }
217 
backend_supported_virtio_features(backend: VideoBackendType) -> u64218     pub fn backend_supported_virtio_features(backend: VideoBackendType) -> u64 {
219         match backend {
220             #[cfg(feature = "libvda")]
221             VideoBackendType::Libvda | VideoBackendType::LibvdaVd => {
222                 vda_supported_virtio_features()
223             }
224             #[cfg(feature = "ffmpeg")]
225             VideoBackendType::Ffmpeg => ffmpeg_supported_virtio_features(),
226             #[cfg(feature = "vaapi")]
227             VideoBackendType::Vaapi => vaapi_supported_virtio_features(),
228         }
229     }
230 
231     #[repr(C)]
232     #[derive(Debug, Default, Copy, Clone, FromBytes, AsBytes)]
233     pub struct virtio_video_config {
234         pub version: Le32,
235         pub max_caps_length: Le32,
236         pub max_resp_length: Le32,
237         pub device_name: [u8; 32],
238     }
239 }
240 
241 pub mod vsock {
242     pub const QUEUE_SIZE: u16 = 256;
243     pub const NUM_QUEUES: usize = 3;
244     pub const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE; NUM_QUEUES];
245 }
246 
247 pub mod wl {
248     pub const QUEUE_SIZE: u16 = 256;
249     pub const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE, QUEUE_SIZE];
250 
251     pub const VIRTIO_WL_F_TRANS_FLAGS: u32 = 0x01;
252     pub const VIRTIO_WL_F_SEND_FENCES: u32 = 0x02;
253     pub const VIRTIO_WL_F_USE_SHMEM: u32 = 0x03;
254 }
255