// Copyright 2019 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //! The root level module that includes the config and aggregate of the submodules for running said //! configs. pub mod argument; #[cfg(all(target_arch = "x86_64", feature = "gdb"))] pub mod gdb; #[path = "linux.rs"] pub mod platform; #[cfg(feature = "plugin")] pub mod plugin; use std::collections::BTreeMap; use std::net; use std::os::unix::io::RawFd; use std::path::{Path, PathBuf}; use std::str::FromStr; use arch::{Pstore, SerialHardware, SerialParameters, VcpuAffinity}; use devices::virtio::fs::passthrough; #[cfg(feature = "gpu")] use devices::virtio::gpu::GpuParameters; #[cfg(feature = "audio")] use devices::Ac97Parameters; use devices::ProtectionType; use libc::{getegid, geteuid}; use vm_control::BatteryType; static KVM_PATH: &str = "/dev/kvm"; static VHOST_VSOCK_PATH: &str = "/dev/vhost-vsock"; static VHOST_NET_PATH: &str = "/dev/vhost-net"; static SECCOMP_POLICY_DIR: &str = "/usr/share/policy/crosvm"; /// Indicates the location and kind of executable kernel for a VM. #[derive(Debug)] pub enum Executable { /// An executable intended to be run as a BIOS directly. Bios(PathBuf), /// A elf linux kernel, loaded and executed by crosvm. Kernel(PathBuf), /// Path to a plugin executable that is forked by crosvm. Plugin(PathBuf), } /// Maximum length of a `DiskOption` identifier. /// /// This is based on the virtio-block ID length limit. pub const DISK_ID_LEN: usize = 20; pub struct DiskOption { pub path: PathBuf, pub read_only: bool, pub sparse: bool, pub block_size: u32, pub id: Option<[u8; DISK_ID_LEN]>, } pub struct VhostUserOption { pub socket: PathBuf, } pub struct VhostUserFsOption { pub socket: PathBuf, pub tag: String, } /// A bind mount for directories in the plugin process. pub struct BindMount { pub src: PathBuf, pub dst: PathBuf, pub writable: bool, } /// A mapping of linux group IDs for the plugin process. pub struct GidMap { pub inner: libc::gid_t, pub outer: libc::gid_t, pub count: u32, } /// Direct IO forwarding options #[cfg(feature = "direct")] pub struct DirectIoOption { pub path: PathBuf, pub ranges: Vec<(u64, u64)>, } pub const DEFAULT_TOUCH_DEVICE_HEIGHT: u32 = 1024; pub const DEFAULT_TOUCH_DEVICE_WIDTH: u32 = 1280; pub struct TouchDeviceOption { path: PathBuf, width: Option, height: Option, default_width: u32, default_height: u32, } impl TouchDeviceOption { pub fn new(path: PathBuf) -> TouchDeviceOption { TouchDeviceOption { path, width: None, height: None, default_width: DEFAULT_TOUCH_DEVICE_WIDTH, default_height: DEFAULT_TOUCH_DEVICE_HEIGHT, } } /// Getter for the path to the input event streams. pub fn get_path(&self) -> &Path { self.path.as_path() } /// When a user specifies the parameters for a touch device, width and height are optional. /// If the width and height are missing, default values are used. Default values can be set /// dynamically, for example from the display sizes specified by the gpu argument. pub fn set_default_size(&mut self, width: u32, height: u32) { self.default_width = width; self.default_height = height; } /// Setter for the width specified by the user. pub fn set_width(&mut self, width: u32) { self.width.replace(width); } /// Setter for the height specified by the user. pub fn set_height(&mut self, height: u32) { self.height.replace(height); } /// If the user specifies the size, use it. Otherwise, use the default values. pub fn get_size(&self) -> (u32, u32) { ( self.width.unwrap_or(self.default_width), self.height.unwrap_or(self.default_height), ) } } #[derive(Eq, PartialEq)] pub enum SharedDirKind { FS, P9, } impl FromStr for SharedDirKind { type Err = &'static str; fn from_str(s: &str) -> Result { use SharedDirKind::*; match s { "fs" | "FS" => Ok(FS), "9p" | "9P" | "p9" | "P9" => Ok(P9), _ => Err("invalid file system type"), } } } impl Default for SharedDirKind { fn default() -> SharedDirKind { SharedDirKind::P9 } } pub struct SharedDir { pub src: PathBuf, pub tag: String, pub kind: SharedDirKind, pub uid_map: String, pub gid_map: String, pub fs_cfg: passthrough::Config, pub p9_cfg: p9::Config, } impl Default for SharedDir { fn default() -> SharedDir { SharedDir { src: Default::default(), tag: Default::default(), kind: Default::default(), uid_map: format!("0 {} 1", unsafe { geteuid() }), gid_map: format!("0 {} 1", unsafe { getegid() }), fs_cfg: Default::default(), p9_cfg: Default::default(), } } } /// Aggregate of all configurable options for a running VM. pub struct Config { pub kvm_device_path: PathBuf, pub vhost_vsock_device_path: PathBuf, pub vhost_net_device_path: PathBuf, pub vcpu_count: Option, pub rt_cpus: Vec, pub vcpu_affinity: Option, pub no_smt: bool, pub memory: Option, pub hugepages: bool, pub memory_file: Option, pub executable_path: Option, pub android_fstab: Option, pub initrd_path: Option, pub params: Vec, pub socket_path: Option, pub plugin_root: Option, pub plugin_mounts: Vec, pub plugin_gid_maps: Vec, pub disks: Vec, pub pmem_devices: Vec, pub pstore: Option, pub host_ip: Option, pub netmask: Option, pub mac_address: Option, pub net_vq_pairs: Option, pub vhost_net: bool, pub tap_fd: Vec, pub cid: Option, pub wayland_socket_paths: BTreeMap, pub wayland_dmabuf: bool, pub x_display: Option, pub shared_dirs: Vec, pub sandbox: bool, pub seccomp_policy_dir: PathBuf, pub seccomp_log_failures: bool, #[cfg(feature = "gpu")] pub gpu_parameters: Option, pub software_tpm: bool, pub display_window_keyboard: bool, pub display_window_mouse: bool, #[cfg(feature = "audio")] pub ac97_parameters: Vec, pub serial_parameters: BTreeMap<(SerialHardware, u8), SerialParameters>, pub syslog_tag: Option, pub virtio_single_touch: Option, pub virtio_multi_touch: Option, pub virtio_trackpad: Option, pub virtio_mouse: Option, pub virtio_keyboard: Option, pub virtio_switches: Option, pub virtio_input_evdevs: Vec, pub split_irqchip: bool, pub vfio: Vec, pub video_dec: bool, pub video_enc: bool, pub acpi_tables: Vec, pub protected_vm: ProtectionType, pub battery_type: Option, #[cfg(all(target_arch = "x86_64", feature = "gdb"))] pub gdb: Option, pub balloon_bias: i64, pub vhost_user_blk: Vec, pub vhost_user_fs: Vec, pub vhost_user_net: Vec, #[cfg(feature = "direct")] pub direct_pmio: Option, #[cfg(feature = "direct")] pub direct_level_irq: Vec, #[cfg(feature = "direct")] pub direct_edge_irq: Vec, pub dmi_path: Option, } impl Default for Config { fn default() -> Config { Config { kvm_device_path: PathBuf::from(KVM_PATH), vhost_vsock_device_path: PathBuf::from(VHOST_VSOCK_PATH), vhost_net_device_path: PathBuf::from(VHOST_NET_PATH), vcpu_count: None, rt_cpus: Vec::new(), vcpu_affinity: None, no_smt: false, memory: None, hugepages: false, memory_file: None, executable_path: None, android_fstab: None, initrd_path: None, params: Vec::new(), socket_path: None, plugin_root: None, plugin_mounts: Vec::new(), plugin_gid_maps: Vec::new(), disks: Vec::new(), pmem_devices: Vec::new(), pstore: None, host_ip: None, netmask: None, mac_address: None, net_vq_pairs: None, vhost_net: false, tap_fd: Vec::new(), cid: None, #[cfg(feature = "gpu")] gpu_parameters: None, software_tpm: false, wayland_socket_paths: BTreeMap::new(), wayland_dmabuf: false, x_display: None, display_window_keyboard: false, display_window_mouse: false, shared_dirs: Vec::new(), sandbox: !cfg!(feature = "default-no-sandbox"), seccomp_policy_dir: PathBuf::from(SECCOMP_POLICY_DIR), seccomp_log_failures: false, #[cfg(feature = "audio")] ac97_parameters: Vec::new(), serial_parameters: BTreeMap::new(), syslog_tag: None, virtio_single_touch: None, virtio_multi_touch: None, virtio_trackpad: None, virtio_mouse: None, virtio_keyboard: None, virtio_switches: None, virtio_input_evdevs: Vec::new(), split_irqchip: false, vfio: Vec::new(), video_dec: false, video_enc: false, acpi_tables: Vec::new(), protected_vm: ProtectionType::Unprotected, battery_type: None, #[cfg(all(target_arch = "x86_64", feature = "gdb"))] gdb: None, balloon_bias: 0, vhost_user_blk: Vec::new(), vhost_user_fs: Vec::new(), vhost_user_net: Vec::new(), #[cfg(feature = "direct")] direct_pmio: None, #[cfg(feature = "direct")] direct_level_irq: Vec::new(), #[cfg(feature = "direct")] direct_edge_irq: Vec::new(), dmi_path: None, } } }