summary refs log tree commit diff
path: root/src/linux.rs
diff options
context:
space:
mode:
authorZach Reizner <zachr@google.com>2018-08-15 10:46:32 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-12-11 19:33:56 -0800
commitaa5756669a8331420b84a22e29ddbfc13b791da5 (patch)
tree3a2767b6ecc2779ca1e9f64ff7c60d8ae3bf8fdf /src/linux.rs
parent42c409c4d7c661ead9794c54811ce5fadf0ae8e7 (diff)
downloadcrosvm-aa5756669a8331420b84a22e29ddbfc13b791da5.tar
crosvm-aa5756669a8331420b84a22e29ddbfc13b791da5.tar.gz
crosvm-aa5756669a8331420b84a22e29ddbfc13b791da5.tar.bz2
crosvm-aa5756669a8331420b84a22e29ddbfc13b791da5.tar.lz
crosvm-aa5756669a8331420b84a22e29ddbfc13b791da5.tar.xz
crosvm-aa5756669a8331420b84a22e29ddbfc13b791da5.tar.zst
crosvm-aa5756669a8331420b84a22e29ddbfc13b791da5.zip
devices: allow virtio-wayland to use virtgpu resources
This change uses the resource bridge between virtio-gpu and virtio-cpu
to send resources over the host wayland connection that originated from
the virtio-gpu device. This will help support gpu accelerated wayland
surfaces.

BUG=chromium:875998
TEST=wayland-simple-egl

Change-Id: I3340ecef438779be5cb3643b2de8bb8c33097d75
Reviewed-on: https://chromium-review.googlesource.com/1182793
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'src/linux.rs')
-rw-r--r--src/linux.rs179
1 files changed, 96 insertions, 83 deletions
diff --git a/src/linux.rs b/src/linux.rs
index d4094fa..1cb99cc 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -382,6 +382,98 @@ fn create_virtio_devs(
         }
     }
 
+    #[cfg(feature = "gpu")]
+    let mut resource_bridge_wl_socket: Option<
+        devices::virtio::resource_bridge::ResourceRequestSocket,
+    > = None;
+    #[cfg(feature = "gpu")]
+    {
+        if cfg.gpu {
+            if let Some(wayland_socket_path) = cfg.wayland_socket_path.as_ref() {
+                let (wl_socket, gpu_socket) =
+                    devices::virtio::resource_bridge::pair().map_err(Error::CreateSocket)?;
+                resource_bridge_wl_socket = Some(wl_socket);
+
+                let jailed_wayland_path = Path::new("/wayland-0");
+
+                let gpu_box = Box::new(devices::virtio::Gpu::new(
+                    _exit_evt.try_clone().map_err(Error::CloneEventFd)?,
+                    Some(gpu_socket),
+                    if cfg.multiprocess {
+                        &jailed_wayland_path
+                    } else {
+                        wayland_socket_path.as_path()
+                    },
+                ));
+
+                let jail = if cfg.multiprocess {
+                    let policy_path: PathBuf = cfg.seccomp_policy_dir.join("gpu_device.policy");
+                    let mut jail = create_base_minijail(empty_root_path, &policy_path)?;
+
+                    // Create a tmpfs in the device's root directory so that we can bind mount the
+                    // dri directory into it.  The size=67108864 is size=64*1024*1024 or size=64MB.
+                    jail.mount_with_data(
+                        Path::new("none"),
+                        Path::new("/"),
+                        "tmpfs",
+                        (libc::MS_NOSUID | libc::MS_NODEV | libc::MS_NOEXEC) as usize,
+                        "size=67108864",
+                    ).unwrap();
+
+                    // Device nodes required for DRM.
+                    let sys_dev_char_path = Path::new("/sys/dev/char");
+                    jail.mount_bind(sys_dev_char_path, sys_dev_char_path, false)
+                        .unwrap();
+                    let sys_devices_path = Path::new("/sys/devices");
+                    jail.mount_bind(sys_devices_path, sys_devices_path, false)
+                        .unwrap();
+                    let drm_dri_path = Path::new("/dev/dri");
+                    jail.mount_bind(drm_dri_path, drm_dri_path, false).unwrap();
+
+                    // Libraries that are required when mesa drivers are dynamically loaded.
+                    let lib_path = Path::new("/lib64");
+                    jail.mount_bind(lib_path, lib_path, false).unwrap();
+                    let usr_lib_path = Path::new("/usr/lib64");
+                    jail.mount_bind(usr_lib_path, usr_lib_path, false).unwrap();
+
+                    // Bind mount the wayland socket into jail's root. This is necessary since each
+                    // new wayland context must open() the socket.
+                    jail.mount_bind(wayland_socket_path.as_path(), jailed_wayland_path, true)
+                        .unwrap();
+
+                    // Set the uid/gid for the jailed process, and give a basic id map. This
+                    // is required for the above bind mount to work.
+                    let crosvm_user_group = CStr::from_bytes_with_nul(b"crosvm\0").unwrap();
+                    let crosvm_uid = match get_user_id(&crosvm_user_group) {
+                        Ok(u) => u,
+                        Err(e) => {
+                            warn!("falling back to current user id for gpu: {:?}", e);
+                            geteuid()
+                        }
+                    };
+                    let crosvm_gid = match get_group_id(&crosvm_user_group) {
+                        Ok(u) => u,
+                        Err(e) => {
+                            warn!("falling back to current group id for gpu: {:?}", e);
+                            getegid()
+                        }
+                    };
+                    jail.change_uid(crosvm_uid);
+                    jail.change_gid(crosvm_gid);
+                    jail.uidmap(&format!("{0} {0} 1", crosvm_uid))
+                        .map_err(Error::SettingUidMap)?;
+                    jail.gidmap(&format!("{0} {0} 1", crosvm_gid))
+                        .map_err(Error::SettingGidMap)?;
+
+                    Some(jail)
+                } else {
+                    None
+                };
+                devs.push(VirtioDeviceStub { dev: gpu_box, jail });
+            }
+        }
+    }
+
     if let Some(wayland_socket_path) = cfg.wayland_socket_path.as_ref() {
         let wayland_socket_dir = wayland_socket_path
             .parent()
@@ -392,6 +484,9 @@ fn create_virtio_devs(
         let jailed_wayland_dir = Path::new("/wayland");
         let jailed_wayland_path = jailed_wayland_dir.join(wayland_socket_name);
 
+        #[cfg(not(feature = "gpu"))]
+        let resource_bridge_wl_socket = None;
+
         let wl_box = Box::new(
             devices::virtio::Wl::new(
                 if cfg.multiprocess {
@@ -400,6 +495,7 @@ fn create_virtio_devs(
                     wayland_socket_path.as_path()
                 },
                 wayland_device_socket,
+                resource_bridge_wl_socket,
             ).map_err(Error::WaylandDeviceNew)?,
         );
 
@@ -474,89 +570,6 @@ fn create_virtio_devs(
         });
     }
 
-    #[cfg(feature = "gpu")]
-    {
-        if cfg.gpu {
-            if let Some(wayland_socket_path) = cfg.wayland_socket_path.as_ref() {
-                let jailed_wayland_path = Path::new("/wayland-0");
-
-                let gpu_box = Box::new(devices::virtio::Gpu::new(
-                    _exit_evt.try_clone().map_err(Error::CloneEventFd)?,
-                    if cfg.multiprocess {
-                        &jailed_wayland_path
-                    } else {
-                        wayland_socket_path.as_path()
-                    },
-                ));
-
-                let jail = if cfg.multiprocess {
-                    let policy_path: PathBuf = cfg.seccomp_policy_dir.join("gpu_device.policy");
-                    let mut jail = create_base_minijail(empty_root_path, &policy_path)?;
-
-                    // Create a tmpfs in the device's root directory so that we can bind mount the
-                    // dri directory into it.  The size=67108864 is size=64*1024*1024 or size=64MB.
-                    jail.mount_with_data(
-                        Path::new("none"),
-                        Path::new("/"),
-                        "tmpfs",
-                        (libc::MS_NOSUID | libc::MS_NODEV | libc::MS_NOEXEC) as usize,
-                        "size=67108864",
-                    ).unwrap();
-
-                    // Device nodes required for DRM.
-                    let sys_dev_char_path = Path::new("/sys/dev/char");
-                    jail.mount_bind(sys_dev_char_path, sys_dev_char_path, false)
-                        .unwrap();
-                    let sys_devices_path = Path::new("/sys/devices");
-                    jail.mount_bind(sys_devices_path, sys_devices_path, false)
-                        .unwrap();
-                    let drm_dri_path = Path::new("/dev/dri");
-                    jail.mount_bind(drm_dri_path, drm_dri_path, false).unwrap();
-
-                    // Libraries that are required when mesa drivers are dynamically loaded.
-                    let lib_path = Path::new("/lib64");
-                    jail.mount_bind(lib_path, lib_path, false).unwrap();
-                    let usr_lib_path = Path::new("/usr/lib64");
-                    jail.mount_bind(usr_lib_path, usr_lib_path, false).unwrap();
-
-                    // Bind mount the wayland socket into jail's root. This is necessary since each
-                    // new wayland context must open() the socket.
-                    jail.mount_bind(wayland_socket_path.as_path(), jailed_wayland_path, true)
-                        .unwrap();
-
-                    // Set the uid/gid for the jailed process, and give a basic id map. This
-                    // is required for the above bind mount to work.
-                    let crosvm_user_group = CStr::from_bytes_with_nul(b"crosvm\0").unwrap();
-                    let crosvm_uid = match get_user_id(&crosvm_user_group) {
-                        Ok(u) => u,
-                        Err(e) => {
-                            warn!("falling back to current user id for gpu: {:?}", e);
-                            geteuid()
-                        }
-                    };
-                    let crosvm_gid = match get_group_id(&crosvm_user_group) {
-                        Ok(u) => u,
-                        Err(e) => {
-                            warn!("falling back to current group id for gpu: {:?}", e);
-                            getegid()
-                        }
-                    };
-                    jail.change_uid(crosvm_uid);
-                    jail.change_gid(crosvm_gid);
-                    jail.uidmap(&format!("{0} {0} 1", crosvm_uid))
-                        .map_err(Error::SettingUidMap)?;
-                    jail.gidmap(&format!("{0} {0} 1", crosvm_gid))
-                        .map_err(Error::SettingGidMap)?;
-
-                    Some(jail)
-                } else {
-                    None
-                };
-                devs.push(VirtioDeviceStub { dev: gpu_box, jail });
-            }
-        }
-    }
-
     let chronos_user_group = CStr::from_bytes_with_nul(b"chronos\0").unwrap();
     let chronos_uid = match get_user_id(&chronos_user_group) {
         Ok(u) => u,