summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-06-02 03:03:26 +0000
committerAlyssa Ross <hi@alyssa.is>2020-06-14 11:23:24 +0000
commit28d9682698d287d14cbe67a0ed7acc1427add320 (patch)
tree669ed98d9b1388b553c8e0f0189678cc68dd4162 /src
parent460406d10bbfaa890d56d616b4610813da63a312 (diff)
parent4264464153a7a788ef73c5015ac8bbde5f8ebe1c (diff)
downloadcrosvm-28d9682698d287d14cbe67a0ed7acc1427add320.tar
crosvm-28d9682698d287d14cbe67a0ed7acc1427add320.tar.gz
crosvm-28d9682698d287d14cbe67a0ed7acc1427add320.tar.bz2
crosvm-28d9682698d287d14cbe67a0ed7acc1427add320.tar.lz
crosvm-28d9682698d287d14cbe67a0ed7acc1427add320.tar.xz
crosvm-28d9682698d287d14cbe67a0ed7acc1427add320.tar.zst
crosvm-28d9682698d287d14cbe67a0ed7acc1427add320.zip
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'src')
-rw-r--r--src/crosvm.rs6
-rw-r--r--src/linux.rs97
-rw-r--r--src/main.rs35
-rw-r--r--src/plugin/process.rs4
4 files changed, 140 insertions, 2 deletions
diff --git a/src/crosvm.rs b/src/crosvm.rs
index 49a08c0..1ea7e0d 100644
--- a/src/crosvm.rs
+++ b/src/crosvm.rs
@@ -202,6 +202,9 @@ pub struct Config {
     pub virtio_input_evdevs: Vec<PathBuf>,
     pub split_irqchip: bool,
     pub vfio: Vec<PathBuf>,
+    pub video_dec: bool,
+    pub video_enc: bool,
+    pub acpi_tables: Vec<PathBuf>,
 }
 
 impl Default for Config {
@@ -250,6 +253,9 @@ impl Default for Config {
             virtio_input_evdevs: Vec::new(),
             split_irqchip: false,
             vfio: Vec::new(),
+            video_dec: false,
+            video_enc: false,
+            acpi_tables: Vec::new(),
         }
     }
 }
diff --git a/src/linux.rs b/src/linux.rs
index 574493d..3e2045f 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -26,6 +26,8 @@ use std::time::Duration;
 
 use libc::{self, c_int, gid_t, uid_t};
 
+use acpi_tables::sdt::SDT;
+
 #[cfg(feature = "gpu")]
 use devices::virtio::EventDevice;
 use devices::virtio::{self, Console, VirtioDevice};
@@ -109,6 +111,7 @@ pub enum Error {
     LoadKernel(Box<dyn StdError>),
     MemoryTooLarge,
     NetDeviceNew(virtio::NetError),
+    OpenAcpiTable(PathBuf, io::Error),
     OpenAndroidFstab(PathBuf, io::Error),
     OpenBios(PathBuf, io::Error),
     OpenInitrd(PathBuf, io::Error),
@@ -196,6 +199,7 @@ impl Display for Error {
             LoadKernel(e) => write!(f, "failed to load kernel: {}", e),
             MemoryTooLarge => write!(f, "requested memory size too large"),
             NetDeviceNew(e) => write!(f, "failed to set up virtio networking: {}", e),
+            OpenAcpiTable(p, e) => write!(f, "failed to open ACPI file {}: {}", p.display(), e),
             OpenAndroidFstab(p, e) => write!(
                 f,
                 "failed to open android fstab file {}: {}",
@@ -792,6 +796,70 @@ fn create_wayland_device(
     })
 }
 
+#[cfg(any(feature = "video-decoder", feature = "video-encoder"))]
+fn create_video_device(
+    cfg: &Config,
+    typ: devices::virtio::VideoDeviceType,
+    resource_bridge: virtio::resource_bridge::ResourceRequestSocket,
+) -> DeviceResult {
+    let jail = match simple_jail(&cfg, "video_device")? {
+        Some(mut jail) => {
+            match typ {
+                devices::virtio::VideoDeviceType::Decoder => {
+                    add_crosvm_user_to_jail(&mut jail, "video-decoder")?
+                }
+                devices::virtio::VideoDeviceType::Encoder => {
+                    add_crosvm_user_to_jail(&mut jail, "video-encoder")?
+                }
+            };
+
+            // Create a tmpfs in the device's root directory so that we can bind mount files.
+            jail.mount_with_data(
+                Path::new("none"),
+                Path::new("/"),
+                "tmpfs",
+                (libc::MS_NOSUID | libc::MS_NODEV | libc::MS_NOEXEC) as usize,
+                "size=67108864",
+            )?;
+
+            // Render node for libvda.
+            let dev_dri_path = Path::new("/dev/dri/renderD128");
+            jail.mount_bind(dev_dri_path, dev_dri_path, false)?;
+
+            // Device nodes required by libchrome which establishes Mojo connection in libvda.
+            let dev_urandom_path = Path::new("/dev/urandom");
+            jail.mount_bind(dev_urandom_path, dev_urandom_path, false)?;
+            let system_bus_socket_path = Path::new("/run/dbus/system_bus_socket");
+            jail.mount_bind(system_bus_socket_path, system_bus_socket_path, true)?;
+
+            Some(jail)
+        }
+        None => None,
+    };
+
+    Ok(VirtioDeviceStub {
+        dev: Box::new(devices::virtio::VideoDevice::new(
+            typ,
+            Some(resource_bridge),
+        )),
+        jail,
+    })
+}
+
+#[cfg(any(feature = "video-decoder", feature = "video-encoder"))]
+fn register_video_device(
+    devs: &mut Vec<VirtioDeviceStub>,
+    resource_bridges: &mut Vec<virtio::resource_bridge::ResourceResponseSocket>,
+    cfg: &Config,
+    typ: devices::virtio::VideoDeviceType,
+) -> std::result::Result<(), Error> {
+    let (video_socket, gpu_socket) =
+        virtio::resource_bridge::pair().map_err(Error::CreateSocket)?;
+    resource_bridges.push(gpu_socket);
+    devs.push(create_video_device(cfg, typ, video_socket)?);
+    Ok(())
+}
+
 fn create_vhost_vsock_device(cfg: &Config, cid: u64, mem: &GuestMemory) -> DeviceResult {
     let dev = virtio::vhost::Vsock::new(cid, mem).map_err(Error::VhostVsockDeviceNew)?;
 
@@ -1088,6 +1156,30 @@ fn create_virtio_devices(
         )?);
     }
 
+    #[cfg(feature = "video-decoder")]
+    {
+        if cfg.video_dec {
+            register_video_device(
+                &mut devs,
+                &mut resource_bridges,
+                cfg,
+                devices::virtio::VideoDeviceType::Decoder,
+            )?;
+        }
+    }
+
+    #[cfg(feature = "video-encoder")]
+    {
+        if cfg.video_enc {
+            register_video_device(
+                &mut devs,
+                &mut resource_bridges,
+                cfg,
+                devices::virtio::VideoDeviceType::Encoder,
+            )?;
+        }
+    }
+
     #[cfg(feature = "gpu")]
     {
         if let Some(gpu_parameters) = &cfg.gpu_parameters {
@@ -1624,6 +1716,11 @@ pub fn run_config(cfg: Config) -> Result<()> {
         initrd_image,
         extra_kernel_params: cfg.params.clone(),
         wayland_dmabuf: cfg.wayland_dmabuf,
+        acpi_sdts: cfg
+            .acpi_tables
+            .iter()
+            .map(|path| SDT::from_file(path).map_err(|e| Error::OpenAcpiTable(path.clone(), e)))
+            .collect::<Result<Vec<SDT>>>()?,
     };
 
     let control_server_socket = match &cfg.socket_path {
diff --git a/src/main.rs b/src/main.rs
index 7fd3eca..ed7bb30 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1223,6 +1223,29 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
 
             cfg.vfio.push(vfio_path);
         }
+        "video-decoder" => {
+            cfg.video_dec = true;
+        }
+        "video-encoder" => {
+            cfg.video_enc = true;
+        }
+        "acpi-table" => {
+            let acpi_table = PathBuf::from(value.unwrap());
+            if !acpi_table.exists() {
+                return Err(argument::Error::InvalidValue {
+                    value: value.unwrap().to_owned(),
+                    expected: String::from("the acpi-table path does not exist"),
+                });
+            }
+            if !acpi_table.is_file() {
+                return Err(argument::Error::InvalidValue {
+                    value: value.unwrap().to_owned(),
+                    expected: String::from("the acpi-table path should be a file"),
+                });
+            }
+
+            cfg.acpi_tables.push(acpi_table);
+        }
 
         "help" => return Err(argument::Error::PrintHelp),
         _ => unreachable!(),
@@ -1677,6 +1700,18 @@ Enable split-irqchip support.
             "PATH",
             "Path to sysfs of pass through or mdev device",
         ),
+        #[cfg(feature = "video-decoder")]
+        Argument::flag("video-decoder", "\
+(EXPERIMENTAL)
+Enable virtio-video decoder device.
+",
+        ),
+        #[cfg(feature = "video-encoder")]
+        Argument::flag("video-encoder", "\
+(EXPERIMENTAL)
+Enable virtio-video encoder device.
+"),
+        Argument::value("acpi-table", "PATH", "Path to user provided ACPI table."),
         Argument::short_flag('h', "help", "Print help message."),
     ];
 
diff --git a/src/plugin/process.rs b/src/plugin/process.rs
index 783239a..688aa85 100644
--- a/src/plugin/process.rs
+++ b/src/plugin/process.rs
@@ -5,7 +5,7 @@
 use std::collections::hash_map::{Entry, HashMap, VacantEntry};
 use std::env::set_var;
 use std::fs::File;
-use std::io::Write;
+use std::io::{IoSlice, Write};
 use std::mem::transmute;
 use std::os::unix::io::{IntoRawFd, RawFd};
 use std::os::unix::net::UnixDatagram;
@@ -730,7 +730,7 @@ impl Process {
             .map_err(Error::EncodeResponse)?;
         assert_ne!(self.response_buffer.len(), 0);
         self.request_sockets[index]
-            .send_with_fds(&self.response_buffer[..], &response_fds)
+            .send_with_fds(&[IoSlice::new(&self.response_buffer[..])], &response_fds)
             .map_err(Error::PluginSocketSend)?;
 
         Ok(())