]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/VirtioNetDxe/SnpInitialize.c
OvmfPkg/VirtioNetDxe: negotiate VIRTIO_F_IOMMU_PLATFORM
[mirror_edk2.git] / OvmfPkg / VirtioNetDxe / SnpInitialize.c
index 430670a980f2fe7dc2033462b8b4928a8cf89fcb..9dff04ce6071cee47c2dad8c2a273ce9c6610941 100644 (file)
@@ -5,6 +5,7 @@
 \r
   Copyright (C) 2013, Red Hat, Inc.\r
   Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
 \r
   Copyright (C) 2013, Red Hat, Inc.\r
   Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>\r
 \r
   This program and the accompanying materials are licensed and made available\r
   under the terms and conditions of the BSD License which accompanies this\r
 \r
   This program and the accompanying materials are licensed and made available\r
   under the terms and conditions of the BSD License which accompanies this\r
@@ -17,6 +18,7 @@
 **/\r
 \r
 #include <Library/BaseLib.h>\r
 **/\r
 \r
 #include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 \r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 \r
                            the network device.\r
   @param[out]    Ring      The virtio-ring inside the VNET_DEV structure,\r
                            corresponding to Selector.\r
                            the network device.\r
   @param[out]    Ring      The virtio-ring inside the VNET_DEV structure,\r
                            corresponding to Selector.\r
+  @param[out]    Mapping   A resulting token to pass to VirtioNetUninitRing()\r
 \r
   @retval EFI_UNSUPPORTED  The queue size reported by the virtio-net device is\r
                            too small.\r
   @return                  Status codes from VIRTIO_CFG_WRITE(),\r
 \r
   @retval EFI_UNSUPPORTED  The queue size reported by the virtio-net device is\r
                            too small.\r
   @return                  Status codes from VIRTIO_CFG_WRITE(),\r
-                           VIRTIO_CFG_READ() and VirtioRingInit().\r
+                           VIRTIO_CFG_READ(), VirtioRingInit() and\r
+                           VirtioRingMap().\r
   @retval EFI_SUCCESS      Ring initialized.\r
 */\r
 \r
   @retval EFI_SUCCESS      Ring initialized.\r
 */\r
 \r
@@ -48,11 +52,14 @@ EFIAPI
 VirtioNetInitRing (\r
   IN OUT VNET_DEV *Dev,\r
   IN     UINT16   Selector,\r
 VirtioNetInitRing (\r
   IN OUT VNET_DEV *Dev,\r
   IN     UINT16   Selector,\r
-  OUT    VRING    *Ring\r
+  OUT    VRING    *Ring,\r
+  OUT    VOID     **Mapping\r
   )\r
 {\r
   EFI_STATUS Status;\r
   UINT16     QueueSize;\r
   )\r
 {\r
   EFI_STATUS Status;\r
   UINT16     QueueSize;\r
+  UINT64     RingBaseShift;\r
+  VOID       *MapInfo;\r
 \r
   //\r
   // step 4b -- allocate selected queue\r
 \r
   //\r
   // step 4b -- allocate selected queue\r
@@ -73,37 +80,50 @@ VirtioNetInitRing (
   if (QueueSize < 2) {\r
     return EFI_UNSUPPORTED;\r
   }\r
   if (QueueSize < 2) {\r
     return EFI_UNSUPPORTED;\r
   }\r
-  Status = VirtioRingInit (QueueSize, Ring);\r
+  Status = VirtioRingInit (Dev->VirtIo, QueueSize, Ring);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
+  //\r
+  // If anything fails from here on, we must release the ring resources.\r
+  //\r
+  Status = VirtioRingMap (Dev->VirtIo, Ring, &RingBaseShift, &MapInfo);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ReleaseQueue;\r
+  }\r
+\r
   //\r
   // Additional steps for MMIO: align the queue appropriately, and set the\r
   //\r
   // Additional steps for MMIO: align the queue appropriately, and set the\r
-  // size. If anything fails from here on, we must release the ring resources.\r
+  // size. If anything fails from here on, we must unmap the ring resources.\r
   //\r
   Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
   if (EFI_ERROR (Status)) {\r
   //\r
   Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
   if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+    goto UnmapQueue;\r
   }\r
 \r
   Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
   if (EFI_ERROR (Status)) {\r
   }\r
 \r
   Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
   if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+    goto UnmapQueue;\r
   }\r
 \r
   //\r
   // step 4c -- report GPFN (guest-physical frame number) of queue\r
   //\r
   }\r
 \r
   //\r
   // step 4c -- report GPFN (guest-physical frame number) of queue\r
   //\r
-  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring);\r
+  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring, RingBaseShift);\r
   if (EFI_ERROR (Status)) {\r
   if (EFI_ERROR (Status)) {\r
-    goto ReleaseQueue;\r
+    goto UnmapQueue;\r
   }\r
 \r
   }\r
 \r
+  *Mapping = MapInfo;\r
+\r
   return EFI_SUCCESS;\r
 \r
   return EFI_SUCCESS;\r
 \r
+UnmapQueue:\r
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, MapInfo);\r
+\r
 ReleaseQueue:\r
 ReleaseQueue:\r
-  VirtioRingUninit (Ring);\r
+  VirtioRingUninit (Dev->VirtIo, Ring);\r
 \r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
@@ -127,7 +147,11 @@ ReleaseQueue:
                            EfiSimpleNetworkInitialized state.\r
 \r
   @retval EFI_OUT_OF_RESOURCES  Failed to allocate the stack to track the heads\r
                            EfiSimpleNetworkInitialized state.\r
 \r
   @retval EFI_OUT_OF_RESOURCES  Failed to allocate the stack to track the heads\r
-                                of free descriptor chains.\r
+                                of free descriptor chains or failed to init\r
+                                TxBufCollection.\r
+  @return                       Status codes from VIRTIO_DEVICE_PROTOCOL.\r
+                                AllocateSharedPages() or\r
+                                VirtioMapAllBytesInSharedBuffer()\r
   @retval EFI_SUCCESS           TX setup successful.\r
 */\r
 \r
   @retval EFI_SUCCESS           TX setup successful.\r
 */\r
 \r
@@ -138,8 +162,11 @@ VirtioNetInitTx (
   IN OUT VNET_DEV *Dev\r
   )\r
 {\r
   IN OUT VNET_DEV *Dev\r
   )\r
 {\r
-  UINTN TxSharedReqSize;\r
-  UINTN PktIdx;\r
+  UINTN                 TxSharedReqSize;\r
+  UINTN                 PktIdx;\r
+  EFI_STATUS            Status;\r
+  EFI_PHYSICAL_ADDRESS  DeviceAddress;\r
+  VOID                  *TxSharedReqBuffer;\r
 \r
   Dev->TxMaxPending = (UINT16) MIN (Dev->TxRing.QueueSize / 2,\r
                                  VNET_MAX_PENDING);\r
 \r
   Dev->TxMaxPending = (UINT16) MIN (Dev->TxRing.QueueSize / 2,\r
                                  VNET_MAX_PENDING);\r
@@ -150,13 +177,52 @@ VirtioNetInitTx (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  Dev->TxBufCollection = OrderedCollectionInit (\r
+                           VirtioNetTxBufMapInfoCompare,\r
+                           VirtioNetTxBufDeviceAddressCompare\r
+                           );\r
+  if (Dev->TxBufCollection == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto FreeTxFreeStack;\r
+  }\r
+\r
+  //\r
+  // Allocate TxSharedReq header and map with BusMasterCommonBuffer so that it\r
+  // can be accessed equally by both processor and device.\r
+  //\r
+  Status = Dev->VirtIo->AllocateSharedPages (\r
+                          Dev->VirtIo,\r
+                          EFI_SIZE_TO_PAGES (sizeof *Dev->TxSharedReq),\r
+                          &TxSharedReqBuffer\r
+                          );\r
+  if (EFI_ERROR (Status)) {\r
+    goto UninitTxBufCollection;\r
+  }\r
+\r
+  ZeroMem (TxSharedReqBuffer, sizeof *Dev->TxSharedReq);\r
+\r
+  Status = VirtioMapAllBytesInSharedBuffer (\r
+             Dev->VirtIo,\r
+             VirtioOperationBusMasterCommonBuffer,\r
+             TxSharedReqBuffer,\r
+             sizeof *(Dev->TxSharedReq),\r
+             &DeviceAddress,\r
+             &Dev->TxSharedReqMap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeTxSharedReqBuffer;\r
+  }\r
+\r
+  Dev->TxSharedReq = TxSharedReqBuffer;\r
+\r
+\r
   //\r
   // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on\r
   // VIRTIO_NET_F_MRG_RXBUF, which we never negotiate.\r
   //\r
   TxSharedReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ?\r
   //\r
   // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on\r
   // VIRTIO_NET_F_MRG_RXBUF, which we never negotiate.\r
   //\r
   TxSharedReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ?\r
-                    sizeof Dev->TxSharedReq.V0_9_5 :\r
-                    sizeof Dev->TxSharedReq;\r
+                    sizeof (Dev->TxSharedReq->V0_9_5) :\r
+                    sizeof *Dev->TxSharedReq;\r
 \r
   for (PktIdx = 0; PktIdx < Dev->TxMaxPending; ++PktIdx) {\r
     UINT16 DescIdx;\r
 \r
   for (PktIdx = 0; PktIdx < Dev->TxMaxPending; ++PktIdx) {\r
     UINT16 DescIdx;\r
@@ -168,7 +234,7 @@ VirtioNetInitTx (
     // For each possibly pending packet, lay out the descriptor for the common\r
     // (unmodified by the host) virtio-net request header.\r
     //\r
     // For each possibly pending packet, lay out the descriptor for the common\r
     // (unmodified by the host) virtio-net request header.\r
     //\r
-    Dev->TxRing.Desc[DescIdx].Addr  = (UINTN) &Dev->TxSharedReq;\r
+    Dev->TxRing.Desc[DescIdx].Addr  = DeviceAddress;\r
     Dev->TxRing.Desc[DescIdx].Len   = (UINT32) TxSharedReqSize;\r
     Dev->TxRing.Desc[DescIdx].Flags = VRING_DESC_F_NEXT;\r
     Dev->TxRing.Desc[DescIdx].Next  = (UINT16) (DescIdx + 1);\r
     Dev->TxRing.Desc[DescIdx].Len   = (UINT32) TxSharedReqSize;\r
     Dev->TxRing.Desc[DescIdx].Flags = VRING_DESC_F_NEXT;\r
     Dev->TxRing.Desc[DescIdx].Next  = (UINT16) (DescIdx + 1);\r
@@ -183,13 +249,13 @@ VirtioNetInitTx (
   //\r
   // virtio-0.9.5, Appendix C, Packet Transmission\r
   //\r
   //\r
   // virtio-0.9.5, Appendix C, Packet Transmission\r
   //\r
-  Dev->TxSharedReq.V0_9_5.Flags   = 0;\r
-  Dev->TxSharedReq.V0_9_5.GsoType = VIRTIO_NET_HDR_GSO_NONE;\r
+  Dev->TxSharedReq->V0_9_5.Flags   = 0;\r
+  Dev->TxSharedReq->V0_9_5.GsoType = VIRTIO_NET_HDR_GSO_NONE;\r
 \r
   //\r
   // For VirtIo 1.0 only -- the field exists, but it is unused\r
   //\r
 \r
   //\r
   // For VirtIo 1.0 only -- the field exists, but it is unused\r
   //\r
-  Dev->TxSharedReq.NumBuffers = 0;\r
+  Dev->TxSharedReq->NumBuffers = 0;\r
 \r
   //\r
   // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
 \r
   //\r
   // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
@@ -204,6 +270,21 @@ VirtioNetInitTx (
   *Dev->TxRing.Avail.Flags = (UINT16) VRING_AVAIL_F_NO_INTERRUPT;\r
 \r
   return EFI_SUCCESS;\r
   *Dev->TxRing.Avail.Flags = (UINT16) VRING_AVAIL_F_NO_INTERRUPT;\r
 \r
   return EFI_SUCCESS;\r
+\r
+FreeTxSharedReqBuffer:\r
+  Dev->VirtIo->FreeSharedPages (\r
+                 Dev->VirtIo,\r
+                 EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)),\r
+                 TxSharedReqBuffer\r
+                 );\r
+\r
+UninitTxBufCollection:\r
+  OrderedCollectionUninit (Dev->TxBufCollection);\r
+\r
+FreeTxFreeStack:\r
+  FreePool (Dev->TxFreeStack);\r
+\r
+  return Status;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -223,8 +304,9 @@ VirtioNetInitTx (
   @param[in,out] Dev       The VNET_DEV driver instance about to enter the\r
                            EfiSimpleNetworkInitialized state.\r
 \r
   @param[in,out] Dev       The VNET_DEV driver instance about to enter the\r
                            EfiSimpleNetworkInitialized state.\r
 \r
-  @retval EFI_OUT_OF_RESOURCES  Failed to allocate RX destination area.\r
-  @return                       Status codes from VIRTIO_CFG_WRITE().\r
+  @return                       Status codes from VIRTIO_CFG_WRITE() or\r
+                                VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages or\r
+                                VirtioMapAllBytesInSharedBuffer().\r
   @retval EFI_SUCCESS           RX setup successful. The device is live and may\r
                                 already be writing to the receive area.\r
 */\r
   @retval EFI_SUCCESS           RX setup successful. The device is live and may\r
                                 already be writing to the receive area.\r
 */\r
@@ -236,13 +318,15 @@ VirtioNetInitRx (
   IN OUT VNET_DEV *Dev\r
   )\r
 {\r
   IN OUT VNET_DEV *Dev\r
   )\r
 {\r
-  EFI_STATUS Status;\r
-  UINTN      VirtioNetReqSize;\r
-  UINTN      RxBufSize;\r
-  UINT16     RxAlwaysPending;\r
-  UINTN      PktIdx;\r
-  UINT16     DescIdx;\r
-  UINT8      *RxPtr;\r
+  EFI_STATUS            Status;\r
+  UINTN                 VirtioNetReqSize;\r
+  UINTN                 RxBufSize;\r
+  UINT16                RxAlwaysPending;\r
+  UINTN                 PktIdx;\r
+  UINT16                DescIdx;\r
+  UINTN                 NumBytes;\r
+  EFI_PHYSICAL_ADDRESS  RxBufDeviceAddress;\r
+  VOID                  *RxBuffer;\r
 \r
   //\r
   // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on\r
 \r
   //\r
   // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on\r
@@ -267,11 +351,39 @@ VirtioNetInitRx (
   //\r
   RxAlwaysPending = (UINT16) MIN (Dev->RxRing.QueueSize / 2, VNET_MAX_PENDING);\r
 \r
   //\r
   RxAlwaysPending = (UINT16) MIN (Dev->RxRing.QueueSize / 2, VNET_MAX_PENDING);\r
 \r
-  Dev->RxBuf = AllocatePool (RxAlwaysPending * RxBufSize);\r
-  if (Dev->RxBuf == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+  //\r
+  // The RxBuf is shared between guest and hypervisor, use\r
+  // AllocateSharedPages() to allocate this memory region and map it with\r
+  // BusMasterCommonBuffer so that it can be accessed by both guest and\r
+  // hypervisor.\r
+  //\r
+  NumBytes = RxAlwaysPending * RxBufSize;\r
+  Dev->RxBufNrPages = EFI_SIZE_TO_PAGES (NumBytes);\r
+  Status = Dev->VirtIo->AllocateSharedPages (\r
+                          Dev->VirtIo,\r
+                          Dev->RxBufNrPages,\r
+                          &RxBuffer\r
+                          );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  ZeroMem (RxBuffer, NumBytes);\r
+\r
+  Status = VirtioMapAllBytesInSharedBuffer (\r
+             Dev->VirtIo,\r
+             VirtioOperationBusMasterCommonBuffer,\r
+             RxBuffer,\r
+             NumBytes,\r
+             &Dev->RxBufDeviceBase,\r
+             &Dev->RxBufMap\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeSharedBuffer;\r
   }\r
 \r
   }\r
 \r
+  Dev->RxBuf = RxBuffer;\r
+\r
   //\r
   // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
   //\r
   //\r
   // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device\r
   //\r
@@ -291,7 +403,7 @@ VirtioNetInitRx (
   // link each chain into (from) the available ring as well\r
   //\r
   DescIdx = 0;\r
   // link each chain into (from) the available ring as well\r
   //\r
   DescIdx = 0;\r
-  RxPtr = Dev->RxBuf;\r
+  RxBufDeviceAddress = Dev->RxBufDeviceBase;\r
   for (PktIdx = 0; PktIdx < RxAlwaysPending; ++PktIdx) {\r
     //\r
     // virtio-0.9.5, 2.4.1.2 Updating the Available Ring\r
   for (PktIdx = 0; PktIdx < RxAlwaysPending; ++PktIdx) {\r
     //\r
     // virtio-0.9.5, 2.4.1.2 Updating the Available Ring\r
@@ -302,16 +414,16 @@ VirtioNetInitRx (
     //\r
     // virtio-0.9.5, 2.4.1.1 Placing Buffers into the Descriptor Table\r
     //\r
     //\r
     // virtio-0.9.5, 2.4.1.1 Placing Buffers into the Descriptor Table\r
     //\r
-    Dev->RxRing.Desc[DescIdx].Addr  = (UINTN) RxPtr;\r
+    Dev->RxRing.Desc[DescIdx].Addr  = RxBufDeviceAddress;\r
     Dev->RxRing.Desc[DescIdx].Len   = (UINT32) VirtioNetReqSize;\r
     Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;\r
     Dev->RxRing.Desc[DescIdx].Next  = (UINT16) (DescIdx + 1);\r
     Dev->RxRing.Desc[DescIdx].Len   = (UINT32) VirtioNetReqSize;\r
     Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;\r
     Dev->RxRing.Desc[DescIdx].Next  = (UINT16) (DescIdx + 1);\r
-    RxPtr += Dev->RxRing.Desc[DescIdx++].Len;\r
+    RxBufDeviceAddress += Dev->RxRing.Desc[DescIdx++].Len;\r
 \r
 \r
-    Dev->RxRing.Desc[DescIdx].Addr  = (UINTN) RxPtr;\r
+    Dev->RxRing.Desc[DescIdx].Addr  = RxBufDeviceAddress;\r
     Dev->RxRing.Desc[DescIdx].Len   = (UINT32) (RxBufSize - VirtioNetReqSize);\r
     Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE;\r
     Dev->RxRing.Desc[DescIdx].Len   = (UINT32) (RxBufSize - VirtioNetReqSize);\r
     Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE;\r
-    RxPtr += Dev->RxRing.Desc[DescIdx++].Len;\r
+    RxBufDeviceAddress += Dev->RxRing.Desc[DescIdx++].Len;\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -332,10 +444,21 @@ VirtioNetInitRx (
   Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);\r
   if (EFI_ERROR (Status)) {\r
     Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
   Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);\r
   if (EFI_ERROR (Status)) {\r
     Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
-    FreePool (Dev->RxBuf);\r
+    goto UnmapSharedBuffer;\r
   }\r
 \r
   return Status;\r
   }\r
 \r
   return Status;\r
+\r
+UnmapSharedBuffer:\r
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);\r
+\r
+FreeSharedBuffer:\r
+  Dev->VirtIo->FreeSharedPages (\r
+                 Dev->VirtIo,\r
+                 Dev->RxBufNrPages,\r
+                 RxBuffer\r
+                 );\r
+  return Status;\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -439,7 +562,8 @@ VirtioNetInitialize (
   ASSERT (Dev->Snm.MediaPresentSupported ==\r
     !!(Features & VIRTIO_NET_F_STATUS));\r
 \r
   ASSERT (Dev->Snm.MediaPresentSupported ==\r
     !!(Features & VIRTIO_NET_F_STATUS));\r
 \r
-  Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | VIRTIO_F_VERSION_1;\r
+  Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | VIRTIO_F_VERSION_1 |\r
+              VIRTIO_F_IOMMU_PLATFORM;\r
 \r
   //\r
   // In virtio-1.0, feature negotiation is expected to complete before queue\r
 \r
   //\r
   // In virtio-1.0, feature negotiation is expected to complete before queue\r
@@ -455,12 +579,22 @@ VirtioNetInitialize (
   //\r
   // step 4b, 4c -- allocate and report virtqueues\r
   //\r
   //\r
   // step 4b, 4c -- allocate and report virtqueues\r
   //\r
-  Status = VirtioNetInitRing (Dev, VIRTIO_NET_Q_RX, &Dev->RxRing);\r
+  Status = VirtioNetInitRing (\r
+             Dev,\r
+             VIRTIO_NET_Q_RX,\r
+             &Dev->RxRing,\r
+             &Dev->RxRingMap\r
+             );\r
   if (EFI_ERROR (Status)) {\r
     goto DeviceFailed;\r
   }\r
 \r
   if (EFI_ERROR (Status)) {\r
     goto DeviceFailed;\r
   }\r
 \r
-  Status = VirtioNetInitRing (Dev, VIRTIO_NET_Q_TX, &Dev->TxRing);\r
+  Status = VirtioNetInitRing (\r
+             Dev,\r
+             VIRTIO_NET_Q_TX,\r
+             &Dev->TxRing,\r
+             &Dev->TxRingMap\r
+             );\r
   if (EFI_ERROR (Status)) {\r
     goto ReleaseRxRing;\r
   }\r
   if (EFI_ERROR (Status)) {\r
     goto ReleaseRxRing;\r
   }\r
@@ -469,7 +603,7 @@ VirtioNetInitialize (
   // step 5 -- keep only the features we want\r
   //\r
   if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
   // step 5 -- keep only the features we want\r
   //\r
   if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
-    Features &= ~(UINT64)VIRTIO_F_VERSION_1;\r
+    Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM);\r
     Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
     if (EFI_ERROR (Status)) {\r
       goto ReleaseTxRing;\r
     Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
     if (EFI_ERROR (Status)) {\r
       goto ReleaseTxRing;\r
@@ -509,10 +643,10 @@ AbortDevice:
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
 \r
 ReleaseTxRing:\r
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
 \r
 ReleaseTxRing:\r
-  VirtioRingUninit (&Dev->TxRing);\r
+  VirtioNetUninitRing (Dev, &Dev->TxRing, Dev->TxRingMap);\r
 \r
 ReleaseRxRing:\r
 \r
 ReleaseRxRing:\r
-  VirtioRingUninit (&Dev->RxRing);\r
+  VirtioNetUninitRing (Dev, &Dev->RxRing, Dev->RxRingMap);\r
 \r
 DeviceFailed:\r
   //\r
 \r
 DeviceFailed:\r
   //\r