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