[edk2] [RFC v1 2/3] OvmfPkg/VirtioLib: Add IOMMU_PLATFORM support

Brijesh Singh posted 3 patches 7 years, 5 months ago
[edk2] [RFC v1 2/3] OvmfPkg/VirtioLib: Add IOMMU_PLATFORM support
Posted by Brijesh Singh 7 years, 5 months ago
When iommu_platform is set, use IOMMU protocols buffer allocation
and free routines to allocate and free vring buffer (guest-host
communication 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/Library/VirtioLib/VirtioLib.inf      |  1 +
 OvmfPkg/VirtioBlkDxe/VirtioBlk.inf           |  1 +
 OvmfPkg/VirtioGpuDxe/VirtioGpu.inf           |  1 +
 OvmfPkg/VirtioNetDxe/VirtioNet.inf           |  1 +
 OvmfPkg/VirtioRngDxe/VirtioRng.inf           |  1 +
 OvmfPkg/VirtioScsiDxe/VirtioScsi.inf         |  1 +
 OvmfPkg/Include/IndustryStandard/Virtio095.h |  1 +
 OvmfPkg/Include/Library/VirtioLib.h          | 20 ++++
 OvmfPkg/Library/VirtioLib/VirtioLib.c        | 96 +++++++++++++++++++-
 9 files changed, 121 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.inf b/OvmfPkg/Library/VirtioLib/VirtioLib.inf
index fb5897a88ecf..6629d0d52b04 100644
--- a/OvmfPkg/Library/VirtioLib/VirtioLib.inf
+++ b/OvmfPkg/Library/VirtioLib/VirtioLib.inf
@@ -26,6 +26,7 @@ [Sources]
 
 [Packages]
   MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
index d5975b74eb05..53d5a164a0b8 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
@@ -26,6 +26,7 @@ [Sources]
 
 [Packages]
   MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
diff --git a/OvmfPkg/VirtioGpuDxe/VirtioGpu.inf b/OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
index 04bc2964c223..a6d4cbbd191a 100644
--- a/OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
+++ b/OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
@@ -31,6 +31,7 @@ [Sources]
 
 [Packages]
   MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.inf b/OvmfPkg/VirtioNetDxe/VirtioNet.inf
index a855ad4ac154..2b8996ed366e 100644
--- a/OvmfPkg/VirtioNetDxe/VirtioNet.inf
+++ b/OvmfPkg/VirtioNetDxe/VirtioNet.inf
@@ -42,6 +42,7 @@ [Sources]
 
 [Packages]
   MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.inf b/OvmfPkg/VirtioRngDxe/VirtioRng.inf
index 471beb37bc7f..898bfb7158c2 100644
--- a/OvmfPkg/VirtioRngDxe/VirtioRng.inf
+++ b/OvmfPkg/VirtioRngDxe/VirtioRng.inf
@@ -26,6 +26,7 @@ [Sources]
 
 [Packages]
   MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf b/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
index 75581123930b..082f9a12bb09 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
@@ -27,6 +27,7 @@ [Sources]
 
 [Packages]
   MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
diff --git a/OvmfPkg/Include/IndustryStandard/Virtio095.h b/OvmfPkg/Include/IndustryStandard/Virtio095.h
index 6bf77cb32075..c81b29c6d9d0 100644
--- a/OvmfPkg/Include/IndustryStandard/Virtio095.h
+++ b/OvmfPkg/Include/IndustryStandard/Virtio095.h
@@ -154,6 +154,7 @@ typedef struct {
   VRING_AVAIL         Avail;
   VRING_USED          Used;
   UINT16              QueueSize;
+  VOID                *Iommu;
 } VRING;
 
 //
diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
index 5badfb32917f..92a3d5e10f7b 100644
--- a/OvmfPkg/Include/Library/VirtioLib.h
+++ b/OvmfPkg/Include/Library/VirtioLib.h
@@ -17,10 +17,30 @@
 #ifndef _VIRTIO_LIB_H_
 #define _VIRTIO_LIB_H_
 
+#include <Protocol/IoMmu.h>
 #include <Protocol/VirtioDevice.h>
 
 #include <IndustryStandard/Virtio.h>
 
+/**
+
+  Configure a virtio ring to use IOMMU protocol
+
+  This function tells vring to use the given IOMMU protocol interface
+  for allocating and freeing the vring buffer (this guest-host communication
+  area)
+
+  @param[in]                   The virtio ring to set up.
+
+  @param[in]                   IOMMU protocol to use.
+
+**/
+VOID
+EFIAPI
+VirtioRingUseIommu (
+  IN VRING                  *Ring,
+  IN EDKII_IOMMU_PROTOCOL   *Iommu
+  );
 
 /**
 
diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
index 845f206369a3..d8fdb6310d52 100644
--- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
+++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
@@ -26,6 +26,69 @@
 
 /**
 
+  Configure a virtio ring to use IOMMU protocol
+
+  This function tells vring to use the given IOMMU protocol interface
+  for allocating and freeing the vring buffer (this guest-host communication
+  area)
+
+  @param[in]                   The virtio ring to set up.
+
+  @param[in]                   IOMMU protocol to use.
+
+**/
+VOID
+EFIAPI
+VirtioRingUseIommu (
+  IN VRING                  *Ring,
+  IN EDKII_IOMMU_PROTOCOL   *Iommu
+  )
+{
+  Ring->Iommu = Iommu;
+}
+
+/**
+
+  Allocate vring (the guest-host communication area)
+
+  This function checks if host has requested the Iommu support then it uses
+  the IOMMU protocol allocator for allocating vring otherwise uses AllocatePages
+
+**/
+STATIC
+VOID *
+VirtioRingAllocatePages (
+  IN  VRING   *Ring
+  )
+{
+  UINT32  NumPages;
+  EDKII_IOMMU_PROTOCOL  *Iommu;
+
+  NumPages = Ring->NumPages;
+  Iommu = (EDKII_IOMMU_PROTOCOL *)Ring->Iommu;
+
+  //
+  // If IOMMU protocol is set then use IOMMU allocator otherwise
+  // fallback to standard allocator
+  //
+  if (Iommu) {
+    EFI_STATUS  Status;
+    VOID        *Buffer;
+
+    Status = Iommu->AllocateBuffer (Iommu, 0, EfiBootServicesData,
+                        NumPages, &Buffer, EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED);
+    if (EFI_ERROR (Status)) {
+      return NULL;
+    }
+
+    return Buffer;
+  }
+
+  return AllocatePages (NumPages);
+}
+
+/**
+
   Configure a virtio ring.
 
   This function sets up internal storage (the guest-host communication area)
@@ -76,7 +139,7 @@ VirtioRingInit (
                 EFI_PAGE_SIZE);
 
   Ring->NumPages = EFI_SIZE_TO_PAGES (RingSize);
-  Ring->Base = AllocatePages (Ring->NumPages);
+  Ring->Base = VirtioRingAllocatePages (Ring);
   if (Ring->Base == NULL) {
     return EFI_OUT_OF_RESOURCES;
   }
@@ -118,6 +181,35 @@ VirtioRingInit (
   return EFI_SUCCESS;
 }
 
+/**
+
+  Free vring (the guest-host communication area)
+
+  This function checks if host has requested the Iommu support then it uses
+  the IOMMU protocol free callback otherwise uses FreePages
+
+**/
+STATIC
+VOID
+VirtioRingFreePages (
+  IN  VRING   *Ring
+  )
+{
+  EDKII_IOMMU_PROTOCOL  *Iommu;
+
+  Iommu = (EDKII_IOMMU_PROTOCOL *)Ring->Iommu;
+
+  //
+  // If IOMMU protocol is set then use IOMMU FreeBuffer otherwise
+  // fallback to FreePages
+  //
+  if (Iommu) {
+    Iommu->FreeBuffer (Iommu, Ring->NumPages, Ring->Base);
+  } else {
+    FreePages (Ring->Base, Ring->NumPages);
+  }
+}
+
 
 /**
 
@@ -136,7 +228,7 @@ VirtioRingUninit (
   IN OUT VRING *Ring
   )
 {
-  FreePages (Ring->Base, Ring->NumPages);
+  VirtioRingFreePages (Ring);
   SetMem (Ring, sizeof *Ring, 0x00);
 }
 
-- 
2.7.4

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel