]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/PvScsiDxe: Setup requests and completions rings
authorLiran Alon <liran.alon@oracle.com>
Sat, 28 Mar 2020 20:00:56 +0000 (23:00 +0300)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 30 Mar 2020 16:45:07 +0000 (16:45 +0000)
These rings are shared memory buffers between host and device in which
a cyclic buffer is managed to send request descriptors from host to
device and receive completion descriptors from device to host.

Note that because device may be constrained by IOMMU or guest may be run
under AMD SEV, we make sure to map these rings to device by using
PciIo->Map().

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2567
Signed-off-by: Liran Alon <liran.alon@oracle.com>
Message-Id: <20200328200100.60786-14-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
OvmfPkg/PvScsiDxe/PvScsiDxe.inf

index cf75884350eeef056765133d12b7e2e147d8af5f..c7d367e83a2da97c8aa040a7f345bd1761e995e7 100644 (file)
 \r
 #include <IndustryStandard/Pci.h>\r
 #include <IndustryStandard/PvScsi.h>\r
+#include <Library/BaseLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiLib.h>\r
 #include <Protocol/PciIo.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
 #include <Uefi/UefiSpec.h>\r
 \r
 #include "PvScsi.h"\r
@@ -436,6 +438,207 @@ PvScsiRestorePciAttributes (
                 );\r
 }\r
 \r
+STATIC\r
+EFI_STATUS\r
+PvScsiAllocateSharedPages (\r
+  IN PVSCSI_DEV                     *Dev,\r
+  IN UINTN                          Pages,\r
+  OUT VOID                          **HostAddress,\r
+  OUT PVSCSI_DMA_DESC               *DmaDesc\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  UINTN      NumberOfBytes;\r
+\r
+  Status = Dev->PciIo->AllocateBuffer (\r
+                         Dev->PciIo,\r
+                         AllocateAnyPages,\r
+                         EfiBootServicesData,\r
+                         Pages,\r
+                         HostAddress,\r
+                         EFI_PCI_ATTRIBUTE_MEMORY_CACHED\r
+                         );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);\r
+  Status = Dev->PciIo->Map (\r
+                         Dev->PciIo,\r
+                         EfiPciIoOperationBusMasterCommonBuffer,\r
+                         *HostAddress,\r
+                         &NumberOfBytes,\r
+                         &DmaDesc->DeviceAddress,\r
+                         &DmaDesc->Mapping\r
+                         );\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeBuffer;\r
+  }\r
+\r
+  if (NumberOfBytes != EFI_PAGES_TO_SIZE (Pages)) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Unmap;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+Unmap:\r
+  Dev->PciIo->Unmap (Dev->PciIo, DmaDesc->Mapping);\r
+\r
+FreeBuffer:\r
+  Dev->PciIo->FreeBuffer (Dev->PciIo, Pages, *HostAddress);\r
+\r
+  return Status;\r
+}\r
+\r
+STATIC\r
+VOID\r
+PvScsiFreeSharedPages (\r
+  IN PVSCSI_DEV                     *Dev,\r
+  IN UINTN                          Pages,\r
+  IN VOID                           *HostAddress,\r
+  IN PVSCSI_DMA_DESC                *DmaDesc\r
+  )\r
+{\r
+  Dev->PciIo->Unmap (Dev->PciIo, DmaDesc->Mapping);\r
+  Dev->PciIo->FreeBuffer (Dev->PciIo, Pages, HostAddress);\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+PvScsiInitRings (\r
+  IN OUT PVSCSI_DEV *Dev\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  union {\r
+    PVSCSI_CMD_DESC_SETUP_RINGS Cmd;\r
+    UINT32                      Uint32;\r
+  } AlignedCmd;\r
+  PVSCSI_CMD_DESC_SETUP_RINGS *Cmd;\r
+\r
+  Cmd = &AlignedCmd.Cmd;\r
+\r
+  Status = PvScsiAllocateSharedPages (\r
+             Dev,\r
+             1,\r
+             (VOID **)&Dev->RingDesc.RingState,\r
+             &Dev->RingDesc.RingStateDmaDesc\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  ZeroMem (Dev->RingDesc.RingState, EFI_PAGE_SIZE);\r
+\r
+  Status = PvScsiAllocateSharedPages (\r
+             Dev,\r
+             1,\r
+             (VOID **)&Dev->RingDesc.RingReqs,\r
+             &Dev->RingDesc.RingReqsDmaDesc\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeRingState;\r
+  }\r
+  ZeroMem (Dev->RingDesc.RingReqs, EFI_PAGE_SIZE);\r
+\r
+  Status = PvScsiAllocateSharedPages (\r
+             Dev,\r
+             1,\r
+             (VOID **)&Dev->RingDesc.RingCmps,\r
+             &Dev->RingDesc.RingCmpsDmaDesc\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeRingReqs;\r
+  }\r
+  ZeroMem (Dev->RingDesc.RingCmps, EFI_PAGE_SIZE);\r
+\r
+  ZeroMem (Cmd, sizeof (*Cmd));\r
+  Cmd->ReqRingNumPages = 1;\r
+  Cmd->CmpRingNumPages = 1;\r
+  Cmd->RingsStatePPN = RShiftU64 (\r
+                         Dev->RingDesc.RingStateDmaDesc.DeviceAddress,\r
+                         EFI_PAGE_SHIFT\r
+                         );\r
+  Cmd->ReqRingPPNs[0] = RShiftU64 (\r
+                          Dev->RingDesc.RingReqsDmaDesc.DeviceAddress,\r
+                          EFI_PAGE_SHIFT\r
+                          );\r
+  Cmd->CmpRingPPNs[0] = RShiftU64 (\r
+                          Dev->RingDesc.RingCmpsDmaDesc.DeviceAddress,\r
+                          EFI_PAGE_SHIFT\r
+                          );\r
+\r
+  STATIC_ASSERT (\r
+    sizeof (*Cmd) % sizeof (UINT32) == 0,\r
+    "Cmd must be multiple of 32-bit words"\r
+    );\r
+  Status = PvScsiWriteCmdDesc (\r
+             Dev,\r
+             PvScsiCmdSetupRings,\r
+             (UINT32 *)Cmd,\r
+             sizeof (*Cmd) / sizeof (UINT32)\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    goto FreeRingCmps;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+FreeRingCmps:\r
+  PvScsiFreeSharedPages (\r
+    Dev,\r
+    1,\r
+    Dev->RingDesc.RingCmps,\r
+    &Dev->RingDesc.RingCmpsDmaDesc\r
+    );\r
+\r
+FreeRingReqs:\r
+  PvScsiFreeSharedPages (\r
+    Dev,\r
+    1,\r
+    Dev->RingDesc.RingReqs,\r
+    &Dev->RingDesc.RingReqsDmaDesc\r
+    );\r
+\r
+FreeRingState:\r
+  PvScsiFreeSharedPages (\r
+    Dev,\r
+    1,\r
+    Dev->RingDesc.RingState,\r
+    &Dev->RingDesc.RingStateDmaDesc\r
+    );\r
+\r
+  return Status;\r
+}\r
+\r
+STATIC\r
+VOID\r
+PvScsiFreeRings (\r
+  IN OUT PVSCSI_DEV *Dev\r
+  )\r
+{\r
+  PvScsiFreeSharedPages (\r
+    Dev,\r
+    1,\r
+    Dev->RingDesc.RingCmps,\r
+    &Dev->RingDesc.RingCmpsDmaDesc\r
+    );\r
+\r
+  PvScsiFreeSharedPages (\r
+    Dev,\r
+    1,\r
+    Dev->RingDesc.RingReqs,\r
+    &Dev->RingDesc.RingReqsDmaDesc\r
+    );\r
+\r
+  PvScsiFreeSharedPages (\r
+    Dev,\r
+    1,\r
+    Dev->RingDesc.RingState,\r
+    &Dev->RingDesc.RingStateDmaDesc\r
+    );\r
+}\r
+\r
 STATIC\r
 EFI_STATUS\r
 PvScsiInit (\r
@@ -466,6 +669,14 @@ PvScsiInit (
     goto RestorePciAttributes;\r
   }\r
 \r
+  //\r
+  // Init PVSCSI rings\r
+  //\r
+  Status = PvScsiInitRings (Dev);\r
+  if (EFI_ERROR (Status)) {\r
+    goto RestorePciAttributes;\r
+  }\r
+\r
   //\r
   // Populate the exported interface's attributes\r
   //\r
@@ -509,6 +720,14 @@ PvScsiUninit (
   IN OUT PVSCSI_DEV *Dev\r
   )\r
 {\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
   PvScsiRestorePciAttributes (Dev);\r
 }\r
 \r
index 5f611dbbc98c5e2e41cb864769e4a6f9ae04f78a..6d23b6e1eccf9fa82afdf214d02671119a604912 100644 (file)
 #include <Library/DebugLib.h>\r
 #include <Protocol/ScsiPassThruExt.h>\r
 \r
+typedef struct {\r
+  EFI_PHYSICAL_ADDRESS DeviceAddress;\r
+  VOID                 *Mapping;\r
+} PVSCSI_DMA_DESC;\r
+\r
+typedef struct {\r
+  PVSCSI_RINGS_STATE   *RingState;\r
+  PVSCSI_DMA_DESC      RingStateDmaDesc;\r
+\r
+  PVSCSI_RING_REQ_DESC *RingReqs;\r
+  PVSCSI_DMA_DESC      RingReqsDmaDesc;\r
+\r
+  PVSCSI_RING_CMP_DESC *RingCmps;\r
+  PVSCSI_DMA_DESC      RingCmpsDmaDesc;\r
+} PVSCSI_RING_DESC;\r
+\r
 #define PVSCSI_SIG SIGNATURE_32 ('P', 'S', 'C', 'S')\r
 \r
 typedef struct {\r
   UINT32                          Signature;\r
   EFI_PCI_IO_PROTOCOL             *PciIo;\r
   UINT64                          OriginalPciAttributes;\r
+  PVSCSI_RING_DESC                RingDesc;\r
   UINT8                           MaxTarget;\r
   UINT8                           MaxLun;\r
   EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;\r
index fcffc90d46c8269a2ff7a30c674a84f36e8e24c2..6200533698fc50e50418b9614f976c793aecc667 100644 (file)
@@ -26,6 +26,7 @@
   OvmfPkg/OvmfPkg.dec\r
 \r
 [LibraryClasses]\r
+  BaseLib\r
   BaseMemoryLib\r
   DebugLib\r
   MemoryAllocationLib\r