1 // Copyright 2019 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 //! The root level module that includes the config and aggregate of the submodules for running said 6 //! configs. 7 8 pub mod argument; 9 #[cfg(all(target_arch = "x86_64", feature = "gdb"))] 10 pub mod gdb; 11 #[path = "linux.rs"] 12 pub mod platform; 13 #[cfg(feature = "plugin")] 14 pub mod plugin; 15 16 use std::collections::BTreeMap; 17 use std::net; 18 use std::os::unix::io::RawFd; 19 use std::path::{Path, PathBuf}; 20 use std::str::FromStr; 21 22 use arch::{Pstore, SerialHardware, SerialParameters, VcpuAffinity}; 23 use devices::virtio::fs::passthrough; 24 #[cfg(feature = "gpu")] 25 use devices::virtio::gpu::GpuParameters; 26 #[cfg(feature = "audio")] 27 use devices::Ac97Parameters; 28 use devices::ProtectionType; 29 use libc::{getegid, geteuid}; 30 use vm_control::BatteryType; 31 32 static KVM_PATH: &str = "/dev/kvm"; 33 static VHOST_VSOCK_PATH: &str = "/dev/vhost-vsock"; 34 static VHOST_NET_PATH: &str = "/dev/vhost-net"; 35 static SECCOMP_POLICY_DIR: &str = "/usr/share/policy/crosvm"; 36 37 /// Indicates the location and kind of executable kernel for a VM. 38 #[derive(Debug)] 39 pub enum Executable { 40 /// An executable intended to be run as a BIOS directly. 41 Bios(PathBuf), 42 /// A elf linux kernel, loaded and executed by crosvm. 43 Kernel(PathBuf), 44 /// Path to a plugin executable that is forked by crosvm. 45 Plugin(PathBuf), 46 } 47 48 /// Maximum length of a `DiskOption` identifier. 49 /// 50 /// This is based on the virtio-block ID length limit. 51 pub const DISK_ID_LEN: usize = 20; 52 53 pub struct DiskOption { 54 pub path: PathBuf, 55 pub read_only: bool, 56 pub sparse: bool, 57 pub block_size: u32, 58 pub id: Option<[u8; DISK_ID_LEN]>, 59 } 60 61 pub struct VhostUserOption { 62 pub socket: PathBuf, 63 } 64 65 pub struct VhostUserFsOption { 66 pub socket: PathBuf, 67 pub tag: String, 68 } 69 70 /// A bind mount for directories in the plugin process. 71 pub struct BindMount { 72 pub src: PathBuf, 73 pub dst: PathBuf, 74 pub writable: bool, 75 } 76 77 /// A mapping of linux group IDs for the plugin process. 78 pub struct GidMap { 79 pub inner: libc::gid_t, 80 pub outer: libc::gid_t, 81 pub count: u32, 82 } 83 84 /// Direct IO forwarding options 85 #[cfg(feature = "direct")] 86 pub struct DirectIoOption { 87 pub path: PathBuf, 88 pub ranges: Vec<(u64, u64)>, 89 } 90 91 pub const DEFAULT_TOUCH_DEVICE_HEIGHT: u32 = 1024; 92 pub const DEFAULT_TOUCH_DEVICE_WIDTH: u32 = 1280; 93 94 pub struct TouchDeviceOption { 95 path: PathBuf, 96 width: Option<u32>, 97 height: Option<u32>, 98 default_width: u32, 99 default_height: u32, 100 } 101 102 impl TouchDeviceOption { new(path: PathBuf) -> TouchDeviceOption103 pub fn new(path: PathBuf) -> TouchDeviceOption { 104 TouchDeviceOption { 105 path, 106 width: None, 107 height: None, 108 default_width: DEFAULT_TOUCH_DEVICE_WIDTH, 109 default_height: DEFAULT_TOUCH_DEVICE_HEIGHT, 110 } 111 } 112 113 /// Getter for the path to the input event streams. get_path(&self) -> &Path114 pub fn get_path(&self) -> &Path { 115 self.path.as_path() 116 } 117 118 /// When a user specifies the parameters for a touch device, width and height are optional. 119 /// If the width and height are missing, default values are used. Default values can be set 120 /// dynamically, for example from the display sizes specified by the gpu argument. set_default_size(&mut self, width: u32, height: u32)121 pub fn set_default_size(&mut self, width: u32, height: u32) { 122 self.default_width = width; 123 self.default_height = height; 124 } 125 126 /// Setter for the width specified by the user. set_width(&mut self, width: u32)127 pub fn set_width(&mut self, width: u32) { 128 self.width.replace(width); 129 } 130 131 /// Setter for the height specified by the user. set_height(&mut self, height: u32)132 pub fn set_height(&mut self, height: u32) { 133 self.height.replace(height); 134 } 135 136 /// If the user specifies the size, use it. Otherwise, use the default values. get_size(&self) -> (u32, u32)137 pub fn get_size(&self) -> (u32, u32) { 138 ( 139 self.width.unwrap_or(self.default_width), 140 self.height.unwrap_or(self.default_height), 141 ) 142 } 143 } 144 145 #[derive(Eq, PartialEq)] 146 pub enum SharedDirKind { 147 FS, 148 P9, 149 } 150 151 impl FromStr for SharedDirKind { 152 type Err = &'static str; 153 from_str(s: &str) -> Result<Self, Self::Err>154 fn from_str(s: &str) -> Result<Self, Self::Err> { 155 use SharedDirKind::*; 156 match s { 157 "fs" | "FS" => Ok(FS), 158 "9p" | "9P" | "p9" | "P9" => Ok(P9), 159 _ => Err("invalid file system type"), 160 } 161 } 162 } 163 164 impl Default for SharedDirKind { default() -> SharedDirKind165 fn default() -> SharedDirKind { 166 SharedDirKind::P9 167 } 168 } 169 170 pub struct SharedDir { 171 pub src: PathBuf, 172 pub tag: String, 173 pub kind: SharedDirKind, 174 pub uid_map: String, 175 pub gid_map: String, 176 pub fs_cfg: passthrough::Config, 177 pub p9_cfg: p9::Config, 178 } 179 180 impl Default for SharedDir { default() -> SharedDir181 fn default() -> SharedDir { 182 SharedDir { 183 src: Default::default(), 184 tag: Default::default(), 185 kind: Default::default(), 186 uid_map: format!("0 {} 1", unsafe { geteuid() }), 187 gid_map: format!("0 {} 1", unsafe { getegid() }), 188 fs_cfg: Default::default(), 189 p9_cfg: Default::default(), 190 } 191 } 192 } 193 194 /// Aggregate of all configurable options for a running VM. 195 pub struct Config { 196 pub kvm_device_path: PathBuf, 197 pub vhost_vsock_device_path: PathBuf, 198 pub vhost_net_device_path: PathBuf, 199 pub vcpu_count: Option<usize>, 200 pub rt_cpus: Vec<usize>, 201 pub vcpu_affinity: Option<VcpuAffinity>, 202 pub no_smt: bool, 203 pub memory: Option<u64>, 204 pub hugepages: bool, 205 pub memory_file: Option<PathBuf>, 206 pub executable_path: Option<Executable>, 207 pub android_fstab: Option<PathBuf>, 208 pub initrd_path: Option<PathBuf>, 209 pub params: Vec<String>, 210 pub socket_path: Option<PathBuf>, 211 pub plugin_root: Option<PathBuf>, 212 pub plugin_mounts: Vec<BindMount>, 213 pub plugin_gid_maps: Vec<GidMap>, 214 pub disks: Vec<DiskOption>, 215 pub pmem_devices: Vec<DiskOption>, 216 pub pstore: Option<Pstore>, 217 pub host_ip: Option<net::Ipv4Addr>, 218 pub netmask: Option<net::Ipv4Addr>, 219 pub mac_address: Option<net_util::MacAddress>, 220 pub net_vq_pairs: Option<u16>, 221 pub vhost_net: bool, 222 pub tap_fd: Vec<RawFd>, 223 pub cid: Option<u64>, 224 pub wayland_socket_paths: BTreeMap<String, PathBuf>, 225 pub wayland_dmabuf: bool, 226 pub x_display: Option<String>, 227 pub shared_dirs: Vec<SharedDir>, 228 pub sandbox: bool, 229 pub seccomp_policy_dir: PathBuf, 230 pub seccomp_log_failures: bool, 231 #[cfg(feature = "gpu")] 232 pub gpu_parameters: Option<GpuParameters>, 233 pub software_tpm: bool, 234 pub display_window_keyboard: bool, 235 pub display_window_mouse: bool, 236 #[cfg(feature = "audio")] 237 pub ac97_parameters: Vec<Ac97Parameters>, 238 pub serial_parameters: BTreeMap<(SerialHardware, u8), SerialParameters>, 239 pub syslog_tag: Option<String>, 240 pub virtio_single_touch: Option<TouchDeviceOption>, 241 pub virtio_multi_touch: Option<TouchDeviceOption>, 242 pub virtio_trackpad: Option<TouchDeviceOption>, 243 pub virtio_mouse: Option<PathBuf>, 244 pub virtio_keyboard: Option<PathBuf>, 245 pub virtio_switches: Option<PathBuf>, 246 pub virtio_input_evdevs: Vec<PathBuf>, 247 pub split_irqchip: bool, 248 pub vfio: Vec<PathBuf>, 249 pub video_dec: bool, 250 pub video_enc: bool, 251 pub acpi_tables: Vec<PathBuf>, 252 pub protected_vm: ProtectionType, 253 pub battery_type: Option<BatteryType>, 254 #[cfg(all(target_arch = "x86_64", feature = "gdb"))] 255 pub gdb: Option<u32>, 256 pub balloon_bias: i64, 257 pub vhost_user_blk: Vec<VhostUserOption>, 258 pub vhost_user_fs: Vec<VhostUserFsOption>, 259 pub vhost_user_net: Vec<VhostUserOption>, 260 #[cfg(feature = "direct")] 261 pub direct_pmio: Option<DirectIoOption>, 262 #[cfg(feature = "direct")] 263 pub direct_level_irq: Vec<u32>, 264 #[cfg(feature = "direct")] 265 pub direct_edge_irq: Vec<u32>, 266 pub dmi_path: Option<PathBuf>, 267 } 268 269 impl Default for Config { default() -> Config270 fn default() -> Config { 271 Config { 272 kvm_device_path: PathBuf::from(KVM_PATH), 273 vhost_vsock_device_path: PathBuf::from(VHOST_VSOCK_PATH), 274 vhost_net_device_path: PathBuf::from(VHOST_NET_PATH), 275 vcpu_count: None, 276 rt_cpus: Vec::new(), 277 vcpu_affinity: None, 278 no_smt: false, 279 memory: None, 280 hugepages: false, 281 memory_file: None, 282 executable_path: None, 283 android_fstab: None, 284 initrd_path: None, 285 params: Vec::new(), 286 socket_path: None, 287 plugin_root: None, 288 plugin_mounts: Vec::new(), 289 plugin_gid_maps: Vec::new(), 290 disks: Vec::new(), 291 pmem_devices: Vec::new(), 292 pstore: None, 293 host_ip: None, 294 netmask: None, 295 mac_address: None, 296 net_vq_pairs: None, 297 vhost_net: false, 298 tap_fd: Vec::new(), 299 cid: None, 300 #[cfg(feature = "gpu")] 301 gpu_parameters: None, 302 software_tpm: false, 303 wayland_socket_paths: BTreeMap::new(), 304 wayland_dmabuf: false, 305 x_display: None, 306 display_window_keyboard: false, 307 display_window_mouse: false, 308 shared_dirs: Vec::new(), 309 sandbox: !cfg!(feature = "default-no-sandbox"), 310 seccomp_policy_dir: PathBuf::from(SECCOMP_POLICY_DIR), 311 seccomp_log_failures: false, 312 #[cfg(feature = "audio")] 313 ac97_parameters: Vec::new(), 314 serial_parameters: BTreeMap::new(), 315 syslog_tag: None, 316 virtio_single_touch: None, 317 virtio_multi_touch: None, 318 virtio_trackpad: None, 319 virtio_mouse: None, 320 virtio_keyboard: None, 321 virtio_switches: None, 322 virtio_input_evdevs: Vec::new(), 323 split_irqchip: false, 324 vfio: Vec::new(), 325 video_dec: false, 326 video_enc: false, 327 acpi_tables: Vec::new(), 328 protected_vm: ProtectionType::Unprotected, 329 battery_type: None, 330 #[cfg(all(target_arch = "x86_64", feature = "gdb"))] 331 gdb: None, 332 balloon_bias: 0, 333 vhost_user_blk: Vec::new(), 334 vhost_user_fs: Vec::new(), 335 vhost_user_net: Vec::new(), 336 #[cfg(feature = "direct")] 337 direct_pmio: None, 338 #[cfg(feature = "direct")] 339 direct_level_irq: Vec::new(), 340 #[cfg(feature = "direct")] 341 direct_edge_irq: Vec::new(), 342 dmi_path: None, 343 } 344 } 345 } 346