public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Brijesh Singh <brijesh.singh@amd.com>
To: edk2-devel@lists.01.org
Cc: Tom Lendacky <thomas.lendacky@amd.com>,
	Brijesh Singh <brijesh.singh@amd.com>,
	Jordan Justen <jordan.l.justen@intel.com>,
	Laszlo Ersek <lersek@redhat.com>,
	Jason Wang <jasowang@redhat.com>,
	"Michael S . Tsirkin" <mst@redhat.com>
Subject: [RFC v1 3/3] OvmfPkg/VirtioBlkDxe: Add VIRITO_F_IOMMU_PLATFORM support
Date: Wed, 19 Jul 2017 18:09:11 -0400	[thread overview]
Message-ID: <1500502151-13508-4-git-send-email-brijesh.singh@amd.com> (raw)
In-Reply-To: <1500502151-13508-1-git-send-email-brijesh.singh@amd.com>

When VIRTIO_F_IOMMU_PLATFORM feature bit in set then try locating
IOMMU protocol. If IOMMU protocol is available, then use the IOMMU
protocols functions to allocate, free, map and unmap the host buffer
to device buffer.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/VirtioBlkDxe/VirtioBlk.inf |   4 +
 OvmfPkg/VirtioBlkDxe/VirtioBlk.c   | 125 ++++++++++++++++++--
 2 files changed, 118 insertions(+), 11 deletions(-)

diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
index 53d5a164a0b8..12577c5f700f 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
@@ -41,3 +41,7 @@ [LibraryClasses]
 [Protocols]
   gEfiBlockIoProtocolGuid   ## BY_START
   gVirtioDeviceProtocolGuid ## TO_START
+  gEdkiiIoMmuProtocolGuid   ## SOMETIMES_CONSUMES
+
+[Depex]
+  gEdkiiIoMmuProtocolGuid OR gIoMmuAbsentProtocolGuid
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index 3ce72281c204..f78052c4ecc0 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -23,6 +23,8 @@
 
 **/
 
+#include <Protocol/IoMmu.h>
+
 #include <IndustryStandard/VirtioBlk.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
@@ -33,6 +35,8 @@
 
 #include "VirtioBlk.h"
 
+STATIC EDKII_IOMMU_PROTOCOL        *mIoMmuProtocol;
+
 /**
 
   Convenience macros to read and write region 0 IO space elements of the
@@ -247,13 +251,49 @@ SynchronousRequest (
   )
 {
   UINT32                  BlockSize;
-  volatile VIRTIO_BLK_REQ Request;
-  volatile UINT8          HostStatus;
+  volatile VIRTIO_BLK_REQ LocalRequest;
+  volatile UINT8          LocalHostStatus;
+  volatile VIRTIO_BLK_REQ *Request;
+  volatile UINT8          *HostStatus;
   DESC_INDICES            Indices;
+  VOID                    *IommuBuffer;
+  UINT32                  NumPages;
+  VOID                    *Mapping;
+  EFI_STATUS              Status;
+  EFI_PHYSICAL_ADDRESS    DeviceBuffer;
 
   BlockSize = Dev->BlockIoMedia.BlockSize;
 
   //
+  // set NumPages to suppress incorrect compiler/analyzer warnings
+  //
+  NumPages = 0;
+
+  //
+  // If IOMMU platform is enabled for this device then allocate Request and
+  // HostStatus variable dynamically using IOMMU allocator
+  //
+  if (mIoMmuProtocol) {
+    EFI_STATUS  Status;
+
+    NumPages = (UINT32)EFI_SIZE_TO_PAGES (sizeof (*Request) + sizeof (*HostStatus));
+    Status = mIoMmuProtocol->AllocateBuffer (mIoMmuProtocol, 0,
+                                EfiBootServicesData, NumPages, &IommuBuffer,
+                                EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    Request = IommuBuffer;
+    HostStatus = IommuBuffer + sizeof(*Request);
+  } else {
+    Request = &LocalRequest;
+    HostStatus = &LocalHostStatus;
+    IommuBuffer = NULL;
+    Mapping = NULL;
+  }
+
+  //
   // ensured by VirtioBlkInit()
   //
   ASSERT (BlockSize > 0);
@@ -268,18 +308,18 @@ SynchronousRequest (
   // Prepare virtio-blk request header, setting zero size for flush.
   // IO Priority is homogeneously 0.
   //
-  Request.Type   = RequestIsWrite ?
+  Request->Type   = RequestIsWrite ?
                    (BufferSize == 0 ? VIRTIO_BLK_T_FLUSH : VIRTIO_BLK_T_OUT) :
                    VIRTIO_BLK_T_IN;
-  Request.IoPrio = 0;
-  Request.Sector = MultU64x32(Lba, BlockSize / 512);
+  Request->IoPrio = 0;
+  Request->Sector = MultU64x32(Lba, BlockSize / 512);
 
   VirtioPrepare (&Dev->Ring, &Indices);
 
   //
   // preset a host status for ourselves that we do not accept as success
   //
-  HostStatus = VIRTIO_BLK_S_IOERR;
+  *HostStatus = VIRTIO_BLK_S_IOERR;
 
   //
   // ensured by VirtioBlkInit() -- this predicate, in combination with the
@@ -290,7 +330,7 @@ SynchronousRequest (
   //
   // virtio-blk header in first desc
   //
-  VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,
+  VirtioAppendDesc (&Dev->Ring, (UINTN) Request, sizeof *Request,
     VRING_DESC_F_NEXT, &Indices);
 
   //
@@ -308,6 +348,42 @@ SynchronousRequest (
     ASSERT (BufferSize <= SIZE_1GB);
 
     //
+    // When IOMMU platform is enabled, map the host buffer to device
+    //
+    if (mIoMmuProtocol) {
+      EDKII_IOMMU_OPERATION   Operation;
+      UINTN                   NumBytes;
+
+      NumBytes = BufferSize;
+
+      if (RequestIsWrite) {
+        Operation = EdkiiIoMmuOperationBusMasterRead;
+      } else {
+        Operation = EdkiiIoMmuOperationBusMasterWrite;
+      }
+
+      Status = mIoMmuProtocol->Map (mIoMmuProtocol, Operation, (VOID *)Buffer,
+                        &NumBytes, &DeviceBuffer, &Mapping);
+      if (EFI_ERROR (Status)) {
+        Status = EFI_DEVICE_ERROR;
+        goto HandleExit;
+      }
+
+      //
+      // Verify that we are able to map the required size
+      //
+      if (NumBytes < BufferSize) {
+        DEBUG ((DEBUG_ERROR, "%a: request %d got %d\n", __FUNCTION__,
+              BufferSize, NumBytes));
+
+        Status = EFI_DEVICE_ERROR;
+        mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping);
+        goto HandleExit;
+      }
+      Buffer = (VOID *)DeviceBuffer;
+    }
+
+    //
     // VRING_DESC_F_WRITE is interpreted from the host's point of view.
     //
     VirtioAppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,
@@ -318,7 +394,7 @@ SynchronousRequest (
   //
   // host status in last (second or third) desc
   //
-  VirtioAppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,
+  VirtioAppendDesc (&Dev->Ring, (UINTN) HostStatus, sizeof *HostStatus,
     VRING_DESC_F_WRITE, &Indices);
 
   //
@@ -326,11 +402,23 @@ SynchronousRequest (
   //
   if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices,
         NULL) == EFI_SUCCESS &&
-      HostStatus == VIRTIO_BLK_S_OK) {
-    return EFI_SUCCESS;
+      *HostStatus == VIRTIO_BLK_S_OK) {
+    Status = EFI_SUCCESS;
+    goto HandleExit;
   }
 
-  return EFI_DEVICE_ERROR;
+  Status = EFI_DEVICE_ERROR;
+
+HandleExit:
+  if (Mapping) {
+    mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping);
+  }
+
+  if (IommuBuffer) {
+    mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, IommuBuffer);
+  }
+
+  return Status;
 }
 
 
@@ -692,6 +780,21 @@ VirtioBlkInit (
     }
   }
 
+  //
+  // If IOMMU_PLATFORM feature is requested then try to locate IOMMU
+  // protocol before acking that we support IOMMU_PLATFORM feature
+  //
+  if (Features & VIRTIO_F_IOMMU_PLATFORM) {
+    Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "%a: Failed to locate IOMMU protocol\n", __FUNCTION__));
+      goto Failed;
+    }
+
+    Features &= VIRTIO_F_IOMMU_PLATFORM;
+    VirtioRingUseIommu (&Dev->Ring, mIoMmuProtocol);
+  }
+
   Features &= VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_TOPOLOGY | VIRTIO_BLK_F_RO |
               VIRTIO_BLK_F_FLUSH | VIRTIO_F_VERSION_1;
 
-- 
2.7.4



  parent reply	other threads:[~2017-07-19 22:07 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-19 22:09 [RFC v1 0/3] Add VIRTIO_F_IOMMU_PLATFORM support Brijesh Singh
2017-07-19 22:09 ` [RFC v1 1/3] OvmfPkg/Include/Virtio10: Define VIRTIO_F_IOMMU_PLATFORM feature bit Brijesh Singh
2017-07-19 22:09 ` [RFC v1 2/3] OvmfPkg/VirtioLib: Add IOMMU_PLATFORM support Brijesh Singh
2017-07-19 22:09 ` Brijesh Singh [this message]
     [not found] ` <62320c1a-0cec-947c-8c63-5eb0416e4e33@redhat.com>
2017-07-21 11:17   ` [RFC v1 0/3] Add VIRTIO_F_IOMMU_PLATFORM support Brijesh Singh
     [not found]     ` <20170722024318-mutt-send-email-mst@kernel.org>
2017-07-24  8:25       ` Gerd Hoffmann
2017-07-25 18:17 ` Laszlo Ersek
2017-07-25 23:42   ` Brijesh Singh
     [not found]   ` <904dae9f-e515-01ba-e16f-6561616c78af@redhat.com>
2017-07-26 15:30     ` Laszlo Ersek
2017-07-27 14:21   ` Brijesh Singh
2017-07-27 17:16     ` Laszlo Ersek
2017-07-27 17:56       ` Ard Biesheuvel
2017-07-27 19:00         ` Brijesh Singh
2017-07-27 20:55           ` Brijesh Singh
2017-07-27 21:31             ` Ard Biesheuvel
2017-07-27 21:38               ` Andrew Fish
2017-07-27 22:13                 ` Brijesh Singh
2017-07-27 22:10               ` Brijesh Singh
2017-07-28  8:39                 ` Ard Biesheuvel
2017-07-28 15:27                   ` Laszlo Ersek
2017-07-28 13:38           ` Laszlo Ersek
2017-07-28 16:00             ` Brijesh Singh
2017-07-28 16:16               ` Laszlo Ersek
2017-07-28 19:21               ` Laszlo Ersek
2017-07-28 19:59               ` Laszlo Ersek
2017-07-29  0:52                 ` Brijesh Singh
2017-07-29  1:37                   ` Brijesh Singh
2017-07-31 18:20                     ` 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=1500502151-13508-4-git-send-email-brijesh.singh@amd.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