public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: edk2-devel-01 <edk2-devel@lists.01.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Brijesh Singh <brijesh.singh@amd.com>,
	Jordan Justen <jordan.l.justen@intel.com>,
	Tom Lendacky <thomas.lendacky@amd.com>
Subject: [PATCH 2/6] OvmfPkg/VirtioGpuDxe: map virtio GPU command objects to device addresses
Date: Mon, 28 Aug 2017 15:24:32 +0200	[thread overview]
Message-ID: <20170828132436.15933-3-lersek@redhat.com> (raw)
In-Reply-To: <20170828132436.15933-1-lersek@redhat.com>

Every virtio GPU command used by VirtioGpuDxe is synchronous and formatted
as a two-descriptor chain: request, response. The internal workhorse
function that all the command-specific functions call for such messaging
is VirtioGpuSendCommand().

In VirtioGpuSendCommand(), map the request from system memory to bus
master device address for BusMasterRead operation, and map the response
from system memory to bus master device address for BusMasterWrite
operation.

Pass the bus master device addresses to VirtioAppendDesc(). (See also
commit 4b725858de68, "OvmfPkg/VirtioLib: change the parameter of
VirtioAppendDesc() to UINT64", 2017-08-23.)

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/VirtioGpuDxe/Commands.c | 83 ++++++++++++++++++--
 1 file changed, 75 insertions(+), 8 deletions(-)

diff --git a/OvmfPkg/VirtioGpuDxe/Commands.c b/OvmfPkg/VirtioGpuDxe/Commands.c
index 4e19bac606ee..bdedea1df6a7 100644
--- a/OvmfPkg/VirtioGpuDxe/Commands.c
+++ b/OvmfPkg/VirtioGpuDxe/Commands.c
@@ -229,148 +229,215 @@ EFIAPI
 VirtioGpuExitBoot (
   IN EFI_EVENT Event,
   IN VOID      *Context
   )
 {
   VGPU_DEV *VgpuDev;
 
   VgpuDev = Context;
   VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);
   VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, VgpuDev->RingMap);
 }
 
 /**
   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.
+                                 messaging, or request/response
+                                 mapping/unmapping.
 **/
 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;
+  EFI_PHYSICAL_ADDRESS               RequestDeviceAddress;
+  VOID                               *RequestMap;
+  EFI_PHYSICAL_ADDRESS               ResponseDeviceAddress;
+  VOID                               *ResponseMap;
 
   //
   // 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);
   ASSERT (RequestSize <= MAX_UINT32);
 
+  //
+  // Map request and response to bus master device addresses.
+  //
+  Status = VirtioMapAllBytesInSharedBuffer (
+             VgpuDev->VirtIo,
+             VirtioOperationBusMasterRead,
+             (VOID *)Header,
+             RequestSize,
+             &RequestDeviceAddress,
+             &RequestMap
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  Status = VirtioMapAllBytesInSharedBuffer (
+             VgpuDev->VirtIo,
+             VirtioOperationBusMasterWrite,
+             (VOID *)&Response,
+             sizeof Response,
+             &ResponseDeviceAddress,
+             &ResponseMap
+             );
+  if (EFI_ERROR (Status)) {
+    goto UnmapRequest;
+  }
+
   //
   // Compose the descriptor chain.
   //
   VirtioPrepare (&VgpuDev->Ring, &Indices);
-  VirtioAppendDesc (&VgpuDev->Ring, (UINTN)Header, (UINT32)RequestSize,
-    VRING_DESC_F_NEXT, &Indices);
-  VirtioAppendDesc (&VgpuDev->Ring, (UINTN)&Response, sizeof Response,
-    VRING_DESC_F_WRITE, &Indices);
+  VirtioAppendDesc (
+    &VgpuDev->Ring,
+    RequestDeviceAddress,
+    (UINT32)RequestSize,
+    VRING_DESC_F_NEXT,
+    &Indices
+    );
+  VirtioAppendDesc (
+    &VgpuDev->Ring,
+    ResponseDeviceAddress,
+    (UINT32)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;
+    goto UnmapResponse;
   }
 
   //
-  // Parse the response.
+  // Verify response size.
   //
   if (ResponseSize != sizeof Response) {
     DEBUG ((EFI_D_ERROR, "%a: malformed response to Request=0x%x\n",
       __FUNCTION__, (UINT32)RequestType));
-    return EFI_PROTOCOL_ERROR;
+    Status = EFI_PROTOCOL_ERROR;
+    goto UnmapResponse;
   }
 
+  //
+  // Unmap response and request, in reverse order of mapping. On error, the
+  // respective mapping is invalidated anyway, only the data may not have been
+  // committed to system memory (in case of VirtioOperationBusMasterWrite).
+  //
+  Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);
+  if (EFI_ERROR (Status)) {
+    goto UnmapRequest;
+  }
+  Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Parse the response.
+  //
   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;
+
+UnmapResponse:
+  VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);
+
+UnmapRequest:
+  VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);
+
+  return Status;
 }
 
 /**
   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").
 **/
-- 
2.14.1.3.gb7cf6e02401b




  parent reply	other threads:[~2017-08-28 13:22 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-28 13:24 [PATCH 0/6] OvmfPkg/VirtioGpuDxe: map system memory addresses to device addresses Laszlo Ersek
2017-08-28 13:24 ` [PATCH 1/6] OvmfPkg/VirtioGpuDxe: map VRING for bus master common buffer operation Laszlo Ersek
2017-08-28 13:24 ` Laszlo Ersek [this message]
2017-08-28 13:24 ` [PATCH 3/6] OvmfPkg/VirtioGpuDxe: take EFI_PHYSICAL_ADDRESS in ResourceAttachBacking() Laszlo Ersek
2017-08-28 13:24 ` [PATCH 4/6] OvmfPkg/VirtioGpuDxe: helpers for backing store (de)allocation+(un)mapping Laszlo Ersek
2017-08-28 13:24 ` [PATCH 5/6] OvmfPkg/VirtioGpuDxe: map backing store to bus master device address Laszlo Ersek
2017-08-28 13:24 ` [PATCH 6/6] OvmfPkg/VirtioGpuDxe: negotiate VIRTIO_F_IOMMU_PLATFORM Laszlo Ersek
2017-08-29 23:02 ` [PATCH 0/6] OvmfPkg/VirtioGpuDxe: map system memory addresses to device addresses Laszlo Ersek
2017-08-30 15:47   ` Brijesh Singh
2017-08-30 16:15     ` Laszlo Ersek
2017-09-01 12:31     ` 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=20170828132436.15933-3-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