1 // Copyright 2017 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //! Implements virtio devices, queues, and transport mechanisms.
6
7 mod balloon;
8 mod block;
9 mod block_async;
10 mod console;
11 mod descriptor_utils;
12 mod input;
13 mod interrupt;
14 mod net;
15 mod p9;
16 mod pmem;
17 mod queue;
18 mod rng;
19 #[cfg(feature = "tpm")]
20 mod tpm;
21 #[cfg(any(feature = "video-decoder", feature = "video-encoder"))]
22 mod video;
23 mod virtio_device;
24 mod virtio_pci_common_config;
25 mod virtio_pci_device;
26 mod wl;
27
28 pub mod fs;
29 #[cfg(feature = "gpu")]
30 pub mod gpu;
31 pub mod resource_bridge;
32 #[cfg(feature = "audio")]
33 pub mod snd;
34 pub mod vhost;
35
36 pub use self::balloon::*;
37 pub use self::block::*;
38 pub use self::block_async::*;
39 pub use self::console::*;
40 pub use self::descriptor_utils::Error as DescriptorError;
41 pub use self::descriptor_utils::*;
42 #[cfg(feature = "gpu")]
43 pub use self::gpu::*;
44 pub use self::input::*;
45 pub use self::interrupt::*;
46 pub use self::net::*;
47 pub use self::p9::*;
48 pub use self::pmem::*;
49 pub use self::queue::*;
50 pub use self::rng::*;
51 #[cfg(feature = "tpm")]
52 pub use self::tpm::*;
53 #[cfg(any(feature = "video-decoder", feature = "video-encoder"))]
54 pub use self::video::*;
55 pub use self::virtio_device::*;
56 pub use self::virtio_pci_device::*;
57 pub use self::wl::*;
58
59 use crate::ProtectionType;
60 use std::cmp;
61 use std::convert::TryFrom;
62
63 const DEVICE_RESET: u32 = 0x0;
64 const DEVICE_ACKNOWLEDGE: u32 = 0x01;
65 const DEVICE_DRIVER: u32 = 0x02;
66 const DEVICE_DRIVER_OK: u32 = 0x04;
67 const DEVICE_FEATURES_OK: u32 = 0x08;
68 const DEVICE_FAILED: u32 = 0x80;
69
70 // Types taken from linux/virtio_ids.h
71 const TYPE_NET: u32 = 1;
72 const TYPE_BLOCK: u32 = 2;
73 const TYPE_CONSOLE: u32 = 3;
74 const TYPE_RNG: u32 = 4;
75 const TYPE_BALLOON: u32 = 5;
76 const TYPE_RPMSG: u32 = 7;
77 const TYPE_SCSI: u32 = 8;
78 const TYPE_9P: u32 = 9;
79 const TYPE_RPROC_SERIAL: u32 = 11;
80 const TYPE_CAIF: u32 = 12;
81 const TYPE_GPU: u32 = 16;
82 const TYPE_INPUT: u32 = 18;
83 const TYPE_VSOCK: u32 = 19;
84 const TYPE_CRYPTO: u32 = 20;
85 const TYPE_IOMMU: u32 = 23;
86 const TYPE_FS: u32 = 26;
87 const TYPE_PMEM: u32 = 27;
88 const TYPE_VIDEO_ENC: u32 = 30;
89 const TYPE_VIDEO_DEC: u32 = 31;
90 // Additional types invented by crosvm
91 const MAX_VIRTIO_DEVICE_ID: u32 = 63;
92 const TYPE_WL: u32 = MAX_VIRTIO_DEVICE_ID;
93 const TYPE_TPM: u32 = MAX_VIRTIO_DEVICE_ID - 1;
94
95 pub const VIRTIO_F_VERSION_1: u32 = 32;
96 const VIRTIO_F_ACCESS_PLATFORM: u32 = 33;
97
98 const INTERRUPT_STATUS_USED_RING: u32 = 0x1;
99 const INTERRUPT_STATUS_CONFIG_CHANGED: u32 = 0x2;
100
101 const VIRTIO_MSI_NO_VECTOR: u16 = 0xffff;
102
103 /// Offset from the base MMIO address of a virtio device used by the guest to notify the device of
104 /// queue events.
105 pub const NOTIFY_REG_OFFSET: u32 = 0x50;
106
107 /// Returns a string representation of the given virtio device type number.
type_to_str(type_: u32) -> Option<&'static str>108 pub fn type_to_str(type_: u32) -> Option<&'static str> {
109 Some(match type_ {
110 TYPE_NET => "net",
111 TYPE_BLOCK => "block",
112 TYPE_CONSOLE => "console",
113 TYPE_RNG => "rng",
114 TYPE_BALLOON => "balloon",
115 TYPE_RPMSG => "rpmsg",
116 TYPE_SCSI => "scsi",
117 TYPE_9P => "9p",
118 TYPE_RPROC_SERIAL => "rproc-serial",
119 TYPE_CAIF => "caif",
120 TYPE_INPUT => "input",
121 TYPE_GPU => "gpu",
122 TYPE_VSOCK => "vsock",
123 TYPE_CRYPTO => "crypto",
124 TYPE_IOMMU => "iommu",
125 TYPE_FS => "fs",
126 TYPE_PMEM => "pmem",
127 TYPE_WL => "wl",
128 TYPE_TPM => "tpm",
129 TYPE_VIDEO_DEC => "video-decoder",
130 TYPE_VIDEO_ENC => "video-encoder",
131 _ => return None,
132 })
133 }
134
135 /// Copy virtio device configuration data from a subslice of `src` to a subslice of `dst`.
136 /// Unlike std::slice::copy_from_slice(), this function copies as much as possible within
137 /// the common subset of the two slices, truncating the requested range instead of
138 /// panicking if the slices do not match in size.
139 ///
140 /// `dst_offset` and `src_offset` specify the starting indexes of the `dst` and `src`
141 /// slices, respectively; if either index is out of bounds, this function is a no-op
142 /// rather than panicking. This makes it safe to call with arbitrary user-controlled
143 /// inputs.
copy_config(dst: &mut [u8], dst_offset: u64, src: &[u8], src_offset: u64)144 pub fn copy_config(dst: &mut [u8], dst_offset: u64, src: &[u8], src_offset: u64) {
145 if let Ok(dst_offset) = usize::try_from(dst_offset) {
146 if let Ok(src_offset) = usize::try_from(src_offset) {
147 if let Some(dst_slice) = dst.get_mut(dst_offset..) {
148 if let Some(src_slice) = src.get(src_offset..) {
149 let len = cmp::min(dst_slice.len(), src_slice.len());
150 let dst_subslice = &mut dst_slice[0..len];
151 let src_subslice = &src_slice[0..len];
152 dst_subslice.copy_from_slice(src_subslice);
153 }
154 }
155 }
156 }
157 }
158
159 /// Returns the set of reserved base features common to all virtio devices.
base_features(protected_vm: ProtectionType) -> u64160 pub fn base_features(protected_vm: ProtectionType) -> u64 {
161 let mut features: u64 = 1 << VIRTIO_F_VERSION_1;
162
163 if protected_vm == ProtectionType::Protected {
164 features |= 1 << VIRTIO_F_ACCESS_PLATFORM;
165 }
166
167 features
168 }
169