mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 10:10:41 +00:00
devices: virtio: Advertise VIRTIO_F_ACCESS_PLATFORM for protected VMs
Virtio 1.1 introduces the VIRTIO_F_ACCESS_PLATFORM reserved feature bit, which allows the guest operating system to discover that a virtio device has limited access to memory. In the case of Linux, this forces the use of the DMA API for virtio transfers, which in turn can bounce data through a shared window that is negotiated between the guest and the hypervisor. Advertise the VIRTIO_F_ACCESS_PLATFORM reserved feature bit when crosvm is running with the '--protected-vm' option. BUG=None TEST=./build_test Change-Id: I78e8d9e78999790059639b64611b8081c39d24ed Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2453560 Reviewed-by: Dylan Reid <dgreid@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
parent
0405973907
commit
7d2b8ac342
13 changed files with 53 additions and 25 deletions
|
@ -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,
|
||||
|
|
|
@ -83,6 +83,7 @@ pub struct VmComponents {
|
|||
pub wayland_dmabuf: bool,
|
||||
pub acpi_sdts: Vec<SDT>,
|
||||
pub rt_cpus: Vec<usize>,
|
||||
pub protected_vm: bool,
|
||||
}
|
||||
|
||||
/// Holds the elements needed to run a Linux VM. Created by `build_vm`.
|
||||
|
|
|
@ -224,6 +224,7 @@ impl SerialParameters {
|
|||
/// process. `evt` will always be added to this vector by this function.
|
||||
pub fn create_serial_device<T: SerialDevice>(
|
||||
&self,
|
||||
protected_vm: bool,
|
||||
evt: &Event,
|
||||
keep_fds: &mut Vec<RawFd>,
|
||||
) -> std::result::Result<T, Error> {
|
||||
|
@ -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::<Serial>(&com_evt, &mut preserved_fds)
|
||||
.create_serial_device::<Serial>(protected_vm, &com_evt, &mut preserved_fds)
|
||||
.map_err(DeviceRegistrationError::CreateSerialDevice)?;
|
||||
|
||||
match serial_jail.as_ref() {
|
||||
|
|
|
@ -84,6 +84,7 @@ pub struct Serial {
|
|||
|
||||
impl SerialDevice for Serial {
|
||||
fn new(
|
||||
_protected_vm: bool,
|
||||
interrupt_evt: Event,
|
||||
input: Option<Box<dyn io::Read + Send>>,
|
||||
out: Option<Box<dyn io::Write + Send>>,
|
||||
|
@ -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())),
|
||||
|
|
|
@ -11,6 +11,7 @@ use base::Event;
|
|||
/// output streams.
|
||||
pub trait SerialDevice {
|
||||
fn new(
|
||||
protected_vm: bool,
|
||||
interrupt_evt: Event,
|
||||
input: Option<Box<dyn io::Read + Send>>,
|
||||
output: Option<Box<dyn io::Write + Send>>,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -309,13 +309,14 @@ pub struct Console {
|
|||
|
||||
impl SerialDevice for Console {
|
||||
fn new(
|
||||
protected_vm: bool,
|
||||
_evt: Event,
|
||||
input: Option<Box<dyn io::Read + Send>>,
|
||||
output: Option<Box<dyn io::Write + Send>>,
|
||||
keep_fds: Vec<RawFd>,
|
||||
) -> Console {
|
||||
Console {
|
||||
base_features: base_features(),
|
||||
base_features: base_features(protected_vm),
|
||||
kill_evt: None,
|
||||
worker_thread: None,
|
||||
input,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -364,7 +364,7 @@ pub mod tests {
|
|||
|
||||
fn create_net_common() -> Net<FakeTap, FakeNet<FakeTap>> {
|
||||
let guest_memory = create_guest_memory().unwrap();
|
||||
let features = base_features();
|
||||
let features = base_features(false);
|
||||
Net::<FakeTap, FakeNet<FakeTap>>::new(
|
||||
features,
|
||||
Ipv4Addr::new(127, 0, 0, 1),
|
||||
|
|
|
@ -209,6 +209,7 @@ pub struct Config {
|
|||
pub video_dec: bool,
|
||||
pub video_enc: bool,
|
||||
pub acpi_tables: Vec<PathBuf>,
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
27
src/linux.rs
27
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::<Tap, vhost::Net<Tap>>::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::<Option<Vec<_>>>()
|
||||
.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::<Console>(&evt, &mut keep_fds)
|
||||
.create_serial_device::<Console>(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::<Result<Vec<SDT>>>()?,
|
||||
rt_cpus: cfg.rt_cpus.clone(),
|
||||
protected_vm: cfg.protected_vm,
|
||||
};
|
||||
|
||||
let control_server_socket = match &cfg.socket_path {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue