From 5b636babc1e83b7187ef72bd85b3a3bdc2e5d03f Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Tue, 23 Apr 2019 10:27:49 -0700 Subject: [PATCH] virtio-gpu: handle VIRTIO_GPU_CMD_ALLOCATION_METADATA Designed to return metadata to the guest. BUG=chromium:924405 TEST=compile Change-Id: Ic04a0bbb6b0a5bb6d08314371181f256eb7230df Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1591464 Reviewed-by: Zach Reizner Tested-by: kokoro Tested-by: Gurchetan Singh Commit-Queue: Gurchetan Singh --- devices/src/virtio/gpu/backend.rs | 28 ++++++++++++++-- devices/src/virtio/gpu/mod.rs | 23 +++++++++++++ devices/src/virtio/gpu/protocol.rs | 52 ++++++++++++++++++++++++++++++ gpu_renderer/src/lib.rs | 18 +++++++++++ 4 files changed, 119 insertions(+), 2 deletions(-) diff --git a/devices/src/virtio/gpu/backend.rs b/devices/src/virtio/gpu/backend.rs index 9415226c6d..4cfac7a0d3 100644 --- a/devices/src/virtio/gpu/backend.rs +++ b/devices/src/virtio/gpu/backend.rs @@ -23,8 +23,8 @@ use gpu_renderer::{ }; use super::protocol::{ - GpuResponse, GpuResponsePlaneInfo, VIRTIO_GPU_CAPSET3, VIRTIO_GPU_CAPSET_VIRGL, - VIRTIO_GPU_CAPSET_VIRGL2, + AllocationMetadataResponse, GpuResponse, GpuResponsePlaneInfo, VIRTIO_GPU_CAPSET3, + VIRTIO_GPU_CAPSET_VIRGL, VIRTIO_GPU_CAPSET_VIRGL2, }; use crate::virtio::resource_bridge::*; use vm_control::VmMemoryControlRequestSocket; @@ -778,4 +778,28 @@ impl Backend { pub fn force_ctx_0(&mut self) { self.renderer.force_ctx_0(); } + + pub fn allocation_metadata( + &mut self, + request_id: u32, + request: Vec, + mut response: Vec, + ) -> GpuResponse { + let res = self.renderer.allocation_metadata(&request, &mut response); + + match res { + Ok(_) => { + let res_info = AllocationMetadataResponse { + request_id, + response, + }; + + GpuResponse::OkAllocationMetadata { res_info } + } + Err(_) => { + error!("failed to get metadata"); + GpuResponse::ErrUnspec + } + } + } } diff --git a/devices/src/virtio/gpu/mod.rs b/devices/src/virtio/gpu/mod.rs index b229cb58c0..2ad1f2e94d 100644 --- a/devices/src/virtio/gpu/mod.rs +++ b/devices/src/virtio/gpu/mod.rs @@ -262,6 +262,29 @@ impl Frontend { GpuResponse::OkNoData } } + GpuCommand::AllocationMetadata(info) => { + if reader.available_bytes() != 0 { + let id = info.request_id.to_native(); + let request_size = info.request_size.to_native(); + let response_size = info.response_size.to_native(); + if request_size > VIRTIO_GPU_MAX_BLOB_ARGUMENT_SIZE + || response_size > VIRTIO_GPU_MAX_BLOB_ARGUMENT_SIZE + { + return GpuResponse::ErrUnspec; + } + + let mut request_buf = vec![0; request_size as usize]; + let response_buf = vec![0; response_size as usize]; + if reader.read(&mut request_buf[..]).is_ok() { + self.backend + .allocation_metadata(id, request_buf, response_buf) + } else { + GpuResponse::ErrInvalidParameter + } + } else { + GpuResponse::ErrUnspec + } + } } } diff --git a/devices/src/virtio/gpu/protocol.rs b/devices/src/virtio/gpu/protocol.rs index 26d7168ed5..9c3b11219a 100644 --- a/devices/src/virtio/gpu/protocol.rs +++ b/devices/src/virtio/gpu/protocol.rs @@ -84,6 +84,9 @@ pub const VIRTIO_GPU_CACHED: u32 = 1; pub const VIRTIO_GPU_WRITE_COMBINE: u32 = 2; pub const VIRTIO_GPU_UNCACHED: u32 = 3; +/* Limits on virtio-gpu stream (not upstreamed) */ +pub const VIRTIO_GPU_MAX_BLOB_ARGUMENT_SIZE: u32 = 4096; + pub fn virtio_gpu_cmd_str(cmd: u32) -> &'static str { match cmd { VIRTIO_GPU_CMD_GET_DISPLAY_INFO => "VIRTIO_GPU_CMD_GET_DISPLAY_INFO", @@ -489,6 +492,29 @@ pub struct virtio_gpu_config { unsafe impl DataInit for virtio_gpu_config {} +#[derive(Copy, Clone, Debug, Default)] +#[repr(C)] +pub struct virtio_gpu_allocation_metadata { + pub hdr: virtio_gpu_ctrl_hdr, + pub request_id: Le32, + pub padding: Le32, + pub request_size: Le32, + pub response_size: Le32, +} + +unsafe impl DataInit for virtio_gpu_allocation_metadata {} + +/* VIRTIO_GPU_RESP_OK_ALLOCATION_METADATA */ +#[derive(Copy, Clone, Debug, Default)] +#[repr(C)] +pub struct virtio_gpu_resp_allocation_metadata { + pub hdr: virtio_gpu_ctrl_hdr, + pub request_id: Le32, + pub response_size: Le32, +} + +unsafe impl DataInit for virtio_gpu_resp_allocation_metadata {} + /* simple formats for fbcon/X use */ pub const VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM: u32 = 1; pub const VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM: u32 = 2; @@ -520,6 +546,7 @@ pub enum GpuCommand { TransferToHost3d(virtio_gpu_transfer_host_3d), TransferFromHost3d(virtio_gpu_transfer_host_3d), CmdSubmit3d(virtio_gpu_cmd_submit), + AllocationMetadata(virtio_gpu_allocation_metadata), UpdateCursor(virtio_gpu_update_cursor), MoveCursor(virtio_gpu_update_cursor), } @@ -577,6 +604,7 @@ impl fmt::Debug for GpuCommand { TransferToHost3d(_info) => f.debug_struct("TransferToHost3d").finish(), TransferFromHost3d(_info) => f.debug_struct("TransferFromHost3d").finish(), CmdSubmit3d(_info) => f.debug_struct("CmdSubmit3d").finish(), + AllocationMetadata(_info) => f.debug_struct("AllocationMetadata").finish(), UpdateCursor(_info) => f.debug_struct("UpdateCursor").finish(), MoveCursor(_info) => f.debug_struct("MoveCursor").finish(), } @@ -607,6 +635,7 @@ impl GpuCommand { VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D => TransferToHost3d(cmd.read_obj()?), VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D => TransferFromHost3d(cmd.read_obj()?), VIRTIO_GPU_CMD_SUBMIT_3D => CmdSubmit3d(cmd.read_obj()?), + VIRTIO_GPU_CMD_ALLOCATION_METADATA => AllocationMetadata(cmd.read_obj()?), VIRTIO_GPU_CMD_UPDATE_CURSOR => UpdateCursor(cmd.read_obj()?), VIRTIO_GPU_CMD_MOVE_CURSOR => MoveCursor(cmd.read_obj()?), _ => return Err(GpuCommandDecodeError::InvalidType(hdr.type_.into())), @@ -635,6 +664,7 @@ impl GpuCommand { TransferToHost3d(info) => &info.hdr, TransferFromHost3d(info) => &info.hdr, CmdSubmit3d(info) => &info.hdr, + AllocationMetadata(info) => &info.hdr, UpdateCursor(info) => &info.hdr, MoveCursor(info) => &info.hdr, } @@ -647,6 +677,12 @@ pub struct GpuResponsePlaneInfo { pub offset: u32, } +#[derive(Default, Debug, PartialEq)] +pub struct AllocationMetadataResponse { + pub request_id: u32, + pub response: Vec, +} + /// A response to a `GpuCommand`. These correspond to `VIRTIO_GPU_RESP_*`. #[derive(Debug, PartialEq)] pub enum GpuResponse { @@ -662,6 +698,9 @@ pub enum GpuResponse { format_modifier: u64, plane_info: Vec, }, + OkAllocationMetadata { + res_info: AllocationMetadataResponse, + }, ErrUnspec, ErrOutOfMemory, ErrInvalidScanoutId, @@ -786,6 +825,17 @@ impl GpuResponse { size_of_val(&hdr) } } + GpuResponse::OkAllocationMetadata { ref res_info } => { + let resp_info = virtio_gpu_resp_allocation_metadata { + hdr, + request_id: Le32::from(res_info.request_id), + response_size: Le32::from(res_info.response.len() as u32), + }; + + resp.write_obj(resp_info)?; + resp.write(&res_info.response)?; + size_of_val(&resp_info) + res_info.response.len() + } _ => { resp.write_obj(hdr)?; size_of_val(&hdr) @@ -802,6 +852,7 @@ impl GpuResponse { GpuResponse::OkCapsetInfo { .. } => VIRTIO_GPU_RESP_OK_CAPSET_INFO, GpuResponse::OkCapset(_) => VIRTIO_GPU_RESP_OK_CAPSET, GpuResponse::OkResourcePlaneInfo { .. } => VIRTIO_GPU_RESP_OK_RESOURCE_PLANE_INFO, + GpuResponse::OkAllocationMetadata { .. } => VIRTIO_GPU_RESP_OK_ALLOCATION_METADATA, GpuResponse::ErrUnspec => VIRTIO_GPU_RESP_ERR_UNSPEC, GpuResponse::ErrOutOfMemory => VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY, GpuResponse::ErrInvalidScanoutId => VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID, @@ -819,6 +870,7 @@ impl GpuResponse { GpuResponse::OkCapsetInfo { .. } => true, GpuResponse::OkCapset(_) => true, GpuResponse::OkResourcePlaneInfo { .. } => true, + GpuResponse::OkAllocationMetadata { .. } => true, _ => false, } } diff --git a/gpu_renderer/src/lib.rs b/gpu_renderer/src/lib.rs index c8f6f84c65..42df26a74c 100644 --- a/gpu_renderer/src/lib.rs +++ b/gpu_renderer/src/lib.rs @@ -392,6 +392,24 @@ impl Renderer { pub fn force_ctx_0(&self) { unsafe { virgl_renderer_force_ctx_0() }; } + + #[allow(unused_variables)] + pub fn allocation_metadata(&self, request: &[u8], response: &mut Vec) -> Result<()> { + #[cfg(feature = "virtio-gpu-next")] + { + let ret = unsafe { + virgl_renderer_allocation_metadata( + request.as_ptr() as *const c_void, + response.as_mut_ptr() as *mut c_void, + request.len() as u32, + response.len() as u32, + ) + }; + ret_to_res(ret) + } + #[cfg(not(feature = "virtio-gpu-next"))] + Err(Error::Unsupported) + } } /// A context in which resources can be attached/detached and commands can be submitted.