public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v2 0/3] OvmfPkg/VirtioBlkDxe: map host address to device address
@ 2017-08-28  0:34 Brijesh Singh
  2017-08-28  0:34 ` [PATCH v2 1/3] OvmfPkg/VirtioBlkDxe: map VRING using VirtioRingMap() Brijesh Singh
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Brijesh Singh @ 2017-08-28  0:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

The patch updates the VirtioBlkDxe to use IOMMU-like member functions to map
the system physical address to device address for buffers (including vring,
device specific request and response pointed by vring descriptor, and any
furter memory reference by those request and response).

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>

Repo: https://github.com/codomania/edk2
Branch: virtio-blk-2

Changes since v1:
 * changes to address v1 feedback

Brijesh Singh (3):
  OvmfPkg/VirtioBlkDxe: map VRING using VirtioRingMap()
  Ovmfpkg/VirtioBlkDxe: map virtio-blk request and response buffers
  OvmfPkg/VirtioBlkDxe: negotiate VIRTIO_F_IOMMU_PLATFORM

 OvmfPkg/VirtioBlkDxe/VirtioBlk.h |   1 +
 OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 188 +++++++++++++++++---
 2 files changed, 166 insertions(+), 23 deletions(-)

-- 
2.7.4



^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2 1/3] OvmfPkg/VirtioBlkDxe: map VRING using VirtioRingMap()
  2017-08-28  0:34 [PATCH v2 0/3] OvmfPkg/VirtioBlkDxe: map host address to device address Brijesh Singh
@ 2017-08-28  0:34 ` Brijesh Singh
  2017-08-28  0:34 ` [PATCH v2 2/3] Ovmfpkg/VirtioBlkDxe: map virtio-blk request and response buffers Brijesh Singh
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Brijesh Singh @ 2017-08-28  0:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

When device is behind the IOMMU then driver need to pass the device
address when programing the bus master. The patch uses VirtioRingMap() to
map the VRING system physical address to device address.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/VirtioBlkDxe/VirtioBlk.h |  1 +
 OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 45 ++++++++++++++++----
 2 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h
index 6c402ca88ea4..9ec0b956b818 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h
@@ -41,6 +41,7 @@ typedef struct {
   VRING                  Ring;                 // VirtioRingInit      2
   EFI_BLOCK_IO_PROTOCOL  BlockIo;              // VirtioBlkInit       1
   EFI_BLOCK_IO_MEDIA     BlockIoMedia;         // VirtioBlkInit       1
+  VOID                   *RingMap;             // VirtioRingMap       2
 } VBLK_DEV;
 
 #define VIRTIO_BLK_FROM_BLOCK_IO(BlockIoPointer) \
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index bff15fe3add1..663ba281ab73 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -580,7 +580,8 @@ VirtioBlkDriverBindingSupported (
                            virtio-blk attributes the host provides.
 
   @return                  Error codes from VirtioRingInit() or
-                           VIRTIO_CFG_READ() / VIRTIO_CFG_WRITE().
+                           VIRTIO_CFG_READ() / VIRTIO_CFG_WRITE or
+                           VirtioRingMap().
 
 **/
 
@@ -601,6 +602,7 @@ VirtioBlkInit (
   UINT8      AlignmentOffset;
   UINT32     OptIoSize;
   UINT16     QueueSize;
+  UINT64     RingBaseShift;
 
   PhysicalBlockExp = 0;
   AlignmentOffset = 0;
@@ -729,25 +731,42 @@ VirtioBlkInit (
   }
 
   //
+  // If anything fails from here on, we must release the ring resources
+  //
+  Status = VirtioRingMap (
+             Dev->VirtIo,
+             &Dev->Ring,
+             &RingBaseShift,
+             &Dev->RingMap
+             );
+  if (EFI_ERROR (Status)) {
+    goto ReleaseQueue;
+  }
+
+  //
   // Additional steps for MMIO: align the queue appropriately, and set the
-  // size. If anything fails from here on, we must release the ring resources.
+  // size. If anything fails from here on, we must unmap the ring resources.
   //
   Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
   if (EFI_ERROR (Status)) {
-    goto ReleaseQueue;
+    goto UnmapQueue;
   }
 
   Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
   if (EFI_ERROR (Status)) {
-    goto ReleaseQueue;
+    goto UnmapQueue;
   }
 
   //
   // step 4c -- Report GPFN (guest-physical frame number) of queue.
   //
-  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);
+  Status = Dev->VirtIo->SetQueueAddress (
+                          Dev->VirtIo,
+                          &Dev->Ring,
+                          RingBaseShift
+                          );
   if (EFI_ERROR (Status)) {
-    goto ReleaseQueue;
+    goto UnmapQueue;
   }
 
 
@@ -758,7 +777,7 @@ VirtioBlkInit (
     Features &= ~(UINT64)VIRTIO_F_VERSION_1;
     Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
     if (EFI_ERROR (Status)) {
-      goto ReleaseQueue;
+      goto UnmapQueue;
     }
   }
 
@@ -768,7 +787,7 @@ VirtioBlkInit (
   NextDevStat |= VSTAT_DRIVER_OK;
   Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
   if (EFI_ERROR (Status)) {
-    goto ReleaseQueue;
+    goto UnmapQueue;
   }
 
   //
@@ -811,6 +830,9 @@ VirtioBlkInit (
   }
   return EFI_SUCCESS;
 
+UnmapQueue:
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
+
 ReleaseQueue:
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
@@ -849,6 +871,7 @@ VirtioBlkUninit (
   //
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
 
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
   SetMem (&Dev->BlockIo,      sizeof Dev->BlockIo,      0x00);
@@ -885,6 +908,12 @@ VirtioBlkExitBoot (
   //
   Dev = Context;
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
+
+  //
+  // Unmap the ring buffer so that hypervisor will not be able to get
+  // readable data after device is reset.
+  //
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
 }
 
 /**
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 2/3] Ovmfpkg/VirtioBlkDxe: map virtio-blk request and response buffers
  2017-08-28  0:34 [PATCH v2 0/3] OvmfPkg/VirtioBlkDxe: map host address to device address Brijesh Singh
  2017-08-28  0:34 ` [PATCH v2 1/3] OvmfPkg/VirtioBlkDxe: map VRING using VirtioRingMap() Brijesh Singh
@ 2017-08-28  0:34 ` Brijesh Singh
  2017-08-28  8:10   ` Laszlo Ersek
  2017-08-28  0:34 ` [PATCH v2 3/3] OvmfPkg/VirtioBlkDxe: negotiate VIRTIO_F_IOMMU_PLATFORM Brijesh Singh
  2017-08-28  9:01 ` [PATCH v2 0/3] OvmfPkg/VirtioBlkDxe: map host address to device address Laszlo Ersek
  3 siblings, 1 reply; 6+ messages in thread
From: Brijesh Singh @ 2017-08-28  0:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

When device is behind the IOMMU, driver is require to pass the device
address of virtio request, response and any memory referenced by those
request/response to the bus master.

The patch uses IOMMU-like member functions from VIRTIO_DEVICE_PROTOCOL to
map request and response buffers system physical address to the device
address.

- If the buffer need to be accessed by both the processor and a bus
  master then map with BusMasterCommonBuffer.

- If the buffer need to be accessed for a write operation by a bus master
  then map with BusMasterWrite.

- If the buffer need to be accessed for a read  operation by a bus master
  then map with BusMasterRead.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 138 ++++++++++++++++++--
 1 file changed, 125 insertions(+), 13 deletions(-)

diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index 663ba281ab73..c9c42aa41243 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -232,7 +232,8 @@ VerifyReadWriteRequest (
 
   @retval EFI_DEVICE_ERROR     Failed to notify host side via VirtIo write, or
                                unable to parse host response, or host response
-                               is not VIRTIO_BLK_S_OK.
+                               is not VIRTIO_BLK_S_OK or failed to map Buffer
+                               for a bus master operation.
 
 **/
 
@@ -249,8 +250,16 @@ SynchronousRequest (
 {
   UINT32                  BlockSize;
   volatile VIRTIO_BLK_REQ Request;
-  volatile UINT8          HostStatus;
+  volatile UINT8          *HostStatus;
+  VOID                    *HostStatusBuffer;
   DESC_INDICES            Indices;
+  VOID                    *RequestMapping;
+  VOID                    *StatusMapping;
+  VOID                    *BufferMapping;
+  EFI_PHYSICAL_ADDRESS    BufferDeviceAddress;
+  EFI_PHYSICAL_ADDRESS    HostStatusDeviceAddress;
+  EFI_PHYSICAL_ADDRESS    RequestDeviceAddress;
+  EFI_STATUS              Status;
 
   BlockSize = Dev->BlockIoMedia.BlockSize;
 
@@ -275,12 +284,82 @@ SynchronousRequest (
   Request.IoPrio = 0;
   Request.Sector = MultU64x32(Lba, BlockSize / 512);
 
-  VirtioPrepare (&Dev->Ring, &Indices);
+  //
+  // Host status is bi-directional (we preset with a value and expect the
+  // device to update it). Allocate a host status buffer which can be mapped
+  // to access equally by both processor and the device.
+  //
+  Status = Dev->VirtIo->AllocateSharedPages (
+                          Dev->VirtIo,
+                          EFI_SIZE_TO_PAGES (sizeof *HostStatus),
+                          &HostStatusBuffer
+                          );
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  HostStatus = HostStatusBuffer;
+
+  //
+  // Map virtio-blk request header (must be done after request header is
+  // populated)
+  //
+  Status = VirtioMapAllBytesInSharedBuffer (
+             Dev->VirtIo,
+             VirtioOperationBusMasterRead,
+             (VOID *) &Request,
+             sizeof Request,
+             &RequestDeviceAddress,
+             &RequestMapping
+             );
+  if (EFI_ERROR (Status)) {
+    Status = EFI_DEVICE_ERROR;
+    goto FreeHostStatusBuffer;
+  }
+
+  //
+  // Map data buffer
+  //
+  if (BufferSize > 0) {
+    Status = VirtioMapAllBytesInSharedBuffer (
+               Dev->VirtIo,
+               (RequestIsWrite ?
+                VirtioOperationBusMasterRead :
+                VirtioOperationBusMasterWrite),
+               (VOID *) Buffer,
+               BufferSize,
+               &BufferDeviceAddress,
+               &BufferMapping
+               );
+    if (EFI_ERROR (Status)) {
+      Status = EFI_DEVICE_ERROR;
+      goto UnmapRequestBuffer;
+    }
+  }
 
   //
   // preset a host status for ourselves that we do not accept as success
   //
-  HostStatus = VIRTIO_BLK_S_IOERR;
+  *HostStatus = VIRTIO_BLK_S_IOERR;
+
+  //
+  // Map the Status Buffer with VirtioOperationBusMasterCommonBuffer so that
+  // both processor and device can access it.
+  //
+  Status = VirtioMapAllBytesInSharedBuffer (
+             Dev->VirtIo,
+             VirtioOperationBusMasterCommonBuffer,
+             HostStatusBuffer,
+             sizeof *HostStatus,
+             &HostStatusDeviceAddress,
+             &StatusMapping
+             );
+  if (EFI_ERROR (Status)) {
+    Status = EFI_DEVICE_ERROR;
+    goto UnmapDataBuffer;
+  }
+
+  VirtioPrepare (&Dev->Ring, &Indices);
 
   //
   // ensured by VirtioBlkInit() -- this predicate, in combination with the
@@ -291,8 +370,13 @@ SynchronousRequest (
   //
   // virtio-blk header in first desc
   //
-  VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,
-    VRING_DESC_F_NEXT, &Indices);
+  VirtioAppendDesc (
+    &Dev->Ring,
+    RequestDeviceAddress,
+    sizeof Request,
+    VRING_DESC_F_NEXT,
+    &Indices
+    );
 
   //
   // data buffer for read/write in second desc
@@ -311,27 +395,55 @@ SynchronousRequest (
     //
     // VRING_DESC_F_WRITE is interpreted from the host's point of view.
     //
-    VirtioAppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,
+    VirtioAppendDesc (
+      &Dev->Ring,
+      BufferDeviceAddress,
+      (UINT32) BufferSize,
       VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE),
-      &Indices);
+      &Indices
+      );
   }
 
   //
   // host status in last (second or third) desc
   //
-  VirtioAppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,
-    VRING_DESC_F_WRITE, &Indices);
+  VirtioAppendDesc (
+    &Dev->Ring,
+    HostStatusDeviceAddress,
+    sizeof *HostStatus,
+    VRING_DESC_F_WRITE,
+    &Indices
+    );
 
   //
   // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
   //
   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;
+  } else {
+    Status = EFI_DEVICE_ERROR;
   }
 
-  return EFI_DEVICE_ERROR;
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, StatusMapping);
+
+UnmapDataBuffer:
+  if (BufferSize > 0) {
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, BufferMapping);
+  }
+
+UnmapRequestBuffer:
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping);
+
+FreeHostStatusBuffer:
+  Dev->VirtIo->FreeSharedPages (
+                 Dev->VirtIo,
+                 EFI_SIZE_TO_PAGES (sizeof *HostStatus),
+                 HostStatusBuffer
+                 );
+
+  return Status;
 }
 
 
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v2 3/3] OvmfPkg/VirtioBlkDxe: negotiate VIRTIO_F_IOMMU_PLATFORM
  2017-08-28  0:34 [PATCH v2 0/3] OvmfPkg/VirtioBlkDxe: map host address to device address Brijesh Singh
  2017-08-28  0:34 ` [PATCH v2 1/3] OvmfPkg/VirtioBlkDxe: map VRING using VirtioRingMap() Brijesh Singh
  2017-08-28  0:34 ` [PATCH v2 2/3] Ovmfpkg/VirtioBlkDxe: map virtio-blk request and response buffers Brijesh Singh
@ 2017-08-28  0:34 ` Brijesh Singh
  2017-08-28  9:01 ` [PATCH v2 0/3] OvmfPkg/VirtioBlkDxe: map host address to device address Laszlo Ersek
  3 siblings, 0 replies; 6+ messages in thread
From: Brijesh Singh @ 2017-08-28  0:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

VirtioBlkDxe driver has been updated to use IOMMU-like member functions
from VIRTIO_DEVICE_PROTOCOL to translate the system physical address to
device address. We do not need to do anything special when
VIRTIO_F_IOMMU_PLATFORM bit is present hence treat it in parallel with
VIRTIO_F_VERSION_1.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index c9c42aa41243..6abd937f86c6 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -808,7 +808,8 @@ VirtioBlkInit (
   }
 
   Features &= VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_TOPOLOGY | VIRTIO_BLK_F_RO |
-              VIRTIO_BLK_F_FLUSH | VIRTIO_F_VERSION_1;
+              VIRTIO_BLK_F_FLUSH | VIRTIO_F_VERSION_1 |
+              VIRTIO_F_IOMMU_PLATFORM;
 
   //
   // In virtio-1.0, feature negotiation is expected to complete before queue
@@ -886,7 +887,7 @@ VirtioBlkInit (
   // step 5 -- Report understood features.
   //
   if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
-    Features &= ~(UINT64)VIRTIO_F_VERSION_1;
+    Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM);
     Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
     if (EFI_ERROR (Status)) {
       goto UnmapQueue;
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 2/3] Ovmfpkg/VirtioBlkDxe: map virtio-blk request and response buffers
  2017-08-28  0:34 ` [PATCH v2 2/3] Ovmfpkg/VirtioBlkDxe: map virtio-blk request and response buffers Brijesh Singh
@ 2017-08-28  8:10   ` Laszlo Ersek
  0 siblings, 0 replies; 6+ messages in thread
From: Laszlo Ersek @ 2017-08-28  8:10 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Ard Biesheuvel, Jordan Justen, Tom Lendacky

On 08/28/17 02:34, Brijesh Singh wrote:
> When device is behind the IOMMU, driver is require to pass the device
> address of virtio request, response and any memory referenced by those
> request/response to the bus master.
> 
> The patch uses IOMMU-like member functions from VIRTIO_DEVICE_PROTOCOL to
> map request and response buffers system physical address to the device
> address.
> 
> - If the buffer need to be accessed by both the processor and a bus
>   master then map with BusMasterCommonBuffer.
> 
> - If the buffer need to be accessed for a write operation by a bus master
>   then map with BusMasterWrite.
> 
> - If the buffer need to be accessed for a read  operation by a bus master
>   then map with BusMasterRead.
> 
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 138 ++++++++++++++++++--
>  1 file changed, 125 insertions(+), 13 deletions(-)

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Thanks!
Laszlo

> diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> index 663ba281ab73..c9c42aa41243 100644
> --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> @@ -232,7 +232,8 @@ VerifyReadWriteRequest (
>  
>    @retval EFI_DEVICE_ERROR     Failed to notify host side via VirtIo write, or
>                                 unable to parse host response, or host response
> -                               is not VIRTIO_BLK_S_OK.
> +                               is not VIRTIO_BLK_S_OK or failed to map Buffer
> +                               for a bus master operation.
>  
>  **/
>  
> @@ -249,8 +250,16 @@ SynchronousRequest (
>  {
>    UINT32                  BlockSize;
>    volatile VIRTIO_BLK_REQ Request;
> -  volatile UINT8          HostStatus;
> +  volatile UINT8          *HostStatus;
> +  VOID                    *HostStatusBuffer;
>    DESC_INDICES            Indices;
> +  VOID                    *RequestMapping;
> +  VOID                    *StatusMapping;
> +  VOID                    *BufferMapping;
> +  EFI_PHYSICAL_ADDRESS    BufferDeviceAddress;
> +  EFI_PHYSICAL_ADDRESS    HostStatusDeviceAddress;
> +  EFI_PHYSICAL_ADDRESS    RequestDeviceAddress;
> +  EFI_STATUS              Status;
>  
>    BlockSize = Dev->BlockIoMedia.BlockSize;
>  
> @@ -275,12 +284,82 @@ SynchronousRequest (
>    Request.IoPrio = 0;
>    Request.Sector = MultU64x32(Lba, BlockSize / 512);
>  
> -  VirtioPrepare (&Dev->Ring, &Indices);
> +  //
> +  // Host status is bi-directional (we preset with a value and expect the
> +  // device to update it). Allocate a host status buffer which can be mapped
> +  // to access equally by both processor and the device.
> +  //
> +  Status = Dev->VirtIo->AllocateSharedPages (
> +                          Dev->VirtIo,
> +                          EFI_SIZE_TO_PAGES (sizeof *HostStatus),
> +                          &HostStatusBuffer
> +                          );
> +  if (EFI_ERROR (Status)) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  HostStatus = HostStatusBuffer;
> +
> +  //
> +  // Map virtio-blk request header (must be done after request header is
> +  // populated)
> +  //
> +  Status = VirtioMapAllBytesInSharedBuffer (
> +             Dev->VirtIo,
> +             VirtioOperationBusMasterRead,
> +             (VOID *) &Request,
> +             sizeof Request,
> +             &RequestDeviceAddress,
> +             &RequestMapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    Status = EFI_DEVICE_ERROR;
> +    goto FreeHostStatusBuffer;
> +  }
> +
> +  //
> +  // Map data buffer
> +  //
> +  if (BufferSize > 0) {
> +    Status = VirtioMapAllBytesInSharedBuffer (
> +               Dev->VirtIo,
> +               (RequestIsWrite ?
> +                VirtioOperationBusMasterRead :
> +                VirtioOperationBusMasterWrite),
> +               (VOID *) Buffer,
> +               BufferSize,
> +               &BufferDeviceAddress,
> +               &BufferMapping
> +               );
> +    if (EFI_ERROR (Status)) {
> +      Status = EFI_DEVICE_ERROR;
> +      goto UnmapRequestBuffer;
> +    }
> +  }
>  
>    //
>    // preset a host status for ourselves that we do not accept as success
>    //
> -  HostStatus = VIRTIO_BLK_S_IOERR;
> +  *HostStatus = VIRTIO_BLK_S_IOERR;
> +
> +  //
> +  // Map the Status Buffer with VirtioOperationBusMasterCommonBuffer so that
> +  // both processor and device can access it.
> +  //
> +  Status = VirtioMapAllBytesInSharedBuffer (
> +             Dev->VirtIo,
> +             VirtioOperationBusMasterCommonBuffer,
> +             HostStatusBuffer,
> +             sizeof *HostStatus,
> +             &HostStatusDeviceAddress,
> +             &StatusMapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    Status = EFI_DEVICE_ERROR;
> +    goto UnmapDataBuffer;
> +  }
> +
> +  VirtioPrepare (&Dev->Ring, &Indices);
>  
>    //
>    // ensured by VirtioBlkInit() -- this predicate, in combination with the
> @@ -291,8 +370,13 @@ SynchronousRequest (
>    //
>    // virtio-blk header in first desc
>    //
> -  VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,
> -    VRING_DESC_F_NEXT, &Indices);
> +  VirtioAppendDesc (
> +    &Dev->Ring,
> +    RequestDeviceAddress,
> +    sizeof Request,
> +    VRING_DESC_F_NEXT,
> +    &Indices
> +    );
>  
>    //
>    // data buffer for read/write in second desc
> @@ -311,27 +395,55 @@ SynchronousRequest (
>      //
>      // VRING_DESC_F_WRITE is interpreted from the host's point of view.
>      //
> -    VirtioAppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,
> +    VirtioAppendDesc (
> +      &Dev->Ring,
> +      BufferDeviceAddress,
> +      (UINT32) BufferSize,
>        VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE),
> -      &Indices);
> +      &Indices
> +      );
>    }
>  
>    //
>    // host status in last (second or third) desc
>    //
> -  VirtioAppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,
> -    VRING_DESC_F_WRITE, &Indices);
> +  VirtioAppendDesc (
> +    &Dev->Ring,
> +    HostStatusDeviceAddress,
> +    sizeof *HostStatus,
> +    VRING_DESC_F_WRITE,
> +    &Indices
> +    );
>  
>    //
>    // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
>    //
>    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;
> +  } else {
> +    Status = EFI_DEVICE_ERROR;
>    }
>  
> -  return EFI_DEVICE_ERROR;
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, StatusMapping);
> +
> +UnmapDataBuffer:
> +  if (BufferSize > 0) {
> +    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, BufferMapping);
> +  }
> +
> +UnmapRequestBuffer:
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping);
> +
> +FreeHostStatusBuffer:
> +  Dev->VirtIo->FreeSharedPages (
> +                 Dev->VirtIo,
> +                 EFI_SIZE_TO_PAGES (sizeof *HostStatus),
> +                 HostStatusBuffer
> +                 );
> +
> +  return Status;
>  }
>  
>  
> 



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2 0/3] OvmfPkg/VirtioBlkDxe: map host address to device address
  2017-08-28  0:34 [PATCH v2 0/3] OvmfPkg/VirtioBlkDxe: map host address to device address Brijesh Singh
                   ` (2 preceding siblings ...)
  2017-08-28  0:34 ` [PATCH v2 3/3] OvmfPkg/VirtioBlkDxe: negotiate VIRTIO_F_IOMMU_PLATFORM Brijesh Singh
@ 2017-08-28  9:01 ` Laszlo Ersek
  3 siblings, 0 replies; 6+ messages in thread
From: Laszlo Ersek @ 2017-08-28  9:01 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/28/17 02:34, Brijesh Singh wrote:
> The patch updates the VirtioBlkDxe to use IOMMU-like member functions to map
> the system physical address to device address for buffers (including vring,
> device specific request and response pointed by vring descriptor, and any
> furter memory reference by those request and response).
> 
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> 
> Repo: https://github.com/codomania/edk2
> Branch: virtio-blk-2
> 
> Changes since v1:
>  * changes to address v1 feedback
> 
> Brijesh Singh (3):
>   OvmfPkg/VirtioBlkDxe: map VRING using VirtioRingMap()
>   Ovmfpkg/VirtioBlkDxe: map virtio-blk request and response buffers
>   OvmfPkg/VirtioBlkDxe: negotiate VIRTIO_F_IOMMU_PLATFORM
> 
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.h |   1 +
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 188 +++++++++++++++++---
>  2 files changed, 166 insertions(+), 23 deletions(-)
> 

test scenario     legacy PCI (X64) modern PCI (X64)
----------------  ---------------  ----------------
shell RECONNECT   PASS             PASS
shell LS/TYPE     PASS             PASS
ExitBootServices  PASS             PASS

Regression-tested-by: Laszlo Ersek <lersek@redhat.com>

Commit range a2285a896384..dd4205f8ba41.

Thanks,
Laszlo


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-08-28  8:59 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-28  0:34 [PATCH v2 0/3] OvmfPkg/VirtioBlkDxe: map host address to device address Brijesh Singh
2017-08-28  0:34 ` [PATCH v2 1/3] OvmfPkg/VirtioBlkDxe: map VRING using VirtioRingMap() Brijesh Singh
2017-08-28  0:34 ` [PATCH v2 2/3] Ovmfpkg/VirtioBlkDxe: map virtio-blk request and response buffers Brijesh Singh
2017-08-28  8:10   ` Laszlo Ersek
2017-08-28  0:34 ` [PATCH v2 3/3] OvmfPkg/VirtioBlkDxe: negotiate VIRTIO_F_IOMMU_PLATFORM Brijesh Singh
2017-08-28  9:01 ` [PATCH v2 0/3] OvmfPkg/VirtioBlkDxe: map host address to device address Laszlo Ersek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox