public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: edk2-devel-01 <edk2-devel@ml01.01.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Jordan Justen <jordan.l.justen@intel.com>
Subject: [PATCH 09/11] OvmfPkg/VirtioGpuDxe: provide functions for sending VirtIo GPU commands
Date: Fri, 19 Aug 2016 14:49:30 +0200	[thread overview]
Message-ID: <20160819124932.29711-10-lersek@redhat.com> (raw)
In-Reply-To: <20160819124932.29711-1-lersek@redhat.com>

In this patch we add a "workhorse" function called VirtioGpuSendCommand(),
and implement seven simple RPCs atop, for the command types listed in
"OvmfPkg/Include/IndustryStandard/VirtioGpu.h".

These functions will be called by our EFI_GRAPHICS_OUTPUT_PROTOCOL
implementation.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Ref: https://tianocore.acgmultimedia.com/show_bug.cgi?id=66
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/VirtioGpuDxe/VirtioGpu.h |  93 ++++++
 OvmfPkg/VirtioGpuDxe/Commands.c  | 347 +++++++++++++++++++-
 2 files changed, 439 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/VirtioGpuDxe/VirtioGpu.h b/OvmfPkg/VirtioGpuDxe/VirtioGpu.h
index 97767dba709f..f8839922487c 100644
--- a/OvmfPkg/VirtioGpuDxe/VirtioGpu.h
+++ b/OvmfPkg/VirtioGpuDxe/VirtioGpu.h
@@ -14,12 +14,13 @@
 
 **/
 
 #ifndef _VIRTIO_GPU_DXE_H_
 #define _VIRTIO_GPU_DXE_H_
 
+#include <IndustryStandard/VirtioGpu.h>
 #include <Library/DebugLib.h>
 #include <Library/UefiLib.h>
 #include <Protocol/VirtioDevice.h>
 
 //
 // Forward declaration of VGPU_GOP.
@@ -56,12 +57,17 @@ typedef struct {
   //
   // Event to be signaled at ExitBootServices().
   //
   EFI_EVENT                ExitBoot;
 
   //
+  // Common running counter for all VirtIo GPU requests that ask for fencing.
+  //
+  UINT64                   FenceId;
+
+  //
   // The Child field references the GOP wrapper structure. If this pointer is
   // NULL, then the hybrid driver has bound (i.e., started) the
   // VIRTIO_DEVICE_PROTOCOL controller without producing the child GOP
   // controller (that is, after Start() was called with RemainingDevicePath
   // pointing to and End of Device Path node). Child can be created and
   // destroyed, even repeatedly, independently of VGPU_DEV.
@@ -168,7 +174,94 @@ VOID
 EFIAPI
 VirtioGpuExitBoot (
   IN EFI_EVENT Event,
   IN VOID      *Context
   );
 
+/**
+  The following functions send requests to the VirtIo GPU device model, await
+  the answer from the host, and return a status. They share the following
+  interface details:
+
+  @param[in,out] VgpuDev  The VGPU_DEV object that represents the VirtIo GPU
+                          device. The caller is responsible to have
+                          successfully invoked VirtioGpuInit() on VgpuDev
+                          previously, while VirtioGpuUninit() must not have
+                          been called on VgpuDev.
+
+  @retval EFI_INVALID_PARAMETER  Invalid command-specific parameters were
+                                 detected by this driver.
+
+  @retval EFI_SUCCESS            Operation successful.
+
+  @retval EFI_DEVICE_ERROR       The host rejected the request. The host error
+                                 code has been logged on the EFI_D_ERROR level.
+
+  @return                        Codes for unexpected errors in VirtIo
+                                 messaging.
+
+  For the command-specific parameters, please consult the GPU Device section of
+  the VirtIo 1.0 specification (see references in
+  "OvmfPkg/Include/IndustryStandard/VirtioGpu.h").
+**/
+EFI_STATUS
+VirtioGpuResourceCreate2d (
+  IN OUT VGPU_DEV           *VgpuDev,
+  IN     UINT32             ResourceId,
+  IN     VIRTIO_GPU_FORMATS Format,
+  IN     UINT32             Width,
+  IN     UINT32             Height
+  );
+
+EFI_STATUS
+VirtioGpuResourceUnref (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   ResourceId
+  );
+
+EFI_STATUS
+VirtioGpuResourceAttachBacking (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   ResourceId,
+  IN     VOID     *FirstBackingPage,
+  IN     UINTN    NumberOfPages
+  );
+
+EFI_STATUS
+VirtioGpuResourceDetachBacking (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   ResourceId
+  );
+
+EFI_STATUS
+VirtioGpuSetScanout (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   X,
+  IN     UINT32   Y,
+  IN     UINT32   Width,
+  IN     UINT32   Height,
+  IN     UINT32   ScanoutId,
+  IN     UINT32   ResourceId
+  );
+
+EFI_STATUS
+VirtioGpuTransferToHost2d (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   X,
+  IN     UINT32   Y,
+  IN     UINT32   Width,
+  IN     UINT32   Height,
+  IN     UINT64   Offset,
+  IN     UINT32   ResourceId
+  );
+
+EFI_STATUS
+VirtioGpuResourceFlush (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   X,
+  IN     UINT32   Y,
+  IN     UINT32   Width,
+  IN     UINT32   Height,
+  IN     UINT32   ResourceId
+  );
+
 #endif // _VIRTIO_GPU_DXE_H_
diff --git a/OvmfPkg/VirtioGpuDxe/Commands.c b/OvmfPkg/VirtioGpuDxe/Commands.c
index 804de950ff24..b369dc3a7abc 100644
--- a/OvmfPkg/VirtioGpuDxe/Commands.c
+++ b/OvmfPkg/VirtioGpuDxe/Commands.c
@@ -11,13 +11,12 @@
 
   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 **/
 
-#include <IndustryStandard/VirtioGpu.h>
 #include <Library/VirtioLib.h>
 
 #include "VirtioGpu.h"
 
 /**
   Configure the VirtIo GPU device that underlies VgpuDev.
@@ -209,6 +208,352 @@ VirtioGpuExitBoot (
 {
   VGPU_DEV *VgpuDev;
 
   VgpuDev = Context;
   VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);
 }
+
+/**
+  Internal utility function that sends a request to the VirtIo GPU device
+  model, awaits the answer from the host, and returns a status.
+
+  @param[in,out] VgpuDev  The VGPU_DEV object that represents the VirtIo GPU
+                          device. The caller is responsible to have
+                          successfully invoked VirtioGpuInit() on VgpuDev
+                          previously, while VirtioGpuUninit() must not have
+                          been called on VgpuDev.
+
+  @param[in] RequestType  The type of the request. The caller is responsible
+                          for providing a VirtioGpuCmd* RequestType which, on
+                          success, elicits a VirtioGpuRespOkNodata response
+                          from the host.
+
+  @param[in] Fence        Whether to enable fencing for this request. Fencing
+                          forces the host to complete the command before
+                          producing a response. If Fence is TRUE, then
+                          VgpuDev->FenceId is consumed, and incremented.
+
+  @param[in,out] Header   Pointer to the caller-allocated request object. The
+                          request must start with VIRTIO_GPU_CONTROL_HEADER.
+                          This function overwrites all fields of Header before
+                          submitting the request to the host:
+
+                          - it sets Type from RequestType,
+
+                          - it sets Flags and FenceId based on Fence,
+
+                          - it zeroes CtxId and Padding.
+
+  @param[in] RequestSize  Size of the entire caller-allocated request object,
+                          including the leading VIRTIO_GPU_CONTROL_HEADER.
+
+  @retval EFI_SUCCESS            Operation successful.
+
+  @retval EFI_DEVICE_ERROR       The host rejected the request. The host error
+                                 code has been logged on the EFI_D_ERROR level.
+
+  @return                        Codes for unexpected errors in VirtIo
+                                 messaging.
+**/
+STATIC
+EFI_STATUS
+VirtioGpuSendCommand (
+  IN OUT VGPU_DEV                           *VgpuDev,
+  IN     VIRTIO_GPU_CONTROL_TYPE            RequestType,
+  IN     BOOLEAN                            Fence,
+  IN OUT volatile VIRTIO_GPU_CONTROL_HEADER *Header,
+  IN     UINTN                              RequestSize
+  )
+{
+  DESC_INDICES                       Indices;
+  volatile VIRTIO_GPU_CONTROL_HEADER Response;
+  EFI_STATUS                         Status;
+  UINT32                             ResponseSize;
+
+  //
+  // Initialize Header.
+  //
+  Header->Type      = RequestType;
+  if (Fence) {
+    Header->Flags   = VIRTIO_GPU_FLAG_FENCE;
+    Header->FenceId = VgpuDev->FenceId++;
+  } else {
+    Header->Flags   = 0;
+    Header->FenceId = 0;
+  }
+  Header->CtxId     = 0;
+  Header->Padding   = 0;
+
+  ASSERT (RequestSize >= sizeof *Header);
+
+  //
+  // Compose the descriptor chain.
+  //
+  VirtioPrepare (&VgpuDev->Ring, &Indices);
+  VirtioAppendDesc (&VgpuDev->Ring, (UINTN)Header, RequestSize,
+    VRING_DESC_F_NEXT, &Indices);
+  VirtioAppendDesc (&VgpuDev->Ring, (UINTN)&Response, sizeof Response,
+    VRING_DESC_F_WRITE, &Indices);
+
+  //
+  // Send the command.
+  //
+  Status = VirtioFlush (VgpuDev->VirtIo, VIRTIO_GPU_CONTROL_QUEUE,
+             &VgpuDev->Ring, &Indices, &ResponseSize);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Parse the response.
+  //
+  if (ResponseSize != sizeof Response) {
+    DEBUG ((EFI_D_ERROR, "%a: malformed response to Request=0x%x\n",
+      __FUNCTION__, (UINT32)RequestType));
+    return EFI_PROTOCOL_ERROR;
+  }
+
+  if (Response.Type == VirtioGpuRespOkNodata) {
+    return EFI_SUCCESS;
+  }
+
+  DEBUG ((EFI_D_ERROR, "%a: Request=0x%x Response=0x%x\n", __FUNCTION__,
+    (UINT32)RequestType, Response.Type));
+  return EFI_DEVICE_ERROR;
+}
+
+/**
+  The following functions send requests to the VirtIo GPU device model, await
+  the answer from the host, and return a status. They share the following
+  interface details:
+
+  @param[in,out] VgpuDev  The VGPU_DEV object that represents the VirtIo GPU
+                          device. The caller is responsible to have
+                          successfully invoked VirtioGpuInit() on VgpuDev
+                          previously, while VirtioGpuUninit() must not have
+                          been called on VgpuDev.
+
+  @retval EFI_INVALID_PARAMETER  Invalid command-specific parameters were
+                                 detected by this driver.
+
+  @retval EFI_SUCCESS            Operation successful.
+
+  @retval EFI_DEVICE_ERROR       The host rejected the request. The host error
+                                 code has been logged on the EFI_D_ERROR level.
+
+  @return                        Codes for unexpected errors in VirtIo
+                                 messaging.
+
+  For the command-specific parameters, please consult the GPU Device section of
+  the VirtIo 1.0 specification (see references in
+  "OvmfPkg/Include/IndustryStandard/VirtioGpu.h").
+**/
+EFI_STATUS
+VirtioGpuResourceCreate2d (
+  IN OUT VGPU_DEV           *VgpuDev,
+  IN     UINT32             ResourceId,
+  IN     VIRTIO_GPU_FORMATS Format,
+  IN     UINT32             Width,
+  IN     UINT32             Height
+  )
+{
+  volatile VIRTIO_GPU_RESOURCE_CREATE_2D Request;
+
+  if (ResourceId == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Request.ResourceId = ResourceId;
+  Request.Format     = (UINT32)Format;
+  Request.Width      = Width;
+  Request.Height     = Height;
+
+  return VirtioGpuSendCommand (
+           VgpuDev,
+           VirtioGpuCmdResourceCreate2d,
+           FALSE,                        // Fence
+           &Request.Header,
+           sizeof Request
+           );
+}
+
+EFI_STATUS
+VirtioGpuResourceUnref (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   ResourceId
+  )
+{
+  volatile VIRTIO_GPU_RESOURCE_UNREF Request;
+
+  if (ResourceId == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Request.ResourceId = ResourceId;
+  Request.Padding    = 0;
+
+  return VirtioGpuSendCommand (
+           VgpuDev,
+           VirtioGpuCmdResourceUnref,
+           FALSE,                     // Fence
+           &Request.Header,
+           sizeof Request
+           );
+}
+
+EFI_STATUS
+VirtioGpuResourceAttachBacking (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   ResourceId,
+  IN     VOID     *FirstBackingPage,
+  IN     UINTN    NumberOfPages
+  )
+{
+  volatile VIRTIO_GPU_RESOURCE_ATTACH_BACKING Request;
+
+  if (ResourceId == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Request.ResourceId    = ResourceId;
+  Request.NrEntries     = 1;
+  Request.Entry.Addr    = (UINTN)FirstBackingPage;
+  Request.Entry.Length  = (UINT32)EFI_PAGES_TO_SIZE (NumberOfPages);
+  Request.Entry.Padding = 0;
+
+  return VirtioGpuSendCommand (
+           VgpuDev,
+           VirtioGpuCmdResourceAttachBacking,
+           FALSE,                             // Fence
+           &Request.Header,
+           sizeof Request
+           );
+}
+
+EFI_STATUS
+VirtioGpuResourceDetachBacking (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   ResourceId
+  )
+{
+  volatile VIRTIO_GPU_RESOURCE_DETACH_BACKING Request;
+
+  if (ResourceId == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Request.ResourceId = ResourceId;
+  Request.Padding    = 0;
+
+  //
+  // In this case, we set Fence to TRUE, because after this function returns,
+  // the caller might reasonably want to repurpose the backing pages
+  // immediately. Thus we should ensure that the host releases all references
+  // to the backing pages before we return.
+  //
+  return VirtioGpuSendCommand (
+           VgpuDev,
+           VirtioGpuCmdResourceDetachBacking,
+           TRUE,                              // Fence
+           &Request.Header,
+           sizeof Request
+           );
+}
+
+EFI_STATUS
+VirtioGpuSetScanout (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   X,
+  IN     UINT32   Y,
+  IN     UINT32   Width,
+  IN     UINT32   Height,
+  IN     UINT32   ScanoutId,
+  IN     UINT32   ResourceId
+  )
+{
+  volatile VIRTIO_GPU_SET_SCANOUT Request;
+
+  //
+  // Unlike for most other commands, ResourceId=0 is valid; it
+  // is used to disable a scanout.
+  //
+  Request.Rectangle.X      = X;
+  Request.Rectangle.Y      = Y;
+  Request.Rectangle.Width  = Width;
+  Request.Rectangle.Height = Height;
+  Request.ScanoutId        = ScanoutId;
+  Request.ResourceId       = ResourceId;
+
+  return VirtioGpuSendCommand (
+           VgpuDev,
+           VirtioGpuCmdSetScanout,
+           FALSE,                  // Fence
+           &Request.Header,
+           sizeof Request
+           );
+}
+
+EFI_STATUS
+VirtioGpuTransferToHost2d (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   X,
+  IN     UINT32   Y,
+  IN     UINT32   Width,
+  IN     UINT32   Height,
+  IN     UINT64   Offset,
+  IN     UINT32   ResourceId
+  )
+{
+  volatile VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D Request;
+
+  if (ResourceId == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Request.Rectangle.X      = X;
+  Request.Rectangle.Y      = Y;
+  Request.Rectangle.Width  = Width;
+  Request.Rectangle.Height = Height;
+  Request.Offset           = Offset;
+  Request.ResourceId       = ResourceId;
+  Request.Padding          = 0;
+
+  return VirtioGpuSendCommand (
+           VgpuDev,
+           VirtioGpuCmdTransferToHost2d,
+           FALSE,                        // Fence
+           &Request.Header,
+           sizeof Request
+           );
+}
+
+EFI_STATUS
+VirtioGpuResourceFlush (
+  IN OUT VGPU_DEV *VgpuDev,
+  IN     UINT32   X,
+  IN     UINT32   Y,
+  IN     UINT32   Width,
+  IN     UINT32   Height,
+  IN     UINT32   ResourceId
+  )
+{
+  volatile VIRTIO_GPU_RESOURCE_FLUSH Request;
+
+  if (ResourceId == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Request.Rectangle.X      = X;
+  Request.Rectangle.Y      = Y;
+  Request.Rectangle.Width  = Width;
+  Request.Rectangle.Height = Height;
+  Request.ResourceId       = ResourceId;
+  Request.Padding          = 0;
+
+  return VirtioGpuSendCommand (
+           VgpuDev,
+           VirtioGpuCmdResourceFlush,
+           FALSE,                     // Fence
+           &Request.Header,
+           sizeof Request
+           );
+}
-- 
2.9.2




  parent reply	other threads:[~2016-08-19 12:49 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-19 12:49 [PATCH 00/11] OvmfPkg, ArmVirtPkg: GOP driver for the VirtIo GPU (virtio-gpu-pci) Laszlo Ersek
2016-08-19 12:49 ` [PATCH 01/11] OvmfPkg/QemuVideoDxe: don't incorrectly bind virtio-gpu-pci Laszlo Ersek
2016-08-19 12:49 ` [PATCH 02/11] OvmfPkg/Virtio10Dxe: don't bind virtio-vga Laszlo Ersek
2016-08-19 12:49 ` [PATCH 03/11] OvmfPkg/PlatformBootManagerLib: relax device class requirement for ConOut Laszlo Ersek
2016-08-19 12:49 ` [PATCH 04/11] OvmfPkg/IndustryStandard: add type definitions for the virtio GPU device Laszlo Ersek
2016-08-19 12:49 ` [PATCH 05/11] OvmfPkg/VirtioGpuDxe: introduce with Component Name 2 and Driver Binding Laszlo Ersek
2016-08-19 12:49 ` [PATCH 06/11] OvmfPkg: include VirtioGpuDxe in the platform DSC/FDF files Laszlo Ersek
2016-08-19 12:49 ` [PATCH 07/11] ArmVirtPkg/ArmVirtQemu: " Laszlo Ersek
2016-08-19 13:14   ` Ard Biesheuvel
2016-08-19 12:49 ` [PATCH 08/11] OvmfPkg/VirtioGpuDxe: initialize and tear down VirtIo GPU device Laszlo Ersek
2016-08-19 12:49 ` Laszlo Ersek [this message]
2016-08-19 12:49 ` [PATCH 10/11] OvmfPkg/VirtioGpuDxe: implement EFI_GRAPHICS_OUTPUT_PROTOCOL Laszlo Ersek
2016-08-19 12:49 ` [PATCH 11/11] ArmVirtPkg: remove PcdKludgeMapPciMmioAsCached Laszlo Ersek
2016-08-19 13:16   ` Ard Biesheuvel
2016-08-19 13:06 ` [PATCH 00/11] OvmfPkg, ArmVirtPkg: GOP driver for the VirtIo GPU (virtio-gpu-pci) Ard Biesheuvel
2016-08-19 14:25   ` Laszlo Ersek
2016-08-31 20:43     ` Jordan Justen
2016-09-01  7:44       ` Ard Biesheuvel
2016-09-01 16:48         ` Laszlo Ersek
2016-09-01 16:29       ` Laszlo Ersek
2016-09-01 18:03         ` Jordan Justen
2016-09-01 18:46           ` Laszlo Ersek
2016-09-01 19:52             ` Jordan Justen
2016-09-01 20:23               ` Ard Biesheuvel
2016-09-01 20:26                 ` Ard Biesheuvel
2016-09-01 20:52                 ` Jordan Justen
2016-09-01 20:44               ` Laszlo Ersek
2016-09-05 14:17               ` Gerd Hoffmann
2016-08-30 15:07 ` Laszlo Ersek
2016-09-01 20:32 ` Jordan Justen
2016-09-01 21:07   ` Laszlo Ersek
2016-09-01 22:02 ` Laszlo Ersek
     [not found]   ` <57CD6463.90903@suse.de>
2016-09-05 12:56     ` Laszlo Ersek
     [not found]       ` <57CD6C25.7000406@suse.de>
2016-09-05 13:17         ` Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160819124932.29711-10-lersek@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox