]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/PvScsiDxe: Introduce DMA communication buffer
authorLiran Alon <liran.alon@oracle.com>
Sat, 28 Mar 2020 20:00:57 +0000 (23:00 +0300)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 30 Mar 2020 16:45:07 +0000 (16:45 +0000)
In case device is constrained by IOMMU or guest is running under AMD SEV,
input/output buffers provided to device (DataBuffer and SenseData) needs
to be explicitly mapped to device by PciIo->Map().

To avoid the overhead of mapping/unmapping the DataBuffer and SenseData
to the device for every SCSI requst (and to simplify code), introduce a
single DMA communication buffer that will be mapped to device on
initialization. When a SCSI request needs to be sent to device, the
DataBuffer and SenseData will be copied from/to the DMA communication
buffer as required. This will be done by the following commits.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2567
Signed-off-by: Liran Alon <liran.alon@oracle.com>
Message-Id: <20200328200100.60786-15-liran.alon@oracle.com>
Reviewed-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
OvmfPkg/PvScsiDxe/PvScsi.c
OvmfPkg/PvScsiDxe/PvScsi.h

index c7d367e83a2da97c8aa040a7f345bd1761e995e7..6e350bb2d6e02b229b88f534262f97fe1407d00e 100644 (file)
@@ -677,6 +677,19 @@ PvScsiInit (
     goto RestorePciAttributes;\r
   }\r
 \r
+  //\r
+  // Allocate DMA communication buffer\r
+  //\r
+  Status = PvScsiAllocateSharedPages (\r
+             Dev,\r
+             EFI_SIZE_TO_PAGES (sizeof (*Dev->DmaBuf)),\r
+             (VOID **)&Dev->DmaBuf,\r
+             &Dev->DmaBufDmaDesc\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeRings;\r
+  }\r
+\r
   //\r
   // Populate the exported interface's attributes\r
   //\r
@@ -708,6 +721,15 @@ PvScsiInit (
 \r
   return EFI_SUCCESS;\r
 \r
+FreeRings:\r
+  //\r
+  // Reset device to stop device usage of the rings.\r
+  // This is required to safely free the rings.\r
+  //\r
+  PvScsiResetAdapter (Dev);\r
+\r
+  PvScsiFreeRings (Dev);\r
+\r
 RestorePciAttributes:\r
   PvScsiRestorePciAttributes (Dev);\r
 \r
@@ -721,11 +743,25 @@ PvScsiUninit (
   )\r
 {\r
   //\r
-  // Reset device to stop device usage of the rings.\r
-  // This is required to safely free the rings.\r
+  // Reset device to:\r
+  // - Make device stop processing all requests.\r
+  // - Stop device usage of the rings.\r
+  //\r
+  // This is required to safely free the DMA communication buffer\r
+  // and the rings.\r
   //\r
   PvScsiResetAdapter (Dev);\r
 \r
+  //\r
+  // Free DMA communication buffer\r
+  //\r
+  PvScsiFreeSharedPages (\r
+    Dev,\r
+    EFI_SIZE_TO_PAGES (sizeof (*Dev->DmaBuf)),\r
+    Dev->DmaBuf,\r
+    &Dev->DmaBufDmaDesc\r
+    );\r
+\r
   PvScsiFreeRings (Dev);\r
 \r
   PvScsiRestorePciAttributes (Dev);\r
index 6d23b6e1eccf9fa82afdf214d02671119a604912..fff12146dc75512952cf2173d9173e95b3ebe4f8 100644 (file)
@@ -31,6 +31,21 @@ typedef struct {
   PVSCSI_DMA_DESC      RingCmpsDmaDesc;\r
 } PVSCSI_RING_DESC;\r
 \r
+typedef struct {\r
+  //\r
+  // As EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.SenseDataLength is defined\r
+  // as UINT8, defining here SenseData size to MAX_UINT8 will guarantee it\r
+  // cannot overflow when passed to device.\r
+  //\r
+  UINT8     SenseData[MAX_UINT8];\r
+  //\r
+  // This size of the data is arbitrarily chosen.\r
+  // It seems to be sufficient for all I/O requests sent through\r
+  // EFI_SCSI_PASS_THRU_PROTOCOL.PassThru() for common boot scenarios.\r
+  //\r
+  UINT8     Data[0x2000];\r
+} PVSCSI_DMA_BUFFER;\r
+\r
 #define PVSCSI_SIG SIGNATURE_32 ('P', 'S', 'C', 'S')\r
 \r
 typedef struct {\r
@@ -38,6 +53,8 @@ typedef struct {
   EFI_PCI_IO_PROTOCOL             *PciIo;\r
   UINT64                          OriginalPciAttributes;\r
   PVSCSI_RING_DESC                RingDesc;\r
+  PVSCSI_DMA_BUFFER               *DmaBuf;\r
+  PVSCSI_DMA_DESC                 DmaBufDmaDesc;\r
   UINT8                           MaxTarget;\r
   UINT8                           MaxLun;\r
   EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;\r
@@ -47,4 +64,7 @@ typedef struct {
 #define PVSCSI_FROM_PASS_THRU(PassThruPointer) \\r
   CR (PassThruPointer, PVSCSI_DEV, PassThru, PVSCSI_SIG)\r
 \r
+#define PVSCSI_DMA_BUF_DEV_ADDR(Dev, MemberName) \\r
+  (Dev->DmaBufDmaDesc.DeviceAddress + OFFSET_OF(PVSCSI_DMA_BUFFER, MemberName))\r
+\r
 #endif // __PVSCSI_DXE_H_\r