Skip to content

Commit 9d210c1

Browse files
Add pipewire cross domain channel type.
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 <fnkl.kernel@gmail.com>
1 parent 8330325 commit 9d210c1

File tree

9 files changed

+351
-160
lines changed

9 files changed

+351
-160
lines changed

src/devices/src/virtio/gpu/virtio_gpu.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ use rutabaga_gfx::{
2424
};
2525
#[cfg(target_os = "linux")]
2626
use rutabaga_gfx::{
27-
RUTABAGA_CHANNEL_TYPE_X11, RUTABAGA_MAP_ACCESS_MASK, RUTABAGA_MAP_ACCESS_READ,
28-
RUTABAGA_MAP_ACCESS_RW, RUTABAGA_MAP_ACCESS_WRITE,
27+
RUTABAGA_CHANNEL_TYPE_PW, RUTABAGA_CHANNEL_TYPE_X11, RUTABAGA_MAP_ACCESS_MASK,
28+
RUTABAGA_MAP_ACCESS_READ, RUTABAGA_MAP_ACCESS_RW, RUTABAGA_MAP_ACCESS_WRITE,
2929
};
3030
use utils::eventfd::EventFd;
3131
use vm_memory::{GuestAddress, GuestMemory, GuestMemoryMmap, VolatileSlice};
@@ -210,6 +210,19 @@ impl VirtioGpu {
210210
});
211211
}
212212
}
213+
#[cfg(target_os = "linux")]
214+
if let Ok(pw_sock_dir) = env::var("PIPEWIRE_RUNTIME_DIR")
215+
.or_else(|_| env::var("XDG_RUNTIME_DIR"))
216+
.or_else(|_| env::var("USERPROFILE"))
217+
{
218+
let name = env::var("PIPEWIRE_REMOTE").unwrap_or_else(|_| "pipewire-0".to_string());
219+
let mut pw_path = PathBuf::from(pw_sock_dir);
220+
pw_path.push(name);
221+
rutabaga_channels.push(RutabagaChannel {
222+
base_channel: pw_path,
223+
channel_type: RUTABAGA_CHANNEL_TYPE_PW,
224+
});
225+
}
213226
let rutabaga_channels_opt = Some(rutabaga_channels);
214227

215228
let builder = RutabagaBuilder::new(

src/rutabaga_gfx/ffi/src/include/rutabaga_gfx_ffi.h

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ extern "C" {
8787
* Rutabaga channel types
8888
*/
8989
#define RUTABAGA_CHANNEL_TYPE_WAYLAND 1
90+
#define RUTABAGA_CHANNEL_TYPE_PW 0x10
9091
#define RUTABAGA_CHANNEL_TYPE_X11 0x11
9192

9293
/**

src/rutabaga_gfx/ffi/src/tests/virtgpu_cross_domain_protocol.h

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
// Channel types (must match rutabaga channel types)
2020
#define CROSS_DOMAIN_CHANNEL_TYPE_WAYLAND 0x0001
2121
#define CROSS_DOMAIN_CHANNEL_TYPE_CAMERA 0x0002
22+
#define CROSS_DOMAIN_CHANNEL_TYPE_PW 0x0010
2223
#define CROSS_DOMAIN_CHANNEL_TYPE_X11 0x0011
2324

2425
// The maximum number of identifiers (value based on wp_linux_dmabuf)

src/rutabaga_gfx/src/cross_domain/cross_domain_protocol.rs

+96-1
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,19 @@ pub const CROSS_DOMAIN_CMD_WRITE: u8 = 7;
2121
pub const CROSS_DOMAIN_CMD_FUTEX_NEW: u8 = 8;
2222
pub const CROSS_DOMAIN_CMD_FUTEX_SIGNAL: u8 = 9;
2323
pub const CROSS_DOMAIN_CMD_FUTEX_DESTROY: u8 = 10;
24+
pub const CROSS_DOMAIN_CMD_READ_EVENTFD_NEW: u8 = 11;
25+
pub const CROSS_DOMAIN_CMD_READ_EVENTFD_DESTROY: u8 = 12;
2426

2527
/// Channel types (must match rutabaga channel types)
2628
pub const CROSS_DOMAIN_CHANNEL_TYPE_WAYLAND: u32 = 0x0001;
2729
pub const CROSS_DOMAIN_CHANNEL_TYPE_CAMERA: u32 = 0x0002;
30+
pub const CROSS_DOMAIN_CHANNEL_TYPE_PW: u32 = 0x0010;
2831
pub const CROSS_DOMAIN_CHANNEL_TYPE_X11: u32 = 0x0011;
2932

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

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

4449
pub const CROSS_DOMAIN_ID_TYPE_SHM: u32 = 5;
50+
pub const CROSS_DOMAIN_ID_TYPE_EVENTFD: u32 = 6;
4551

4652
/// No ring
4753
pub const CROSS_DOMAIN_RING_NONE: u32 = 0xffffffff;
@@ -86,11 +92,33 @@ pub struct CrossDomainHeader {
8692

8793
#[repr(C)]
8894
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
89-
pub struct CrossDomainInit {
95+
pub struct CrossDomainInitV1 {
9096
pub hdr: CrossDomainHeader,
9197
pub query_ring_id: u32,
9298
pub channel_ring_id: u32,
9399
pub channel_type: u32,
100+
pub protocol_version: u32,
101+
}
102+
103+
#[repr(C)]
104+
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
105+
pub struct CrossDomainInitV0 {
106+
pub hdr: CrossDomainHeader,
107+
pub query_ring_id: u32,
108+
pub channel_ring_id: u32,
109+
pub channel_type: u32,
110+
}
111+
112+
impl CrossDomainInitV0 {
113+
pub(crate) fn upgrade(&self) -> CrossDomainInitV1 {
114+
CrossDomainInitV1 {
115+
hdr: self.hdr,
116+
query_ring_id: self.query_ring_id,
117+
channel_ring_id: self.channel_ring_id,
118+
channel_type: self.channel_type,
119+
protocol_version: 0,
120+
}
121+
}
94122
}
95123

96124
#[repr(C)]
@@ -103,6 +131,14 @@ pub struct CrossDomainGetImageRequirements {
103131
pub flags: u32,
104132
}
105133

134+
pub trait CrossDomainSendReceiveBase: Copy + Clone + Default + AsBytes + FromBytes {
135+
const MAX_IDENTIFIERS: usize;
136+
fn hdr_mut(&mut self) -> &mut CrossDomainHeader;
137+
fn num_identifiers_mut(&mut self) -> &mut u32;
138+
fn opaque_data_size_mut(&mut self) -> &mut u32;
139+
fn iter_over_identifiers(&mut self) -> impl Iterator<Item = (&mut u32, &mut u32, &mut u32)>;
140+
}
141+
106142
#[repr(C)]
107143
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
108144
pub struct CrossDomainSendReceive {
@@ -114,6 +150,57 @@ pub struct CrossDomainSendReceive {
114150
pub identifier_sizes: [u32; CROSS_DOMAIN_MAX_IDENTIFIERS],
115151
// Data of size "opaque data size follows"
116152
}
153+
impl CrossDomainSendReceiveBase for CrossDomainSendReceive {
154+
const MAX_IDENTIFIERS: usize = CROSS_DOMAIN_MAX_IDENTIFIERS;
155+
fn hdr_mut(&mut self) -> &mut CrossDomainHeader {
156+
&mut self.hdr
157+
}
158+
fn num_identifiers_mut(&mut self) -> &mut u32 {
159+
&mut self.num_identifiers
160+
}
161+
fn opaque_data_size_mut(&mut self) -> &mut u32 {
162+
&mut self.opaque_data_size
163+
}
164+
fn iter_over_identifiers(&mut self) -> impl Iterator<Item = (&mut u32, &mut u32, &mut u32)> {
165+
self.identifiers
166+
.iter_mut()
167+
.zip(self.identifier_types.iter_mut())
168+
.zip(self.identifier_sizes.iter_mut())
169+
.map(|((i, it), is)| (i, it, is))
170+
}
171+
}
172+
173+
#[repr(C)]
174+
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
175+
pub struct CrossDomainSendReceiveV2 {
176+
pub hdr: CrossDomainHeader,
177+
pub num_identifiers: u32,
178+
pub opaque_data_size: u32,
179+
pub identifiers: [u32; CROSS_DOMAIN_MAX_IDENTIFIERS_V2],
180+
pub identifier_types: [u32; CROSS_DOMAIN_MAX_IDENTIFIERS_V2],
181+
pub identifier_sizes: [u32; CROSS_DOMAIN_MAX_IDENTIFIERS_V2],
182+
// Data of size "opaque data size follows"
183+
}
184+
185+
impl CrossDomainSendReceiveBase for CrossDomainSendReceiveV2 {
186+
const MAX_IDENTIFIERS: usize = CROSS_DOMAIN_MAX_IDENTIFIERS_V2;
187+
fn hdr_mut(&mut self) -> &mut CrossDomainHeader {
188+
&mut self.hdr
189+
}
190+
fn num_identifiers_mut(&mut self) -> &mut u32 {
191+
&mut self.num_identifiers
192+
}
193+
fn opaque_data_size_mut(&mut self) -> &mut u32 {
194+
&mut self.opaque_data_size
195+
}
196+
fn iter_over_identifiers(&mut self) -> impl Iterator<Item = (&mut u32, &mut u32, &mut u32)> {
197+
self.identifiers
198+
.iter_mut()
199+
.zip(self.identifier_types.iter_mut())
200+
.zip(self.identifier_sizes.iter_mut())
201+
.map(|((i, it), is)| (i, it, is))
202+
}
203+
}
117204

118205
#[repr(C)]
119206
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
@@ -151,3 +238,11 @@ pub struct CrossDomainFutexDestroy {
151238
pub id: u32,
152239
pub pad: u32,
153240
}
241+
242+
#[repr(C)]
243+
#[derive(Copy, Clone, Default, AsBytes, FromBytes)]
244+
pub struct CrossDomainReadEventfdNew {
245+
pub hdr: CrossDomainHeader,
246+
pub id: u32,
247+
pub pad: u32,
248+
}

0 commit comments

Comments
 (0)