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
next prev 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