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