devices: virtio: Initial implementation of virtio-video device
This CL adds a fundamental part of the virtio video device, which will
be shared between the encoder and the decoder.
Both devices uses the virtio-video protocol proposed as RFC v3 [1,2].
The corresponding driver code is at CL:2060327 and its children CLs.
The actual decoding and encoding logic will be implemented in different
CLs.
[1]: mail: https://markmail.org/thread/wxdne5re7aaugbjg
[2]: PDF: https://drive.google.com/file/d/1jOsS2WdVhL4PpcWLO8Zukq5J0fXDiWn-/view
BUG=b:147465619, b:140082257
TEST=cargo check --features=video-decoder,video-encoder
TEST=ARCVM started with --video-decoder --video-encoder
Cq-Depend: chromium:2203997
Change-Id: I01999eea218ba0f3aaed1558ca2311a57d0c6819
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1973973
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
Tested-by: Keiichi Watanabe <keiichiw@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Keiichi Watanabe <keiichiw@chromium.org>
diff --git a/src/linux.rs b/src/linux.rs
index e480a4c..e95f372 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -792,6 +792,70 @@
})
}
+#[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 +1152,30 @@
)?);
}
+ #[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 {