Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions vhost-device-gpu/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

### Added

- [[#945]] (https://github.com/rust-vmm/vhost-device/pull/945) Implement RESOURCE_ASSIGN_UUID command
- [[#932]] (https://github.com/rust-vmm/vhost-device/pull/932) vhost-device-gpu: Add support for GPU device path
- [[#927]] (https://github.com/rust-vmm/vhost-device/pull/927) vhost-device-gpu: Introduce headless mode

Expand Down
1 change: 1 addition & 0 deletions vhost-device-gpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ virtio-queue = "0.17.0"
vm-memory = "0.17.1"
vmm-sys-util = "0.15.0"
bitflags = "2.11.0"
uuid = { version = "1.19", features = ["v4"] }

[dev-dependencies]
assert_matches = "1.5"
Expand Down
33 changes: 26 additions & 7 deletions vhost-device-gpu/src/backend/gfxstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use rutabaga_gfx::{
ResourceCreate3D, Rutabaga, RutabagaBuilder, RutabagaComponentType, RutabagaFence,
RutabagaFenceHandler, RutabagaHandle, RutabagaIntoRawDescriptor, RutabagaIovec, Transfer3D,
};
use uuid::Uuid;
use vhost::vhost_user::{
gpu_message::{
VhostUserGpuCursorPos, VhostUserGpuEdidRequest, VhostUserGpuScanout, VhostUserGpuUpdate,
Expand Down Expand Up @@ -51,14 +52,15 @@ use crate::{
const READ_RESOURCE_BYTES_PER_PIXEL: u32 = 4;

// A local resource struct for the Gfxstream backend
#[derive(Default, Clone)]
#[derive(Clone)]
pub struct GfxstreamResource {
pub id: u32,
pub width: u32,
pub height: u32,
scanouts: common::AssociatedScanouts,
pub info_3d: Option<rutabaga_gfx::Resource3DInfo>,
pub handle: Option<Arc<RutabagaHandle>>,
pub uuid: Uuid,
}

impl GfxstreamResource {
Expand All @@ -85,6 +87,7 @@ impl GfxstreamResource {
scanouts: AssociatedScanouts::default(),
info_3d: None,
handle: None,
uuid: Uuid::new_v4(),
}
}
}
Expand Down Expand Up @@ -285,6 +288,7 @@ impl Renderer for GfxstreamAdapter {
scanouts: AssociatedScanouts::default(),
info_3d: None,
handle: None,
uuid: Uuid::new_v4(),
};
debug_assert!(
!self.resources.contains_key(&resource_id),
Expand Down Expand Up @@ -425,9 +429,15 @@ impl Renderer for GfxstreamAdapter {
})
}

fn resource_assign_uuid(&self, _resource_id: u32) -> VirtioGpuResult {
error!("Not implemented: resource_assign_uuid");
Err(ErrUnspec)
fn resource_assign_uuid(&self, resource_id: u32) -> VirtioGpuResult {
debug!("resource_assign_uuid for resource {}", resource_id);
let resource = self
.resources
.get(&resource_id)
.ok_or(ErrInvalidResourceId)?;
Ok(GpuResponse::OkResourceUuid {
uuid: *resource.uuid.as_bytes(),
})
}

fn get_capset_info(&self, index: u32) -> VirtioGpuResult {
Expand Down Expand Up @@ -1124,7 +1134,10 @@ mod gfx_fence_tests {
id: 1,
width: 64,
height: 64,
..Default::default()
scanouts: common::AssociatedScanouts::default(),
info_3d: None,
handle: None,
uuid: Uuid::new_v4(),
};
// 64 * 64 * 4 BPP = 16384
assert_eq!(
Expand All @@ -1140,7 +1153,10 @@ mod gfx_fence_tests {
id: 1,
width: u32::MAX,
height: u32::MAX,
..Default::default()
scanouts: common::AssociatedScanouts::default(),
info_3d: None,
handle: None,
uuid: Uuid::new_v4(),
};
r.calculate_size().unwrap_err();
}
Expand All @@ -1153,7 +1169,10 @@ mod gfx_fence_tests {
id: 1,
width: big as u32,
height: 1,
..Default::default()
scanouts: common::AssociatedScanouts::default(),
info_3d: None,
handle: None,
uuid: Uuid::new_v4(),
};
// On 64-bit this should error; if it happens to fit on 32-bit, the guard still
// holds elsewhere.
Expand Down
13 changes: 9 additions & 4 deletions vhost-device-gpu/src/backend/null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ impl Renderer for NullAdapter {
}

fn resource_assign_uuid(&self, _resource_id: u32) -> VirtioGpuResult {
trace!("NullAdapter::resource_assign_uuid - no-op");
Ok(GpuResponse::OkNoData)
trace!("NullAdapter::resource_assign_uuid - returning zero UUID");
Ok(GpuResponse::OkResourceUuid { uuid: [0u8; 16] })
}

fn get_capset_info(&self, _capset_index: u32) -> VirtioGpuResult {
Expand Down Expand Up @@ -452,9 +452,14 @@ mod tests {
fn test_null_adapter_misc_operations() {
let adapter = create_null_adapter();

// Verify assigning UUID to resource succeeds
// Verify assigning UUID to resource succeeds with zero UUID
let result = adapter.resource_assign_uuid(1);
assert!(matches!(result, Ok(GpuResponse::OkNoData)));
match result {
Ok(GpuResponse::OkResourceUuid { uuid }) => {
assert_eq!(uuid, [0u8; 16], "Null adapter should return zero UUID");
}
_ => panic!("Expected OkResourceUuid"),
}

// Verify no event poll fd is provided (null backend has no events)
let event_fd = adapter.get_event_poll_fd();
Expand Down
21 changes: 15 additions & 6 deletions vhost-device-gpu/src/backend/virgl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use libc::c_void;
use log::{debug, error, trace, warn};
use rutabaga_gfx::RutabagaFence;
use thiserror::Error as ThisError;
use uuid::Uuid;
use vhost::vhost_user::{
gpu_message::{
VhostUserGpuCursorPos, VhostUserGpuDMABUFScanout, VhostUserGpuDMABUFScanout2,
Expand Down Expand Up @@ -73,6 +74,7 @@ pub struct GpuResource {
// resource. Resource could be used for multiple scanouts.
pub scanouts: AssociatedScanouts,
pub backing_iovecs: Arc<Mutex<Option<Vec<Iovec>>>>,
pub uuid: Uuid,
}

fn sglist_to_iovecs(
Expand Down Expand Up @@ -211,6 +213,7 @@ impl Renderer for VirglRendererAdapter {
virgl_resource,
scanouts: AssociatedScanouts::default(),
backing_iovecs: Arc::new(Mutex::new(None)),
uuid: Uuid::new_v4(),
};
self.resources.insert(resource_id, local_resource);
Ok(OkNoData)
Expand Down Expand Up @@ -357,9 +360,15 @@ impl Renderer for VirglRendererAdapter {
})
}

fn resource_assign_uuid(&self, _resource_id: u32) -> VirtioGpuResult {
error!("Not implemented: resource_assign_uuid");
Err(ErrUnspec)
fn resource_assign_uuid(&self, resource_id: u32) -> VirtioGpuResult {
debug!("resource_assign_uuid for resource {}", resource_id);
let resource = self
.resources
.get(&resource_id)
.ok_or(ErrInvalidResourceId)?;
Ok(GpuResponse::OkResourceUuid {
uuid: *resource.uuid.as_bytes(),
})
}

fn get_capset_info(&self, index: u32) -> VirtioGpuResult {
Expand Down Expand Up @@ -947,10 +956,10 @@ mod virgl_cov_tests {
Err(GpuResponse::ErrUnspec)
);

// Test resource_assign_uuid (not implemented)
// Test resource_assign_uuid with invalid resource
assert_matches!(
gpu.resource_assign_uuid(1),
Err(GpuResponse::ErrUnspec)
gpu.resource_assign_uuid(999),
Err(GpuResponse::ErrInvalidResourceId)
);

// Test display_info (should fail without frontend)
Expand Down
78 changes: 64 additions & 14 deletions vhost-device-gpu/src/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ use virtio_bindings::{
},
virtio_gpu::{
VIRTIO_GPU_F_CONTEXT_INIT, VIRTIO_GPU_F_EDID, VIRTIO_GPU_F_RESOURCE_BLOB,
VIRTIO_GPU_F_VIRGL,
VIRTIO_GPU_F_RESOURCE_UUID, VIRTIO_GPU_F_VIRGL,
},
};
use virtio_queue::{QueueOwnedT, Reader, Writer};
Expand Down Expand Up @@ -231,8 +231,8 @@ impl VhostUserGpuBackendInner {
}
GpuCommand::UpdateCursor(req) => Self::handle_update_cursor(renderer, req),
GpuCommand::MoveCursor(req) => Self::handle_move_cursor(renderer, req),
GpuCommand::ResourceAssignUuid(_) => {
panic!("virtio_gpu: GpuCommand::ResourceAssignUuid unimplemented")
GpuCommand::ResourceAssignUuid(req) => {
renderer.resource_assign_uuid(req.resource_id.into())
}
GpuCommand::GetCapsetInfo(req) => renderer.get_capset_info(req.capset_index.into()),
GpuCommand::GetCapset(req) => {
Expand Down Expand Up @@ -700,6 +700,7 @@ impl VhostUserBackend for VhostUserGpuBackend {
| (1 << VIRTIO_RING_F_EVENT_IDX)
| (1 << VIRTIO_GPU_F_VIRGL)
| (1 << VIRTIO_GPU_F_RESOURCE_BLOB)
| (1 << VIRTIO_GPU_F_RESOURCE_UUID)
| (1 << VIRTIO_GPU_F_CONTEXT_INIT)
| VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();

Expand Down Expand Up @@ -805,22 +806,24 @@ mod tests {

use super::*;
use crate::{
backend::virgl::VirglRendererAdapter,
gpu_types::{ResourceCreate3d, Transfer3DDesc, VirtioGpuRing},
protocol::{
virtio_gpu_ctrl_hdr, virtio_gpu_ctx_create, virtio_gpu_ctx_destroy,
virtio_gpu_ctx_resource, virtio_gpu_get_capset, virtio_gpu_get_capset_info,
virtio_gpu_mem_entry, virtio_gpu_rect, virtio_gpu_resource_attach_backing,
virtio_gpu_mem_entry, virtio_gpu_rect, virtio_gpu_resource_assign_uuid,
virtio_gpu_resource_attach_backing, virtio_gpu_resource_create_2d,
virtio_gpu_resource_detach_backing, virtio_gpu_resource_flush,
virtio_gpu_resource_unref, virtio_gpu_set_scanout,
GpuResponse::{OkCapset, OkCapsetInfo, OkDisplayInfo, OkEdid, OkNoData},
VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE, VIRTIO_GPU_CMD_CTX_CREATE,
VIRTIO_GPU_CMD_CTX_DESTROY, VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE,
VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING, VIRTIO_GPU_CMD_RESOURCE_CREATE_2D,
VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING, VIRTIO_GPU_CMD_RESOURCE_FLUSH,
VIRTIO_GPU_CMD_SET_SCANOUT, VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D,
VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D, VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D,
VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM, VIRTIO_GPU_RESP_ERR_UNSPEC,
VIRTIO_GPU_RESP_OK_NODATA,
GpuResponse::{self, OkCapset, OkCapsetInfo, OkDisplayInfo, OkEdid, OkNoData},
VIRTIO_GPU_BIND_RENDER_TARGET, VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE,
VIRTIO_GPU_CMD_CTX_CREATE, VIRTIO_GPU_CMD_CTX_DESTROY,
VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE, VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING,
VIRTIO_GPU_CMD_RESOURCE_CREATE_2D, VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING,
VIRTIO_GPU_CMD_RESOURCE_FLUSH, VIRTIO_GPU_CMD_SET_SCANOUT,
VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D, VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D,
VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D, VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM,
VIRTIO_GPU_RESP_ERR_UNSPEC, VIRTIO_GPU_RESP_OK_NODATA, VIRTIO_GPU_TEXTURE_2D,
},
renderer::Renderer,
testutils::{create_vring, TestingDescChainArgs},
Expand Down Expand Up @@ -1114,6 +1117,16 @@ mod tests {
.return_once(|_, _, _| Ok(OkNoData));
});
assert_matches!(result, Ok(OkNoData));

let cmd = GpuCommand::ResourceAssignUuid(virtio_gpu_resource_assign_uuid::default());
let result = test_cmd(cmd, |g| {
g.expect_resource_assign_uuid().return_once(|_| {
Ok(GpuResponse::OkResourceUuid {
uuid: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
})
});
});
assert_matches!(result, Ok(GpuResponse::OkResourceUuid { .. }));
}

fn create_control_vring(
Expand Down Expand Up @@ -1421,6 +1434,43 @@ mod tests {
assert_eq!(backend.features() & (1 << VIRTIO_GPU_F_EDID), 0);
}

#[cfg(feature = "backend-virgl")]
#[test]
fn test_resource_uuid_assignment() {
let (_, mem) = init();
let config = GpuConfigBuilder::default()
.set_gpu_mode(GpuMode::VirglRenderer)
.set_capset(GpuCapset::VIRGL)
.set_flags(GpuFlags::default())
.build()
.unwrap();

let (control_vring, _, _) = create_control_vring(&mem, &[]);
let mut adapter = VirglRendererAdapter::new(&control_vring, &config, None).unwrap();

let resource_id = 42;
let create_req = ResourceCreate3d {
target: VIRTIO_GPU_TEXTURE_2D,
format: VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM,
bind: VIRTIO_GPU_BIND_RENDER_TARGET,
width: 1024,
height: 768,
depth: 1,
array_size: 0,
last_level: 0,
nr_samples: 0,
flags: 0,
};
adapter.resource_create_3d(resource_id, create_req).unwrap();

let uuid = match adapter.resource_assign_uuid(resource_id).unwrap() {
GpuResponse::OkResourceUuid { uuid } => uuid,
other => panic!("Expected OkResourceUuid, got {:?}", other),
};

assert_ne!(uuid, [0u8; 16], "UUID should not be all zeros");
}

rusty_fork_test! {
#[test]
fn test_verify_backend() {
Expand All @@ -1433,7 +1483,7 @@ mod tests {

assert_eq!(backend.num_queues(), NUM_QUEUES);
assert_eq!(backend.max_queue_size(), QUEUE_SIZE);
assert_eq!(backend.features(), 0x0101_7100_001B);
assert_eq!(backend.features(), 0x0101_7100_001F);
assert_eq!(
backend.protocol_features(),
VhostUserProtocolFeatures::CONFIG | VhostUserProtocolFeatures::MQ
Expand Down