diff --git a/aarch64/src/lib.rs b/aarch64/src/lib.rs index af386e09e4..cb8fecfe95 100644 --- a/aarch64/src/lib.rs +++ b/aarch64/src/lib.rs @@ -273,6 +273,7 @@ impl arch::LinuxArch for AArch64 { let com_evt_1_3 = Event::new().map_err(Error::CreateEvent)?; let com_evt_2_4 = Event::new().map_err(Error::CreateEvent)?; arch::add_serial_devices( + components.protected_vm, &mut mmio_bus, &com_evt_1_3, &com_evt_2_4, diff --git a/arch/src/lib.rs b/arch/src/lib.rs index a41f074634..6fa2d3cd68 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -83,6 +83,7 @@ pub struct VmComponents { pub wayland_dmabuf: bool, pub acpi_sdts: Vec, pub rt_cpus: Vec, + pub protected_vm: bool, } /// Holds the elements needed to run a Linux VM. Created by `build_vm`. diff --git a/arch/src/serial.rs b/arch/src/serial.rs index 735418047f..b59ac12612 100644 --- a/arch/src/serial.rs +++ b/arch/src/serial.rs @@ -224,6 +224,7 @@ impl SerialParameters { /// process. `evt` will always be added to this vector by this function. pub fn create_serial_device( &self, + protected_vm: bool, evt: &Event, keep_fds: &mut Vec, ) -> std::result::Result { @@ -287,7 +288,7 @@ impl SerialParameters { None => return Err(Error::PathRequired), }, }; - Ok(T::new(evt, input, output, keep_fds.to_vec())) + Ok(T::new(protected_vm, evt, input, output, keep_fds.to_vec())) } pub fn add_bind_mounts(&self, jail: &mut Minijail) -> Result<(), minijail::Error> { @@ -371,6 +372,7 @@ pub const SERIAL_ADDR: [u64; 4] = [0x3f8, 0x2f8, 0x3e8, 0x2e8]; /// * `serial_parameters` - definitions of serial parameter configurations. /// All four of the traditional PC-style serial ports (COM1-COM4) must be specified. pub fn add_serial_devices( + protected_vm: bool, io_bus: &mut Bus, com_evt_1_3: &Event, com_evt_2_4: &Event, @@ -392,7 +394,7 @@ pub fn add_serial_devices( let mut preserved_fds = Vec::new(); let com = param - .create_serial_device::(&com_evt, &mut preserved_fds) + .create_serial_device::(protected_vm, &com_evt, &mut preserved_fds) .map_err(DeviceRegistrationError::CreateSerialDevice)?; match serial_jail.as_ref() { diff --git a/devices/src/serial.rs b/devices/src/serial.rs index 30e4ad3be4..ca0dee9129 100644 --- a/devices/src/serial.rs +++ b/devices/src/serial.rs @@ -84,6 +84,7 @@ pub struct Serial { impl SerialDevice for Serial { fn new( + _protected_vm: bool, interrupt_evt: Event, input: Option>, out: Option>, @@ -409,6 +410,7 @@ mod tests { let serial_out = SharedBuffer::new(); let mut serial = Serial::new( + false, intr_evt, None, Some(Box::new(serial_out.clone())), @@ -430,6 +432,7 @@ mod tests { let serial_out = SharedBuffer::new(); let mut serial = Serial::new( + false, intr_evt.try_clone().unwrap(), None, Some(Box::new(serial_out.clone())), diff --git a/devices/src/serial_device.rs b/devices/src/serial_device.rs index 67e2107d80..effa5fef4e 100644 --- a/devices/src/serial_device.rs +++ b/devices/src/serial_device.rs @@ -11,6 +11,7 @@ use base::Event; /// output streams. pub trait SerialDevice { fn new( + protected_vm: bool, interrupt_evt: Event, input: Option>, output: Option>, diff --git a/devices/src/virtio/block.rs b/devices/src/virtio/block.rs index 1ec05b89d4..85f960b018 100644 --- a/devices/src/virtio/block.rs +++ b/devices/src/virtio/block.rs @@ -848,7 +848,7 @@ mod tests { let f = tempfile().unwrap(); f.set_len(0x1000).unwrap(); - let features = base_features(); + let features = base_features(false); let b = Block::new(features, Box::new(f), true, false, 512, None).unwrap(); let mut num_sectors = [0u8; 4]; b.read_config(0, &mut num_sectors); @@ -865,7 +865,7 @@ mod tests { let f = tempfile().unwrap(); f.set_len(0x1000).unwrap(); - let features = base_features(); + let features = base_features(false); let b = Block::new(features, Box::new(f), true, false, 4096, None).unwrap(); let mut blk_size = [0u8; 4]; b.read_config(20, &mut blk_size); @@ -878,7 +878,7 @@ mod tests { // read-write block device { let f = tempfile().unwrap(); - let features = base_features(); + let features = base_features(false); let b = Block::new(features, Box::new(f), false, true, 512, None).unwrap(); // writable device should set VIRTIO_BLK_F_FLUSH + VIRTIO_BLK_F_DISCARD // + VIRTIO_BLK_F_WRITE_ZEROES + VIRTIO_F_VERSION_1 + VIRTIO_BLK_F_BLK_SIZE @@ -889,7 +889,7 @@ mod tests { // read-write block device, non-sparse { let f = tempfile().unwrap(); - let features = base_features(); + let features = base_features(false); let b = Block::new(features, Box::new(f), false, false, 512, None).unwrap(); // writable device should set VIRTIO_BLK_F_FLUSH // + VIRTIO_BLK_F_WRITE_ZEROES + VIRTIO_F_VERSION_1 + VIRTIO_BLK_F_BLK_SIZE @@ -900,7 +900,7 @@ mod tests { // read-only block device { let f = tempfile().unwrap(); - let features = base_features(); + let features = base_features(false); let b = Block::new(features, Box::new(f), true, true, 512, None).unwrap(); // read-only device should set VIRTIO_BLK_F_FLUSH and VIRTIO_BLK_F_RO // + VIRTIO_F_VERSION_1 + VIRTIO_BLK_F_BLK_SIZE + VIRTIO_BLK_F_SEG_MAX diff --git a/devices/src/virtio/console.rs b/devices/src/virtio/console.rs index 8662f9d7ed..bd6da3d37e 100644 --- a/devices/src/virtio/console.rs +++ b/devices/src/virtio/console.rs @@ -309,13 +309,14 @@ pub struct Console { impl SerialDevice for Console { fn new( + protected_vm: bool, _evt: Event, input: Option>, output: Option>, keep_fds: Vec, ) -> Console { Console { - base_features: base_features(), + base_features: base_features(protected_vm), kill_evt: None, worker_thread: None, input, diff --git a/devices/src/virtio/mod.rs b/devices/src/virtio/mod.rs index 706b3340ed..441308a709 100644 --- a/devices/src/virtio/mod.rs +++ b/devices/src/virtio/mod.rs @@ -88,6 +88,7 @@ const TYPE_WL: u32 = MAX_VIRTIO_DEVICE_ID; const TYPE_TPM: u32 = MAX_VIRTIO_DEVICE_ID - 1; const VIRTIO_F_VERSION_1: u32 = 32; +const VIRTIO_F_ACCESS_PLATFORM: u32 = 33; const INTERRUPT_STATUS_USED_RING: u32 = 0x1; const INTERRUPT_STATUS_CONFIG_CHANGED: u32 = 0x2; @@ -151,6 +152,12 @@ pub fn copy_config(dst: &mut [u8], dst_offset: u64, src: &[u8], src_offset: u64) } /// Returns the set of reserved base features common to all virtio devices. -pub fn base_features() -> u64 { - 1 << VIRTIO_F_VERSION_1 +pub fn base_features(protected_vm: bool) -> u64 { + let mut features: u64 = 1 << VIRTIO_F_VERSION_1; + + if protected_vm { + features |= 1 << VIRTIO_F_ACCESS_PLATFORM; + } + + features } diff --git a/devices/src/virtio/vhost/net.rs b/devices/src/virtio/vhost/net.rs index 8a639dd5ff..14dc85201c 100644 --- a/devices/src/virtio/vhost/net.rs +++ b/devices/src/virtio/vhost/net.rs @@ -364,7 +364,7 @@ pub mod tests { fn create_net_common() -> Net> { let guest_memory = create_guest_memory().unwrap(); - let features = base_features(); + let features = base_features(false); Net::>::new( features, Ipv4Addr::new(127, 0, 0, 1), diff --git a/src/crosvm.rs b/src/crosvm.rs index 65d8b7ebe9..832257ae7e 100644 --- a/src/crosvm.rs +++ b/src/crosvm.rs @@ -209,6 +209,7 @@ pub struct Config { pub video_dec: bool, pub video_enc: bool, pub acpi_tables: Vec, + pub protected_vm: bool, } impl Default for Config { @@ -263,6 +264,7 @@ impl Default for Config { video_dec: false, video_enc: false, acpi_tables: Vec::new(), + protected_vm: false, } } } diff --git a/src/linux.rs b/src/linux.rs index bf0bd2d2fc..f3b57c041a 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -460,7 +460,7 @@ fn create_block_device( let disk_file = disk::create_disk_file(raw_image).map_err(Error::CreateDiskError)?; let dev = virtio::Block::new( - virtio::base_features(), + virtio::base_features(cfg.protected_vm), disk_file, disk.read_only, disk.sparse, @@ -609,8 +609,8 @@ fn create_vinput_device(cfg: &Config, dev_path: &Path) -> DeviceResult { } fn create_balloon_device(cfg: &Config, socket: BalloonControlResponseSocket) -> DeviceResult { - let dev = - virtio::Balloon::new(virtio::base_features(), socket).map_err(Error::BalloonDeviceNew)?; + let dev = virtio::Balloon::new(virtio::base_features(cfg.protected_vm), socket) + .map_err(Error::BalloonDeviceNew)?; Ok(VirtioDeviceStub { dev: Box::new(dev), @@ -631,7 +631,7 @@ fn create_tap_net_device(cfg: &Config, tap_fd: RawFd) -> DeviceResult { error!("net vq pairs must be smaller than vcpu count, fall back to single queue mode"); vq_pairs = 1; } - let features = virtio::base_features(); + let features = virtio::base_features(cfg.protected_vm); let dev = virtio::Net::from(features, tap, vq_pairs).map_err(Error::NetDeviceNew)?; Ok(VirtioDeviceStub { @@ -654,7 +654,7 @@ fn create_net_device( vq_pairs = 1; } - let features = virtio::base_features(); + let features = virtio::base_features(cfg.protected_vm); let dev = if cfg.vhost_net { let dev = virtio::vhost::Net::>::new( features, @@ -722,7 +722,7 @@ fn create_gpu_device( event_devices, map_request, cfg.sandbox, - virtio::base_features(), + virtio::base_features(cfg.protected_vm), ); let jail = match simple_jail(&cfg, "gpu_device")? { @@ -832,7 +832,7 @@ fn create_wayland_device( .collect::>>() .ok_or(Error::InvalidWaylandPath)?; - let features = virtio::base_features(); + let features = virtio::base_features(cfg.protected_vm); let dev = virtio::Wl::new( features, cfg.wayland_socket_paths.clone(), @@ -929,7 +929,7 @@ fn create_video_device( Ok(VirtioDeviceStub { dev: Box::new(devices::virtio::VideoDevice::new( - virtio::base_features(), + virtio::base_features(cfg.protected_vm), typ, Some(resource_bridge), )), @@ -952,7 +952,7 @@ fn register_video_device( } fn create_vhost_vsock_device(cfg: &Config, cid: u64, mem: &GuestMemory) -> DeviceResult { - let features = virtio::base_features(); + let features = virtio::base_features(cfg.protected_vm); let dev = virtio::vhost::Vsock::new(features, cid, mem).map_err(Error::VhostVsockDeviceNew)?; Ok(VirtioDeviceStub { @@ -989,7 +989,7 @@ fn create_fs_device( create_base_minijail(src, Some(max_open_files), None)? }; - let features = virtio::base_features(); + let features = virtio::base_features(cfg.protected_vm); // TODO(chirantan): Use more than one worker once the kernel driver has been fixed to not panic // when num_queues > 1. let dev = virtio::fs::Fs::new(features, tag, 1, fs_cfg).map_err(Error::FsDeviceNew)?; @@ -1032,7 +1032,7 @@ fn create_9p_device( (None, src) }; - let features = virtio::base_features(); + let features = virtio::base_features(cfg.protected_vm); let dev = virtio::P9::new(features, root, tag).map_err(Error::P9DeviceNew)?; Ok(VirtioDeviceStub { @@ -1115,7 +1115,7 @@ fn create_pmem_device( .map_err(Error::AddPmemDeviceMemory)?; let dev = virtio::Pmem::new( - virtio::base_features(), + virtio::base_features(cfg.protected_vm), fd, GuestAddress(mapping_address), slot, @@ -1134,7 +1134,7 @@ fn create_console_device(cfg: &Config, param: &SerialParameters) -> DeviceResult let mut keep_fds = Vec::new(); let evt = Event::new().map_err(Error::CreateEvent)?; let dev = param - .create_serial_device::(&evt, &mut keep_fds) + .create_serial_device::(cfg.protected_vm, &evt, &mut keep_fds) .map_err(Error::CreateConsole)?; let jail = match simple_jail(&cfg, "serial")? { @@ -1981,6 +1981,7 @@ where .map(|path| SDT::from_file(path).map_err(|e| Error::OpenAcpiTable(path.clone(), e))) .collect::>>()?, rt_cpus: cfg.rt_cpus.clone(), + protected_vm: cfg.protected_vm, }; let control_server_socket = match &cfg.socket_path { diff --git a/src/main.rs b/src/main.rs index 339e5f52ea..bf09f0f104 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1378,6 +1378,7 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: cfg.acpi_tables.push(acpi_table); } "protected-vm" => { + cfg.protected_vm = true; cfg.params.push("swiotlb=force".to_string()); } diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs index 77f3aee11c..ef44adc3b6 100644 --- a/x86_64/src/lib.rs +++ b/x86_64/src/lib.rs @@ -387,7 +387,13 @@ impl arch::LinuxArch for X8664arch { components.memory_size, )?; - Self::setup_serial_devices(&mut irq_chip, &mut io_bus, serial_parameters, serial_jail)?; + Self::setup_serial_devices( + components.protected_vm, + &mut irq_chip, + &mut io_bus, + serial_parameters, + serial_jail, + )?; let acpi_dev_resource = Self::setup_acpi_devices( &mut io_bus, @@ -824,6 +830,7 @@ impl X8664arch { /// * - `io_bus` the I/O bus to add the devices to /// * - `serial_parmaters` - definitions for how the serial devices should be configured fn setup_serial_devices( + protected_vm: bool, irq_chip: &mut impl IrqChip, io_bus: &mut devices::Bus, serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>, @@ -833,6 +840,7 @@ impl X8664arch { let com_evt_2_4 = Event::new().map_err(Error::CreateEvent)?; arch::add_serial_devices( + protected_vm, io_bus, &com_evt_1_3, &com_evt_2_4,