summary refs log tree commit diff
diff options
context:
space:
mode:
authorGurchetan Singh <gurchetansingh@chromium.org>2019-04-23 10:27:49 -0700
committerCommit Bot <commit-bot@chromium.org>2019-10-01 07:53:33 +0000
commit5b636babc1e83b7187ef72bd85b3a3bdc2e5d03f (patch)
tree1c856e04303e3c2882a140d2be45015bdb621b2e
parent144c279d281cb2e69caeb8504ff7267d268c4561 (diff)
downloadcrosvm-5b636babc1e83b7187ef72bd85b3a3bdc2e5d03f.tar
crosvm-5b636babc1e83b7187ef72bd85b3a3bdc2e5d03f.tar.gz
crosvm-5b636babc1e83b7187ef72bd85b3a3bdc2e5d03f.tar.bz2
crosvm-5b636babc1e83b7187ef72bd85b3a3bdc2e5d03f.tar.lz
crosvm-5b636babc1e83b7187ef72bd85b3a3bdc2e5d03f.tar.xz
crosvm-5b636babc1e83b7187ef72bd85b3a3bdc2e5d03f.tar.zst
crosvm-5b636babc1e83b7187ef72bd85b3a3bdc2e5d03f.zip
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>
-rw-r--r--devices/src/virtio/gpu/backend.rs28
-rw-r--r--devices/src/virtio/gpu/mod.rs23
-rw-r--r--devices/src/virtio/gpu/protocol.rs52
-rw-r--r--gpu_renderer/src/lib.rs18
4 files changed, 119 insertions, 2 deletions
diff --git a/devices/src/virtio/gpu/backend.rs b/devices/src/virtio/gpu/backend.rs
index 9415226..4cfac7a 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<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
+            }
+        }
+    }
 }
diff --git a/devices/src/virtio/gpu/mod.rs b/devices/src/virtio/gpu/mod.rs
index b229cb5..2ad1f2e 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 26d7168..9c3b112 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<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,
         }
     }
diff --git a/gpu_renderer/src/lib.rs b/gpu_renderer/src/lib.rs
index c8f6f84..42df26a 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<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.