Skip to content

Commit

Permalink
Add pipewire cross domain channel type.
Browse files Browse the repository at this point in the history
This adds a pipewire channel type, increases the maximum number
of fds that can be transferred in a single message, and adds support
for sharing eventfds between the guest and host.

Signed-off-by: Sasha Finkelstein <[email protected]>
  • Loading branch information
WhatAmISupposedToPutHere authored and slp committed Jan 14, 2025
1 parent 8330325 commit a739dfd
Show file tree
Hide file tree
Showing 8 changed files with 342 additions and 144 deletions.
17 changes: 15 additions & 2 deletions src/devices/src/virtio/gpu/virtio_gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use rutabaga_gfx::{
};
#[cfg(target_os = "linux")]
use rutabaga_gfx::{
RUTABAGA_CHANNEL_TYPE_X11, RUTABAGA_MAP_ACCESS_MASK, RUTABAGA_MAP_ACCESS_READ,
RUTABAGA_MAP_ACCESS_RW, RUTABAGA_MAP_ACCESS_WRITE,
RUTABAGA_CHANNEL_TYPE_PW, RUTABAGA_CHANNEL_TYPE_X11, RUTABAGA_MAP_ACCESS_MASK,
RUTABAGA_MAP_ACCESS_READ, RUTABAGA_MAP_ACCESS_RW, RUTABAGA_MAP_ACCESS_WRITE,
};
use utils::eventfd::EventFd;
use vm_memory::{GuestAddress, GuestMemory, GuestMemoryMmap, VolatileSlice};
Expand Down Expand Up @@ -210,6 +210,19 @@ impl VirtioGpu {
});
}
}
#[cfg(target_os = "linux")]
if let Ok(pw_sock_dir) = env::var("PIPEWIRE_RUNTIME_DIR")
.or_else(|_| env::var("XDG_RUNTIME_DIR"))
.or_else(|_| env::var("USERPROFILE"))
{
let name = env::var("PIPEWIRE_REMOTE").unwrap_or_else(|_| "pipewire-0".to_string());
let mut pw_path = PathBuf::from(pw_sock_dir);
pw_path.push(name);
rutabaga_channels.push(RutabagaChannel {
base_channel: pw_path,
channel_type: RUTABAGA_CHANNEL_TYPE_PW,
});
}
let rutabaga_channels_opt = Some(rutabaga_channels);

let builder = RutabagaBuilder::new(
Expand Down
1 change: 1 addition & 0 deletions src/rutabaga_gfx/ffi/src/include/rutabaga_gfx_ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ extern "C" {
* Rutabaga channel types
*/
#define RUTABAGA_CHANNEL_TYPE_WAYLAND 1
#define RUTABAGA_CHANNEL_TYPE_PW 0x10
#define RUTABAGA_CHANNEL_TYPE_X11 0x11

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// Channel types (must match rutabaga channel types)
#define CROSS_DOMAIN_CHANNEL_TYPE_WAYLAND 0x0001
#define CROSS_DOMAIN_CHANNEL_TYPE_CAMERA 0x0002
#define CROSS_DOMAIN_CHANNEL_TYPE_PW 0x0010
#define CROSS_DOMAIN_CHANNEL_TYPE_X11 0x0011

// The maximum number of identifiers (value based on wp_linux_dmabuf)
Expand Down
97 changes: 96 additions & 1 deletion src/rutabaga_gfx/src/cross_domain/cross_domain_protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,19 @@ pub const CROSS_DOMAIN_CMD_WRITE: u8 = 7;
pub const CROSS_DOMAIN_CMD_FUTEX_NEW: u8 = 8;
pub const CROSS_DOMAIN_CMD_FUTEX_SIGNAL: u8 = 9;
pub const CROSS_DOMAIN_CMD_FUTEX_DESTROY: u8 = 10;
pub const CROSS_DOMAIN_CMD_READ_EVENTFD_NEW: u8 = 11;
pub const CROSS_DOMAIN_CMD_READ_EVENTFD_DESTROY: u8 = 12;

/// Channel types (must match rutabaga channel types)
pub const CROSS_DOMAIN_CHANNEL_TYPE_WAYLAND: u32 = 0x0001;
pub const CROSS_DOMAIN_CHANNEL_TYPE_CAMERA: u32 = 0x0002;
pub const CROSS_DOMAIN_CHANNEL_TYPE_PW: u32 = 0x0010;
pub const CROSS_DOMAIN_CHANNEL_TYPE_X11: u32 = 0x0011;

/// The maximum number of identifiers (value inspired by wp_linux_dmabuf)
pub const CROSS_DOMAIN_MAX_IDENTIFIERS: usize = 4;
/// As above, but inspired by sommelier
pub const CROSS_DOMAIN_MAX_IDENTIFIERS_V2: usize = 28;

/// virtgpu memory resource ID. Also works with non-blob memory resources, despite the name.
pub const CROSS_DOMAIN_ID_TYPE_VIRTGPU_BLOB: u32 = 1;
Expand All @@ -42,6 +47,7 @@ pub const CROSS_DOMAIN_ID_TYPE_READ_PIPE: u32 = 3;
pub const CROSS_DOMAIN_ID_TYPE_WRITE_PIPE: u32 = 4;

pub const CROSS_DOMAIN_ID_TYPE_SHM: u32 = 5;
pub const CROSS_DOMAIN_ID_TYPE_EVENTFD: u32 = 6;

/// No ring
pub const CROSS_DOMAIN_RING_NONE: u32 = 0xffffffff;
Expand Down Expand Up @@ -86,11 +92,33 @@ pub struct CrossDomainHeader {

#[repr(C)]
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
pub struct CrossDomainInit {
pub struct CrossDomainInitV1 {
pub hdr: CrossDomainHeader,
pub query_ring_id: u32,
pub channel_ring_id: u32,
pub channel_type: u32,
pub protocol_version: u32,
}

#[repr(C)]
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
pub struct CrossDomainInitV0 {
pub hdr: CrossDomainHeader,
pub query_ring_id: u32,
pub channel_ring_id: u32,
pub channel_type: u32,
}

impl CrossDomainInitV0 {
pub(crate) fn upgrade(&self) -> CrossDomainInitV1 {
CrossDomainInitV1 {
hdr: self.hdr,
query_ring_id: self.query_ring_id,
channel_ring_id: self.channel_ring_id,
channel_type: self.channel_type,
protocol_version: 0,
}
}
}

#[repr(C)]
Expand All @@ -103,6 +131,14 @@ pub struct CrossDomainGetImageRequirements {
pub flags: u32,
}

pub trait CrossDomainSendReceiveBase: Copy + Clone + Default + AsBytes + FromBytes {
const MAX_IDENTIFIERS: usize;
fn hdr_mut(&mut self) -> &mut CrossDomainHeader;
fn num_identifiers_mut(&mut self) -> &mut u32;
fn opaque_data_size_mut(&mut self) -> &mut u32;
fn iter_over_identifiers(&mut self) -> impl Iterator<Item = (&mut u32, &mut u32, &mut u32)>;
}

#[repr(C)]
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
pub struct CrossDomainSendReceive {
Expand All @@ -114,6 +150,57 @@ pub struct CrossDomainSendReceive {
pub identifier_sizes: [u32; CROSS_DOMAIN_MAX_IDENTIFIERS],
// Data of size "opaque data size follows"
}
impl CrossDomainSendReceiveBase for CrossDomainSendReceive {
const MAX_IDENTIFIERS: usize = CROSS_DOMAIN_MAX_IDENTIFIERS;
fn hdr_mut(&mut self) -> &mut CrossDomainHeader {
&mut self.hdr
}
fn num_identifiers_mut(&mut self) -> &mut u32 {
&mut self.num_identifiers
}
fn opaque_data_size_mut(&mut self) -> &mut u32 {
&mut self.opaque_data_size
}
fn iter_over_identifiers(&mut self) -> impl Iterator<Item = (&mut u32, &mut u32, &mut u32)> {
self.identifiers
.iter_mut()
.zip(self.identifier_types.iter_mut())
.zip(self.identifier_sizes.iter_mut())
.map(|((i, it), is)| (i, it, is))
}
}

#[repr(C)]
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
pub struct CrossDomainSendReceiveV2 {
pub hdr: CrossDomainHeader,
pub num_identifiers: u32,
pub opaque_data_size: u32,
pub identifiers: [u32; CROSS_DOMAIN_MAX_IDENTIFIERS_V2],
pub identifier_types: [u32; CROSS_DOMAIN_MAX_IDENTIFIERS_V2],
pub identifier_sizes: [u32; CROSS_DOMAIN_MAX_IDENTIFIERS_V2],
// Data of size "opaque data size follows"
}

impl CrossDomainSendReceiveBase for CrossDomainSendReceiveV2 {
const MAX_IDENTIFIERS: usize = CROSS_DOMAIN_MAX_IDENTIFIERS_V2;
fn hdr_mut(&mut self) -> &mut CrossDomainHeader {
&mut self.hdr
}
fn num_identifiers_mut(&mut self) -> &mut u32 {
&mut self.num_identifiers
}
fn opaque_data_size_mut(&mut self) -> &mut u32 {
&mut self.opaque_data_size
}
fn iter_over_identifiers(&mut self) -> impl Iterator<Item = (&mut u32, &mut u32, &mut u32)> {
self.identifiers
.iter_mut()
.zip(self.identifier_types.iter_mut())
.zip(self.identifier_sizes.iter_mut())
.map(|((i, it), is)| (i, it, is))
}
}

#[repr(C)]
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
Expand Down Expand Up @@ -151,3 +238,11 @@ pub struct CrossDomainFutexDestroy {
pub id: u32,
pub pad: u32,
}

#[repr(C)]
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
pub struct CrossDomainReadEventfdNew {
pub hdr: CrossDomainHeader,
pub id: u32,
pub pad: u32,
}
Loading

0 comments on commit a739dfd

Please sign in to comment.