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 <zachr@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Tested-by: Gurchetan Singh <gurchetansingh@chromium.org>
Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
This commit is contained in:
Gurchetan Singh 2019-04-23 10:27:49 -07:00 committed by Commit Bot
parent 144c279d28
commit 5b636babc1
4 changed files with 119 additions and 2 deletions

View file

@ -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<u8>,
mut response: Vec<u8>,
) -> 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
}
}
}
}

View file

@ -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
}
}
}
}

View file

@ -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<u8>,
}
/// 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<GpuResponsePlaneInfo>,
},
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,
}
}

View file

@ -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<u8>) -> 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.