public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions
@ 2017-08-14 11:36 Brijesh Singh
  2017-08-14 11:36 ` [PATCH v2 01/23] OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute Brijesh Singh
                   ` (22 more replies)
  0 siblings, 23 replies; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

Currently, virtio drivers provides the system physical address to the device.
However, some systems may feature an IOMMU that requires the drivers to pass
the device addresses to the device - which are then translated by the IOMMU 
into physical addresses in memory. The patch series introduces new member
functions in VIRTIO_DEVICE_PROTOCOL which can be used for mapping a system
physical address to device address.

The approach that this patch series takes is to maps the system physical
address to device address for buffers (including rings, device specifc
request and response  pointed by vring descriptor, and any further memory 
reference by those request and response).

Patch 1 - 5:
 miscellaneous fixes

Patch 6 - 9:
 Defines and implements new member functions to map a system physical address
 to device address. The patch implements Laszlo's suggestion [1].

[1] http://mid.mail-archive.com/841bec5f-6f6e-8b1f-25ba-0fd37a915b72@redhat.com

Patch 10 - 16:
 Add some helper functions and allocate the vring using newly added member
 functions.

Patch 17:
 Update the virtio-rng driver to use newly added member functions to map the
 addresses.
 Verified using the following qemu cli

 # $QEMU \
    -device virtio-rng-pci

 # $QEMU \
    -device virtio-rng-pci,disable-legacy=on

 # $QEMU \
    -device virtio-rng-pci,disable-legacy=on,iommu_platform=true

 And succesfully ran RngTest.efi from SecurityPkg/Application

Patch 18:
 Update the virtio-blk driver to use newly added member functions to map the
 addresses.
 Verified using the following qemu cli

 # $QEMU \
    -drive file=${IMAGE},if=none,id=disk0 \
    -device virtio-blk-pci,drive=disk0

 # $QEMU \
    -drive file=${IMAGE},if=none,id=disk0 \
    -device virtio-blk-pci,drive=disk0,disable-legacy=on

 # $QEMU \
    -drive file=${IMAGE},if=none,id=disk0 \
    -device virtio-blk-pci,drive=disk0,disable-legacy=on,iommu_platform=true

Patch 19:
 Update the virtio-scsi driver to use newly added member functions to map the
 addresses.
 Verified using the following qemu cli

 # $QEMU \
    -drive file=${IMAGE},if=none,id=disk0 \
    -device scsi-hd,drive=disk0 \
    -device virtio-scsi-pci,id=scsi 

 # $QEMU \
    -drive file=${IMAGE},if=none,id=disk0 \
    -device scsi-hd,drive=disk0 \
    -device virtio-scsi-pci,id=scsi,disable-legacy=on 

 # $QEMU \
    -drive file=${IMAGE},if=none,id=disk0 \
    -device scsi-hd,drive=disk0 \
    -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true

Patch 20 - 22:
 Update the virtio-net driver to use newly added member functions to map the
 addresses.
 Verified using the following qemu cli

 # $QEMU \
    -netdev type=tap,id=net0 \
    -device virtio-net-pci,netdev=net0,romfile=

 # $QEMU \
    -netdev type=tap,id=net0 \
    -device virtio-net-pci,netdev=net0,disable-legacy=on,romfile=

 # $QEMU \
    -netdev type=tap,id=net0 \
    -device virtio-net-pci,netdev=net0,disable-legacy=on,iommu_platform=true,romfile=

Patch 23:
 Add support for VIRTIO_F_IOMMU_FEATURE bit

Repo: https://github.com/codomania/edk2
Branch: virtio-support-v2

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>

TODO:
 * Update VirtioGpuDxe
 * Runtime test on aarch64

Changes since v1:
 * changes to address v2 feedbacks
 * add VIRTIO_F_IOMMU_PLATFORM feature bit

Brijesh Singh (23):
  OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute
  OvmfPkg/Virtio10Dxe: supply missing BUS_MASTER attribute
  OvmfPkg/VirtioPciDeviceDxe: add missing IN and OUT decoration
  OvmfPkg/VirtioMmioDeviceLib: add missing IN and OUT decoration
  OvmfPkg/Virtio: fix comment style
  OvmfPkg/Virtio: introduce IOMMU-like member functions to
    VIRTIO_DEVICE_PROTOCOL
  OvmfPkg/Virtio10Dxe: implement IOMMU-like member functions
  OvmfPkg/VirtioPciDeviceDxe: implement IOMMU-like member functions
  OvmfPkg/VirtioMmioDeviceLib: implement IOMMU-like member functions
  OvmfPkg/VirtioLib: add VirtioMapAllBytesInSharedBuffer() helper
    function
  OvmfPkg/VirtioLib: take VirtIo instance in
    VirtioRingInit/VirtioRingUninit
  OvmfPkg/VirtioLib: add functions to map/unmap VRING
  OvmfPkg/Virtio: take RingBaseShift in VirtioSetQueueAddress()
  OvmfPkg/Virtio10Dxe: add the RingBaseShift offset
  OvmfPkg/VirtioLib: alloc vring buffer with AllocateSharedPages()
  OvmfPkg/VirtioRngDxe: map host address to device address
  OvmfPkg/VirtioBlkDxe: map host address to device address
  OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors
  OvmfPkg/VirtioNetDxe: alloc Tx and Rx rings using AllocateSharedPage()
  OvmfPkg/VirtioNetDxe: alloc RxBuf using AllocateSharedPages()
  OvmfPkg/VirtioNetDxe: dynamically alloc transmit header
  OvmfPkg/VirtioNetDxe: map transmit buffer host address to device
    address
  OvmfPkg/Virtio: define VIRITO_F_IOMMU_PLATFORM feature bit

 OvmfPkg/Include/IndustryStandard/Virtio10.h                     |   5 +
 OvmfPkg/Include/Library/VirtioLib.h                             |  83 +++++++++-
 OvmfPkg/Include/Protocol/VirtioDevice.h                         | 170 ++++++++++++++++++--
 OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h          |  65 ++++++--
 OvmfPkg/VirtioBlkDxe/VirtioBlk.h                                |   1 +
 OvmfPkg/VirtioNetDxe/VirtioNet.h                                |  25 ++-
 OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h                    |  61 +++++--
 OvmfPkg/VirtioRngDxe/VirtioRng.h                                |   1 +
 OvmfPkg/VirtioScsiDxe/VirtioScsi.h                              |   1 +
 OvmfPkg/Library/VirtioLib/VirtioLib.c                           | 150 ++++++++++++++++-
 OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c |  92 +++++++++--
 OvmfPkg/Virtio10Dxe/Virtio10.c                                  | 127 ++++++++++++++-
 OvmfPkg/VirtioBlkDxe/VirtioBlk.c                                | 131 +++++++++++++--
 OvmfPkg/VirtioGpuDxe/Commands.c                                 |  10 +-
 OvmfPkg/VirtioNetDxe/Events.c                                   |  19 +++
 OvmfPkg/VirtioNetDxe/SnpGetStatus.c                             |  19 ++-
 OvmfPkg/VirtioNetDxe/SnpInitialize.c                            | 168 +++++++++++++++----
 OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c                         | 127 ++++++++++++++-
 OvmfPkg/VirtioNetDxe/SnpShutdown.c                              |   5 +-
 OvmfPkg/VirtioNetDxe/SnpTransmit.c                              |  26 ++-
 OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c                    |  11 +-
 OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c                 |  87 ++++++++--
 OvmfPkg/VirtioRngDxe/VirtioRng.c                                |  74 +++++++--
 OvmfPkg/VirtioScsiDxe/VirtioScsi.c                              | 160 +++++++++++++++---
 24 files changed, 1437 insertions(+), 181 deletions(-)

-- 
2.7.4



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

* [PATCH v2 01/23] OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16  0:34   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 02/23] OvmfPkg/Virtio10Dxe: " Brijesh Singh
                   ` (21 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

Suggested-by: Laszlo Ersek <lersek@redhat.com>
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/VirtioPciDeviceDxe/VirtioPciDevice.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
index bc4f6fe8bfa3..e41730456471 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
@@ -460,7 +460,9 @@ VirtioPciDeviceBindingStart (
 
   Status = Device->PciIo->Attributes (Device->PciIo,
                          EfiPciIoAttributeOperationEnable,
-                         EFI_PCI_IO_ATTRIBUTE_IO, NULL);
+                         (EFI_PCI_IO_ATTRIBUTE_IO |
+                          EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
+                         NULL);
   if (EFI_ERROR (Status)) {
     goto ClosePciIo;
   }
-- 
2.7.4



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

* [PATCH v2 02/23] OvmfPkg/Virtio10Dxe: supply missing BUS_MASTER attribute
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
  2017-08-14 11:36 ` [PATCH v2 01/23] OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16  0:36   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 03/23] OvmfPkg/VirtioPciDeviceDxe: add missing IN and OUT decoration Brijesh Singh
                   ` (20 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

Suggested-by: Laszlo Ersek <lersek@redhat.com>
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/Virtio10Dxe/Virtio10.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
index a8a6a58c3f1d..43dcfd7cb2a4 100644
--- a/OvmfPkg/Virtio10Dxe/Virtio10.c
+++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
@@ -906,7 +906,7 @@ Virtio10BindingStart (
     goto ClosePciIo;
   }
 
-  SetAttributes = 0;
+  SetAttributes =  EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
   UpdateAttributes (&Device->CommonConfig, &SetAttributes);
   UpdateAttributes (&Device->NotifyConfig, &SetAttributes);
   UpdateAttributes (&Device->SpecificConfig, &SetAttributes);
-- 
2.7.4



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

* [PATCH v2 03/23] OvmfPkg/VirtioPciDeviceDxe: add missing IN and OUT decoration
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
  2017-08-14 11:36 ` [PATCH v2 01/23] OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute Brijesh Singh
  2017-08-14 11:36 ` [PATCH v2 02/23] OvmfPkg/Virtio10Dxe: " Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16  0:36   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 04/23] OvmfPkg/VirtioMmioDeviceLib: " Brijesh Singh
                   ` (19 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

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/VirtioPciDeviceDxe/VirtioPciDevice.h    | 24 ++++++++++----------
 OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c | 24 ++++++++++----------
 2 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
index 8f17a16c88f5..6f51f816ef0f 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
@@ -96,15 +96,15 @@ VirtioPciGetQueueSize (
 EFI_STATUS
 EFIAPI
 VirtioPciSetQueueAlignment (
-  VIRTIO_DEVICE_PROTOCOL         *This,
-  UINT32                         Alignment
+  IN  VIRTIO_DEVICE_PROTOCOL         *This,
+  IN  UINT32                         Alignment
   );
 
 EFI_STATUS
 EFIAPI
 VirtioPciSetPageSize (
-  VIRTIO_DEVICE_PROTOCOL         *This,
-  UINT32                         PageSize
+  IN  VIRTIO_DEVICE_PROTOCOL         *This,
+  IN  UINT32                         PageSize
   );
 
 EFI_STATUS
@@ -131,29 +131,29 @@ VirtioPciSetQueueAddress (
 EFI_STATUS
 EFIAPI
 VirtioPciSetQueueSel (
-  VIRTIO_DEVICE_PROTOCOL         *This,
-  UINT16                         Sel
+  IN  VIRTIO_DEVICE_PROTOCOL         *This,
+  IN  UINT16                         Sel
   );
 
 EFI_STATUS
 EFIAPI
 VirtioPciSetQueueNotify (
-  VIRTIO_DEVICE_PROTOCOL         *This,
-  UINT16                         Index
+  IN  VIRTIO_DEVICE_PROTOCOL         *This,
+  IN  UINT16                         Index
   );
 
 EFI_STATUS
 EFIAPI
 VirtioPciSetQueueSize (
-  VIRTIO_DEVICE_PROTOCOL         *This,
-  UINT16                         Size
+  IN  VIRTIO_DEVICE_PROTOCOL         *This,
+  IN  UINT16                         Size
   );
 
 EFI_STATUS
 EFIAPI
 VirtioPciSetDeviceStatus (
-  VIRTIO_DEVICE_PROTOCOL         *This,
-  UINT8                          DeviceStatus
+  IN  VIRTIO_DEVICE_PROTOCOL         *This,
+  IN  UINT8                          DeviceStatus
   );
 
 #endif // _VIRTIO_PCI_DEVICE_DXE_H_
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
index 243aa14c2421..5f86914265ea 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
@@ -196,8 +196,8 @@ VirtioPciSetQueueAddress (
 EFI_STATUS
 EFIAPI
 VirtioPciSetQueueSel (
-  VIRTIO_DEVICE_PROTOCOL    *This,
-  UINT16                    Sel
+  IN  VIRTIO_DEVICE_PROTOCOL    *This,
+  IN  UINT16                    Sel
   )
 {
   VIRTIO_PCI_DEVICE *Dev;
@@ -211,8 +211,8 @@ VirtioPciSetQueueSel (
 EFI_STATUS
 EFIAPI
 VirtioPciSetQueueAlignment (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT32                  Alignment
+  IN  VIRTIO_DEVICE_PROTOCOL *This,
+  IN  UINT32                  Alignment
   )
 {
   return EFI_SUCCESS;
@@ -221,8 +221,8 @@ VirtioPciSetQueueAlignment (
 EFI_STATUS
 EFIAPI
 VirtioPciSetPageSize (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT32                  PageSize
+  IN  VIRTIO_DEVICE_PROTOCOL *This,
+  IN  UINT32                  PageSize
   )
 {
   return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
@@ -231,8 +231,8 @@ VirtioPciSetPageSize (
 EFI_STATUS
 EFIAPI
 VirtioPciSetQueueNotify (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT16                 Index
+  IN  VIRTIO_DEVICE_PROTOCOL *This,
+  IN  UINT16                 Index
   )
 {
   VIRTIO_PCI_DEVICE *Dev;
@@ -246,8 +246,8 @@ VirtioPciSetQueueNotify (
 EFI_STATUS
 EFIAPI
 VirtioPciSetQueueSize (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT16                 Size
+  IN  VIRTIO_DEVICE_PROTOCOL *This,
+  IN  UINT16                 Size
   )
 {
   //
@@ -260,8 +260,8 @@ VirtioPciSetQueueSize (
 EFI_STATUS
 EFIAPI
 VirtioPciSetDeviceStatus (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT8                  DeviceStatus
+  IN  VIRTIO_DEVICE_PROTOCOL *This,
+  IN  UINT8                  DeviceStatus
   )
 {
   VIRTIO_PCI_DEVICE *Dev;
-- 
2.7.4



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

* [PATCH v2 04/23] OvmfPkg/VirtioMmioDeviceLib: add missing IN and OUT decoration
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (2 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 03/23] OvmfPkg/VirtioPciDeviceDxe: add missing IN and OUT decoration Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16  0:37   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 05/23] OvmfPkg/Virtio: fix comment style Brijesh Singh
                   ` (18 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

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/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h          | 28 ++++++++++----------
 OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c | 28 ++++++++++----------
 2 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
index 4130dbc043df..bedd635e1a86 100644
--- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
@@ -85,29 +85,29 @@ VirtioMmioGetDeviceStatus (
 EFI_STATUS
 EFIAPI
 VirtioMmioSetQueueSize (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT16                  QueueSize
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT16                  QueueSize
   );
 
 EFI_STATUS
 EFIAPI
 VirtioMmioSetDeviceStatus (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT8                   DeviceStatus
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT8                   DeviceStatus
   );
 
 EFI_STATUS
 EFIAPI
 VirtioMmioSetQueueNotify (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT16                  QueueNotify
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT16                  QueueNotify
   );
 
 EFI_STATUS
 EFIAPI
 VirtioMmioSetQueueSel (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT16                  Sel
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT16                  Sel
   );
 
 EFI_STATUS
@@ -119,22 +119,22 @@ VirtioMmioSetQueueAddress (
 EFI_STATUS
 EFIAPI
 VirtioMmioSetQueueAlignment (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT32                  Alignment
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT32                  Alignment
   );
 
 EFI_STATUS
 EFIAPI
 VirtioMmioSetPageSize (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT32                  PageSize
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT32                  PageSize
   );
 
 EFI_STATUS
 EFIAPI
 VirtioMmioSetGuestFeatures (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT64                  Features
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT64                  Features
   );
 
 #endif // _VIRTIO_MMIO_DEVICE_INTERNAL_H_
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
index 53c734f6b1af..9142d4a162c0 100644
--- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
@@ -81,8 +81,8 @@ VirtioMmioGetDeviceStatus (
 EFI_STATUS
 EFIAPI
 VirtioMmioSetQueueSize (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT16                  QueueSize
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT16                  QueueSize
   )
 {
   VIRTIO_MMIO_DEVICE *Device;
@@ -97,8 +97,8 @@ VirtioMmioSetQueueSize (
 EFI_STATUS
 EFIAPI
 VirtioMmioSetDeviceStatus (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT8                   DeviceStatus
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT8                   DeviceStatus
   )
 {
   VIRTIO_MMIO_DEVICE *Device;
@@ -113,8 +113,8 @@ VirtioMmioSetDeviceStatus (
 EFI_STATUS
 EFIAPI
 VirtioMmioSetQueueNotify (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT16                  QueueNotify
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT16                  QueueNotify
   )
 {
   VIRTIO_MMIO_DEVICE *Device;
@@ -129,8 +129,8 @@ VirtioMmioSetQueueNotify (
 EFI_STATUS
 EFIAPI
 VirtioMmioSetQueueAlignment (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT32                  Alignment
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT32                  Alignment
   )
 {
   VIRTIO_MMIO_DEVICE *Device;
@@ -145,8 +145,8 @@ VirtioMmioSetQueueAlignment (
 EFI_STATUS
 EFIAPI
 VirtioMmioSetPageSize (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT32                  PageSize
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT32                  PageSize
   )
 {
   VIRTIO_MMIO_DEVICE *Device;
@@ -165,8 +165,8 @@ VirtioMmioSetPageSize (
 EFI_STATUS
 EFIAPI
 VirtioMmioSetQueueSel (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT16                  Sel
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT16                  Sel
   )
 {
   VIRTIO_MMIO_DEVICE *Device;
@@ -197,8 +197,8 @@ VirtioMmioSetQueueAddress (
 EFI_STATUS
 EFIAPI
 VirtioMmioSetGuestFeatures (
-  VIRTIO_DEVICE_PROTOCOL *This,
-  UINT64                  Features
+  IN VIRTIO_DEVICE_PROTOCOL *This,
+  IN UINT64                  Features
   )
 {
   VIRTIO_MMIO_DEVICE *Device;
-- 
2.7.4



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

* [PATCH v2 05/23] OvmfPkg/Virtio: fix comment style
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (3 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 04/23] OvmfPkg/VirtioMmioDeviceLib: " Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16  0:41   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 06/23] OvmfPkg/Virtio: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL Brijesh Singh
                   ` (17 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

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/Include/Protocol/VirtioDevice.h | 22 +++++++++++++-------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
index 910a4866e7ac..edb20c18822c 100644
--- a/OvmfPkg/Include/Protocol/VirtioDevice.h
+++ b/OvmfPkg/Include/Protocol/VirtioDevice.h
@@ -320,16 +320,22 @@ EFI_STATUS
   );
 
 
-///
-///  This protocol provides an abstraction over the VirtIo transport layer
-///
-///  DISCLAIMER: this protocol is a work in progress, and should not be used
-///  outside of the EDK II tree.
-///
+/**
+
+  This protocol provides an abstraction over the VirtIo transport layer
+
+  DISCLAIMER: this protocol is a work in progress, and should not be used
+  outside of the EDK II tree.
+**/
+
 struct _VIRTIO_DEVICE_PROTOCOL {
-  /// VirtIo Specification Revision encoded with VIRTIO_SPEC_REVISION()
+  //
+  // VirtIo Specification Revision encoded with VIRTIO_SPEC_REVISION()
+  //
   UINT32                      Revision;
-  /// From the Virtio Spec
+  //
+  // From the Virtio Spec
+  //
   INT32                       SubSystemDeviceId;
 
   VIRTIO_GET_DEVICE_FEATURES  GetDeviceFeatures;
-- 
2.7.4



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

* [PATCH v2 06/23] OvmfPkg/Virtio: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (4 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 05/23] OvmfPkg/Virtio: fix comment style Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16 14:37   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 07/23] OvmfPkg/Virtio10Dxe: implement IOMMU-like member functions Brijesh Singh
                   ` (16 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

The patch extends VIRTIO_DEVICE_PROTOCOL to provide the following new
member functions:

- AllocateSharedPages : allocate a memory region suitable for sharing
   between guest and hypervisor (e.g ring buffer).

- FreeSharedPages: free the memory allocated using AllocateSharedPages ().

- MapSharedBuffer: map a host address to device address suitable to share
   with device for bus master operations.

- UnmapSharedBuffer: unmap the device address obtained through the
   MapSharedBuffer().

Suggested-by: Laszlo Ersek <lersek@redhat.com>
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/Include/Protocol/VirtioDevice.h | 143 ++++++++++++++++++++
 1 file changed, 143 insertions(+)

diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
index edb20c18822c..14f980d7bf0a 100644
--- a/OvmfPkg/Include/Protocol/VirtioDevice.h
+++ b/OvmfPkg/Include/Protocol/VirtioDevice.h
@@ -5,6 +5,7 @@
   and should not be used outside of the EDK II tree.
 
   Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -31,6 +32,25 @@
 
 typedef struct _VIRTIO_DEVICE_PROTOCOL  VIRTIO_DEVICE_PROTOCOL;
 
+//
+// VIRTIO Operation for VIRTIO_MAP_SHARED
+//
+typedef enum {
+  //
+  // A read operation from system memory by a bus master
+  //
+  VirtioOperationBusMasterRead,
+  //
+  // A write operation to system memory by a bus master
+  //
+  VirtioOperationBusMasterWrite,
+  //
+  // Provides both read and write access to system memory by both the
+  // processor and a bus master
+  //
+  VirtioOperationBusMasterCommonBuffer,
+} VIRTIO_MAP_OPERATION;
+
 /**
 
   Read a word from the device-specific I/O region of the Virtio Header.
@@ -319,6 +339,121 @@ EFI_STATUS
   IN UINT8                   DeviceStatus
   );
 
+/**
+
+  Allocates pages that are suitable for an VirtioOperationBusMasterCommonBuffer
+  mapping. This means that the buffer allocated by this function supports
+  simultaneous access by both the processor and the bus master. The device
+  address that the bus master uses to access the buffer must be retrieved with
+  a call to VIRTIO_MAP_SHARED.
+
+  @param[in]      This              The protocol instance pointer.
+
+  @param[in]      Pages             The number of pages to allocate.
+
+  @param[in,out]  HostAddress       A pointer to store the system memory base
+                                    address of the allocated range.
+
+  @retval EFI_SUCCESS               The requested memory pages were allocated.
+  @retval EFI_OUT_OF_RESOURCES      The memory pages could not be allocated.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VIRTIO_ALLOCATE_SHARED)(
+  IN     VIRTIO_DEVICE_PROTOCOL                   *This,
+  IN     UINTN                                    Pages,
+  IN OUT VOID                                     **HostAddress
+  );
+
+/**
+  Frees memory that was allocated with VIRTIO_ALLOCATE_SHARED.
+
+  @param[in]  This           The protocol instance pointer.
+
+  @param[in]  Pages          The number of pages to free.
+
+  @param[in]  HostAddress    The system memory base address of the allocated
+                             range.
+
+**/
+typedef
+VOID
+(EFIAPI *VIRTIO_FREE_SHARED)(
+  IN  VIRTIO_DEVICE_PROTOCOL                   *This,
+  IN  UINTN                                    Pages,
+  IN  VOID                                     *HostAddress
+  );
+
+/**
+  Provides the virtio device address required to access system memory from a
+  DMA bus master.
+
+  The interface follows the same usage pattern as defined in UEFI spec 2.6
+  (Section 13.2 PCI Root Bridge I/O Protocol)
+
+  @param[in]     This             The protocol instance pointer.
+
+  @param[in]     Operation        Indicates if the bus master is going to
+                                  read or write to system memory.
+
+  @param[in]     HostAddress      The system memory address to map to shared
+                                  buffer address.
+
+  @param[in,out] NumberOfBytes    On input the number of bytes to map.
+                                  On output the number of bytes that were
+                                  mapped.
+
+  @param[out]    DeviceAddress    The resulting shared map address for the
+                                  bus master to access the hosts HostAddress.
+
+  @param[out]    Mapping          A resulting taken to pass to
+                                  VIRTIO_UNMAP_SHARED.
+
+  @retval EFI_SUCCESS             The range was mapped for the returned
+                                  NumberOfBytes.
+  @retval EFI_UNSUPPORTED         The HostAddress cannot be mapped as a
+                                  common buffer.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to
+                                  a lack of resources.
+  @retval EFI_DEVICE_ERROR        The system hardware could not map the
+                                  requested address.
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *VIRTIO_MAP_SHARED) (
+  IN     VIRTIO_DEVICE_PROTOCOL       *This,
+  IN     VIRTIO_MAP_OPERATION         Operation,
+  IN     VOID                         *HostAddress,
+  IN OUT UINTN                        *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS         *DeviceAddress,
+  OUT    VOID                         **Mapping
+  );
+
+/**
+  Completes the VIRTIO_MAP_SHARED operation and releases any corresponding
+  resources.
+
+  @param[in]  This               The protocol instance pointer.
+
+  @param[in]  Mapping            The mapping token returned from
+                                 VIRTIO_MAP_SHARED.
+
+  @retval EFI_SUCCESS            The range was unmapped.
+  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by
+                                 VIRTIO_MAP_SHARED. Passing an invalid Mapping
+                                 token can cause undefined behavior.
+  @retval EFI_DEVICE_ERROR       The data was not committed to the target
+                                 system memory.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VIRTIO_UNMAP_SHARED)(
+  IN  VIRTIO_DEVICE_PROTOCOL    *This,
+  IN  VOID                      *Mapping
+  );
 
 /**
 
@@ -359,6 +494,14 @@ struct _VIRTIO_DEVICE_PROTOCOL {
   // Functions to read/write Device Specific headers
   VIRTIO_DEVICE_WRITE         WriteDevice;
   VIRTIO_DEVICE_READ          ReadDevice;
+
+  //
+  // Functions to allocate, free, map and unmap shared buffer
+  //
+  VIRTIO_ALLOCATE_SHARED      AllocateSharedPages;
+  VIRTIO_FREE_SHARED          FreeSharedPages;
+  VIRTIO_MAP_SHARED           MapSharedBuffer;
+  VIRTIO_UNMAP_SHARED         UnmapSharedBuffer;
 };
 
 extern EFI_GUID gVirtioDeviceProtocolGuid;
-- 
2.7.4



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

* [PATCH v2 07/23] OvmfPkg/Virtio10Dxe: implement IOMMU-like member functions
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (5 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 06/23] OvmfPkg/Virtio: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16 14:59   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 08/23] OvmfPkg/VirtioPciDeviceDxe: " Brijesh Singh
                   ` (15 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

The patch implements the newly added IOMMU-like member functions by
respectively delegating the job to:

- VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages() ->
    EFI_PCI_IO_PROTOCOL.AllocateBuffer()

- VIRTIO_DEVICE_PROTOCOL.FreeSharedPages() ->
    EFI_PCI_IO_PROTOCOL.FreeBuffer()

- VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer() ->
    EFI_PCI_IO_PROTOCOL.Map()

- VIRTIO_DEVICE_PROTOCOL.UnmapSharedBuffer() ->
    EFI_PCI_IO_PROTOCOL.Unmap()

Suggested-by: Laszlo Ersek <lersek@redhat.com>
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/Virtio10Dxe/Virtio10.c | 121 +++++++++++++++++++-
 1 file changed, 119 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
index 43dcfd7cb2a4..413ffa06cf35 100644
--- a/OvmfPkg/Virtio10Dxe/Virtio10.c
+++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
@@ -2,6 +2,7 @@
   A non-transitional driver for VirtIo 1.0 PCI devices.
 
   Copyright (C) 2016, Red Hat, Inc.
+  Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -15,6 +16,7 @@
 #include <IndustryStandard/Pci.h>
 #include <IndustryStandard/Virtio.h>
 #include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
 #include <Protocol/VirtioDevice.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
@@ -772,6 +774,117 @@ Virtio10ReadDevice (
   return Status;
 }
 
+STATIC
+EFI_STATUS
+EFIAPI
+Virtio10AllocateSharedPages (
+  IN     VIRTIO_DEVICE_PROTOCOL  *This,
+  IN     UINTN                   Pages,
+  IN OUT VOID                    **HostAddress
+  )
+{
+  VIRTIO_1_0_DEV *Dev;
+  EFI_STATUS     Status;
+
+  Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
+
+  Status = Dev->PciIo->AllocateBuffer (
+                         Dev->PciIo,
+                         AllocateAnyPages,
+                         EfiBootServicesData,
+                         Pages,
+                         HostAddress,
+                         EFI_PCI_ATTRIBUTE_MEMORY_CACHED
+                         );
+  return Status;
+}
+
+STATIC
+VOID
+EFIAPI
+Virtio10FreeSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,
+  IN  UINTN                   Pages,
+  IN  VOID                    *HostAddress
+  )
+{
+  VIRTIO_1_0_DEV *Dev;
+
+  Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
+
+  Dev->PciIo->FreeBuffer (
+                Dev->PciIo,
+                Pages,
+                HostAddress
+                );
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+Virtio10MapSharedBuffer (
+  IN     VIRTIO_DEVICE_PROTOCOL  *This,
+  IN     VIRTIO_MAP_OPERATION    Operation,
+  IN     VOID                    *HostAddress,
+  IN OUT UINTN                   *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS    *DeviceAddress,
+  OUT    VOID                    **Mapping
+  )
+{
+  EFI_STATUS                    Status;
+  VIRTIO_1_0_DEV                *Dev;
+  EFI_PCI_IO_PROTOCOL_OPERATION PciIoOperation;
+
+  Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
+
+  //
+  // Map VIRTIO_MAP_OPERATION to EFI_PCI_IO_PROTOCOL_OPERATION
+  //
+  switch (Operation) {
+  case VirtioOperationBusMasterRead:
+    PciIoOperation = EfiPciIoOperationBusMasterRead;
+    break;
+  case VirtioOperationBusMasterWrite:
+    PciIoOperation = EfiPciIoOperationBusMasterWrite;
+    break;
+  case VirtioOperationBusMasterCommonBuffer:
+    PciIoOperation = EfiPciIoOperationBusMasterCommonBuffer;
+    break;
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = Dev->PciIo->Map (
+                         Dev->PciIo,
+                         PciIoOperation,
+                         HostAddress,
+                         NumberOfBytes,
+                         DeviceAddress,
+                         Mapping
+                         );
+  return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+Virtio10UnmapSharedBuffer (
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,
+  IN  VOID                    *Mapping
+  )
+{
+  EFI_STATUS      Status;
+  VIRTIO_1_0_DEV  *Dev;
+
+  Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
+
+  Status = Dev->PciIo->Unmap (
+                         Dev->PciIo,
+                         Mapping
+                         );
+
+  return Status;
+}
 
 STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = {
   VIRTIO_SPEC_REVISION (1, 0, 0),
@@ -788,7 +901,11 @@ STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = {
   Virtio10GetDeviceStatus,
   Virtio10SetDeviceStatus,
   Virtio10WriteDevice,
-  Virtio10ReadDevice
+  Virtio10ReadDevice,
+  Virtio10AllocateSharedPages,
+  Virtio10FreeSharedPages,
+  Virtio10MapSharedBuffer,
+  Virtio10UnmapSharedBuffer
 };
 
 
@@ -906,7 +1023,7 @@ Virtio10BindingStart (
     goto ClosePciIo;
   }
 
-  SetAttributes =  EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
+  SetAttributes =  EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
   UpdateAttributes (&Device->CommonConfig, &SetAttributes);
   UpdateAttributes (&Device->NotifyConfig, &SetAttributes);
   UpdateAttributes (&Device->SpecificConfig, &SetAttributes);
-- 
2.7.4



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

* [PATCH v2 08/23] OvmfPkg/VirtioPciDeviceDxe: implement IOMMU-like member functions
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (6 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 07/23] OvmfPkg/Virtio10Dxe: implement IOMMU-like member functions Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16 15:32   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 09/23] OvmfPkg/VirtioMmioDeviceLib: " Brijesh Singh
                   ` (14 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

The patch implements the newly added IOMMU-like member functions by
respectively delegating the job to:

- VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages () ->
    MemoryAllocationLib.AllocatePages()

- VIRTIO_DEVICE_PROTOCOL.FreeSharedPages () ->
    MemoryAllocationLib.FreePages ()

- VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer () -> no-op

- VIRTIO_DEVICE_PROTOCOL.UnmapSharedBuffer () -> no-op

Suggested-by: Laszlo Ersek <lersek@redhat.com>
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/VirtioPciDeviceDxe/VirtioPciDevice.h    | 34 ++++++++++++
 OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c    |  7 ++-
 OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c | 58 ++++++++++++++++++++
 3 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
index 6f51f816ef0f..41df5a98e560 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
@@ -3,6 +3,7 @@
   Internal definitions for the VirtIo PCI Device driver
 
   Copyright (C) 2013, ARM Ltd
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -156,4 +157,37 @@ VirtioPciSetDeviceStatus (
   IN  UINT8                          DeviceStatus
   );
 
+EFI_STATUS
+EFIAPI
+VirtioPciAllocateSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL        *This,
+  IN  UINTN                         NumPages,
+  OUT VOID                          **HostAddress
+  );
+
+VOID
+EFIAPI
+VirtioPciFreeSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL        *This,
+  IN  UINTN                         NumPages,
+  IN  VOID                          *HostAddress
+  );
+
+EFI_STATUS
+EFIAPI
+VirtioPciMapSharedBuffer (
+  IN      VIRTIO_DEVICE_PROTOCOL        *This,
+  IN      VIRTIO_MAP_OPERATION          Operation,
+  IN      VOID                          *HostAddress,
+  IN OUT  UINTN                         *NumberOfBytes,
+  OUT     EFI_PHYSICAL_ADDRESS          *DeviceAddress,
+  OUT     VOID                          **Mapping
+  );
+
+EFI_STATUS
+EFIAPI
+VirtioPciUnmapSharedBuffer (
+  IN  VIRTIO_DEVICE_PROTOCOL        *This,
+  IN  VOID                          *Mapping
+  );
 #endif // _VIRTIO_PCI_DEVICE_DXE_H_
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
index e41730456471..b847f3c02528 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
@@ -5,6 +5,7 @@
   Copyright (C) 2012, Red Hat, Inc.
   Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
   Copyright (C) 2013, ARM Ltd.
+  Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -40,7 +41,11 @@ STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate = {
   VirtioPciGetDeviceStatus,             // GetDeviceStatus
   VirtioPciSetDeviceStatus,             // SetDeviceStatus
   VirtioPciDeviceWrite,                 // WriteDevice
-  VirtioPciDeviceRead                   // ReadDevice
+  VirtioPciDeviceRead,                  // ReadDevice
+  VirtioPciAllocateSharedPages,         // AllocateSharedPages
+  VirtioPciFreeSharedPages,             // FreeSharedPages
+  VirtioPciMapSharedBuffer,             // MapSharedBuffer
+  VirtioPciUnmapSharedBuffer,           // UnmapSharedBuffer
 };
 
 /**
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
index 5f86914265ea..4597095deb78 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
@@ -5,6 +5,7 @@
   Copyright (C) 2012, Red Hat, Inc.
   Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
   Copyright (C) 2013, ARM Ltd.
+  Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -271,3 +272,60 @@ VirtioPciSetDeviceStatus (
   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
       sizeof (UINT8), DeviceStatus);
 }
+
+EFI_STATUS
+EFIAPI
+VirtioPciAllocateSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,
+  IN  UINTN                   NumPages,
+  OUT VOID                    **HostAddress
+  )
+{
+  VOID        *Buffer;
+
+  Buffer = AllocatePages (NumPages);
+  if (Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  *HostAddress = Buffer;
+  return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+VirtioPciFreeSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,
+  IN  UINTN                   NumPages,
+  IN  VOID                    *HostAddress
+  )
+{
+  FreePages (HostAddress, NumPages);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciMapSharedBuffer (
+  IN      VIRTIO_DEVICE_PROTOCOL  *This,
+  IN      VIRTIO_MAP_OPERATION    Operation,
+  IN      VOID                    *HostAddress,
+  IN OUT  UINTN                   *NumberOfBytes,
+  OUT     EFI_PHYSICAL_ADDRESS    *DeviceAddress,
+  OUT     VOID                    **Mapping
+  )
+{
+  *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
+  *Mapping = NULL;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciUnmapSharedBuffer (
+  IN  VIRTIO_DEVICE_PROTOCOL    *This,
+  OUT VOID                      *Mapping
+  )
+{
+  return EFI_SUCCESS;
+}
-- 
2.7.4



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

* [PATCH v2 09/23] OvmfPkg/VirtioMmioDeviceLib: implement IOMMU-like member functions
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (7 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 08/23] OvmfPkg/VirtioPciDeviceDxe: " Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16 15:58   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 10/23] OvmfPkg/VirtioLib: add VirtioMapAllBytesInSharedBuffer() helper function Brijesh Singh
                   ` (13 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

The patch implements the newly added IOMMU-like member functions by
respectively delegating the job to:

- VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages () ->
    MemoryAllocationLib.AllocatePages()

- VIRTIO_DEVICE_PROTOCOL.FreeSharedPages () ->
    MemoryAllocationLib.FreePages ()

- VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer () -> no-op

- VIRTIO_DEVICE_PROTOCOL.UnmapSharedBuffer () -> no-op

Suggested-by: Laszlo Ersek <lersek@redhat.com>
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/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h          | 34 +++++++++++
 OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c | 59 ++++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
index bedd635e1a86..b69f6d7b7a85 100644
--- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
@@ -137,4 +137,38 @@ VirtioMmioSetGuestFeatures (
   IN UINT64                  Features
   );
 
+EFI_STATUS
+EFIAPI
+VirtioMmioAllocateSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL        *This,
+  IN  UINTN                         NumPages,
+  OUT VOID                          **HostAddress
+  );
+
+VOID
+EFIAPI
+VirtioMmioFreeSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL        *This,
+  IN  UINTN                         NumPages,
+  IN  VOID                          *HostAddress
+  );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioMapSharedBuffer (
+  IN      VIRTIO_DEVICE_PROTOCOL        *This,
+  IN      VIRTIO_MAP_OPERATION          Operation,
+  IN      VOID                          *HostAddress,
+  IN OUT  UINTN                         *NumberOfBytes,
+  OUT     EFI_PHYSICAL_ADDRESS          *DeviceAddress,
+  OUT     VOID                          **Mapping
+  );
+
+EFI_STATUS
+EFIAPI
+VirtioMmioUnmapSharedBuffer (
+  IN  VIRTIO_DEVICE_PROTOCOL        *This,
+  IN  VOID                          *Mapping
+  );
+
 #endif // _VIRTIO_MMIO_DEVICE_INTERNAL_H_
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
index 9142d4a162c0..f3f69f324c6c 100644
--- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
@@ -16,6 +16,8 @@
 
 **/
 
+#include <Library/MemoryAllocationLib.h>
+
 #include "VirtioMmioDevice.h"
 
 EFI_STATUS
@@ -293,3 +295,60 @@ VirtioMmioDeviceRead (
 
   return EFI_SUCCESS;
 }
+
+EFI_STATUS
+EFIAPI
+VirtioMmioAllocateSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,
+  IN  UINTN                   NumPages,
+  OUT VOID                    **HostAddress
+  )
+{
+  VOID        *Buffer;
+
+  Buffer = AllocatePages (NumPages);
+  if (Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  *HostAddress = Buffer;
+  return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+VirtioMmioFreeSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL  *This,
+  IN  UINTN                   NumPages,
+  IN  VOID                    *HostAddress
+  )
+{
+  FreePages (HostAddress, NumPages);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioMapSharedBuffer (
+  IN      VIRTIO_DEVICE_PROTOCOL  *This,
+  IN      VIRTIO_MAP_OPERATION    Operation,
+  IN      VOID                    *HostAddress,
+  IN OUT  UINTN                   *NumberOfBytes,
+  OUT     EFI_PHYSICAL_ADDRESS    *DeviceAddress,
+  OUT     VOID                    **Mapping
+  )
+{
+  *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
+  *Mapping = NULL;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioMmioUnmapSharedBuffer (
+  IN  VIRTIO_DEVICE_PROTOCOL    *This,
+  OUT VOID                      *Mapping
+  )
+{
+  return EFI_SUCCESS;
+}
-- 
2.7.4



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

* [PATCH v2 10/23] OvmfPkg/VirtioLib: add VirtioMapAllBytesInSharedBuffer() helper function
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (8 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 09/23] OvmfPkg/VirtioMmioDeviceLib: " Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16 16:47   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 11/23] OvmfPkg/VirtioLib: take VirtIo instance in VirtioRingInit/VirtioRingUninit Brijesh Singh
                   ` (12 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

The function can be used for mapping the system physical address to virtio
device address using VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer (). The
function helps centralizing error handling, and it allows caller to pass
in constant or other evaluated expression for NumberOfBytes.

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/Include/Library/VirtioLib.h   | 44 +++++++++++
 OvmfPkg/Library/VirtioLib/VirtioLib.c | 78 ++++++++++++++++++++
 2 files changed, 122 insertions(+)

diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
index 5badfb32917f..d8f24a5d68b1 100644
--- a/OvmfPkg/Include/Library/VirtioLib.h
+++ b/OvmfPkg/Include/Library/VirtioLib.h
@@ -3,6 +3,7 @@
   Declarations of utility functions used by virtio device drivers.
 
   Copyright (C) 2012-2016, Red Hat, Inc.
+  Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -235,4 +236,47 @@ Virtio10WriteFeatures (
   IN OUT UINT8                  *DeviceStatus
   );
 
+/**
+  Provides the virtio device address required to access system memory from a
+  DMA bus master.
+
+  @param[in]     This             The protocol instance pointer.
+
+  @param[in]     Operation        Indicates if the bus master is going to
+                                  read or write to system memory.
+
+  @param[in]     HostAddress      The system memory address to map to shared
+                                  buffer address.
+
+  @param[in,out] NumberOfBytes    On input the number of bytes to map.
+                                  On output the number of bytes that were
+                                  mapped.
+
+  @param[out]    DeviceAddress    The resulting shared map address for the
+                                  bus master to access the hosts HostAddress.
+
+  @param[out]    Mapping          A resulting taken to pass to
+                                  VIRTIO_UNMAP_SHARED.
+
+
+  @retval EFI_SUCCESS             The range was mapped for the returned
+                                  NumberOfBytes.
+  @retval EFI_UNSUPPORTED         The HostAddress cannot be mapped as a
+                                  common buffer.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to
+                                  a lack of resources.
+  @retval EFI_DEVICE_ERROR        The system hardware could not map the
+                                  requested address.
+**/
+EFI_STATUS
+EFIAPI
+VirtioMapAllBytesInSharedBuffer (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  VIRTIO_MAP_OPERATION    Operation,
+  IN  VOID                    *HostAddress,
+  IN  UINTN                   NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
+  OUT VOID                    **Mapping
+  );
 #endif // _VIRTIO_LIB_H_
diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
index 845f206369a3..ac0ae97f3692 100644
--- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
+++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
@@ -4,6 +4,7 @@
 
   Copyright (C) 2012-2016, Red Hat, Inc.
   Portion of Copyright (C) 2013, ARM Ltd.
+  Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -414,3 +415,80 @@ Virtio10WriteFeatures (
 
   return Status;
 }
+
+/**
+  Provides the virtio device address required to access system memory from a
+  DMA bus master.
+
+  @param[in]     This             The protocol instance pointer.
+
+  @param[in]     Operation        Indicates if the bus master is going to
+                                  read or write to system memory.
+
+  @param[in]     HostAddress      The system memory address to map to shared
+                                  buffer address.
+
+  @param[in,out] NumberOfBytes    On input the number of bytes to map.
+                                  On output the number of bytes that were
+                                  mapped.
+
+  @param[out]    DeviceAddress    The resulting shared map address for the
+                                  bus master to access the hosts HostAddress.
+
+  @param[out]    Mapping          A resulting taken to pass to
+                                  VIRTIO_UNMAP_SHARED.
+
+
+  @retval EFI_SUCCESS             The range was mapped for the returned
+                                  NumberOfBytes.
+  @retval EFI_UNSUPPORTED         The HostAddress cannot be mapped as a
+                                  common buffer.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to
+                                  a lack of resources.
+  @retval EFI_DEVICE_ERROR        The system hardware could not map the
+                                  requested address.
+**/
+EFI_STATUS
+EFIAPI
+VirtioMapAllBytesInSharedBuffer (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  VIRTIO_MAP_OPERATION    Operation,
+  IN  VOID                    *HostAddress,
+  IN  UINTN                   NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
+  OUT VOID                    **Mapping
+  )
+{
+  EFI_STATUS            Status;
+  VOID                  *MapInfo;
+  UINTN                 Size;
+  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
+
+  Size = NumberOfBytes;
+  Status = VirtIo->MapSharedBuffer (
+                     VirtIo,
+                     Operation,
+                     HostAddress,
+                     &Size,
+                     &PhysicalAddress,
+                     &MapInfo
+                     );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (Size < NumberOfBytes) {
+    goto Failed;
+  }
+
+  *Mapping = MapInfo;
+  *DeviceAddress = PhysicalAddress;
+
+  return EFI_SUCCESS;
+
+Failed:
+  VirtIo->UnmapSharedBuffer (VirtIo, MapInfo);
+  *Mapping = NULL;
+  return EFI_OUT_OF_RESOURCES;
+}
-- 
2.7.4



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

* [PATCH v2 11/23] OvmfPkg/VirtioLib: take VirtIo instance in VirtioRingInit/VirtioRingUninit
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (9 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 10/23] OvmfPkg/VirtioLib: add VirtioMapAllBytesInSharedBuffer() helper function Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16 16:53   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 12/23] OvmfPkg/VirtioLib: add functions to map/unmap VRING Brijesh Singh
                   ` (11 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

Passing the VirtIo protocol instance will allow the vring to use
VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages () to allocate vring buffer.

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/Include/Library/VirtioLib.h   | 14 ++++++++++----
 OvmfPkg/Library/VirtioLib/VirtioLib.c | 14 ++++++++++----
 OvmfPkg/VirtioBlkDxe/VirtioBlk.c      |  7 ++++---
 OvmfPkg/VirtioGpuDxe/Commands.c       |  7 ++++---
 OvmfPkg/VirtioNetDxe/SnpInitialize.c  |  9 +++++----
 OvmfPkg/VirtioNetDxe/SnpShutdown.c    |  5 +++--
 OvmfPkg/VirtioRngDxe/VirtioRng.c      |  7 ++++---
 OvmfPkg/VirtioScsiDxe/VirtioScsi.c    |  7 ++++---
 8 files changed, 44 insertions(+), 26 deletions(-)

diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
index d8f24a5d68b1..ca0b217a04eb 100644
--- a/OvmfPkg/Include/Library/VirtioLib.h
+++ b/OvmfPkg/Include/Library/VirtioLib.h
@@ -35,6 +35,8 @@
   - 1.1 Virtqueues,
   - 2.3 Virtqueue Configuration.
 
+  @param[in]  VirtIo            The virtio device which will use the ring.
+
   @param[in]                    The number of descriptors to allocate for the
                                 virtio ring, as requested by the host.
 
@@ -52,8 +54,9 @@
 EFI_STATUS
 EFIAPI
 VirtioRingInit (
-  IN  UINT16 QueueSize,
-  OUT VRING  *Ring
+  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
+  IN  UINT16                 QueueSize,
+  OUT VRING                  *Ring
   );
 
 
@@ -65,13 +68,16 @@ VirtioRingInit (
   invoking this function: the VSTAT_DRIVER_OK bit must be clear in
   VhdrDeviceStatus.
 
-  @param[out] Ring  The virtio ring to clean up.
+  @param[in]  VirtIo  The virtio device which was using the ring.
+
+  @param[out] Ring    The virtio ring to clean up.
 
 **/
 VOID
 EFIAPI
 VirtioRingUninit (
-  IN OUT VRING *Ring
+  IN     VIRTIO_DEVICE_PROTOCOL *VirtIo,
+  IN OUT VRING                  *Ring
   );
 
 
diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
index ac0ae97f3692..5b64d18a8d6f 100644
--- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
+++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
@@ -37,6 +37,8 @@
   - 1.1 Virtqueues,
   - 2.3 Virtqueue Configuration.
 
+  @param[in]  VirtIo            The virtio device which will use the ring.
+
   @param[in]                    The number of descriptors to allocate for the
                                 virtio ring, as requested by the host.
 
@@ -54,8 +56,9 @@
 EFI_STATUS
 EFIAPI
 VirtioRingInit (
-  IN  UINT16 QueueSize,
-  OUT VRING  *Ring
+  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
+  IN  UINT16                 QueueSize,
+  OUT VRING                  *Ring
   )
 {
   UINTN          RingSize;
@@ -128,13 +131,16 @@ VirtioRingInit (
   invoking this function: the VSTAT_DRIVER_OK bit must be clear in
   VhdrDeviceStatus.
 
-  @param[out] Ring  The virtio ring to clean up.
+  @param[in]  VirtIo  The virtio device which was using the ring.
+
+  @param[out] Ring    The virtio ring to clean up.
 
 **/
 VOID
 EFIAPI
 VirtioRingUninit (
-  IN OUT VRING *Ring
+  IN     VIRTIO_DEVICE_PROTOCOL *VirtIo,
+  IN OUT VRING                  *Ring
   )
 {
   FreePages (Ring->Base, Ring->NumPages);
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index 3ce72281c204..61b9cab4ff02 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -12,6 +12,7 @@
 
   Copyright (C) 2012, Red Hat, Inc.
   Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -722,7 +723,7 @@ VirtioBlkInit (
     goto Failed;
   }
 
-  Status = VirtioRingInit (QueueSize, &Dev->Ring);
+  Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring);
   if (EFI_ERROR (Status)) {
     goto Failed;
   }
@@ -811,7 +812,7 @@ VirtioBlkInit (
   return EFI_SUCCESS;
 
 ReleaseQueue:
-  VirtioRingUninit (&Dev->Ring);
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
 Failed:
   //
@@ -848,7 +849,7 @@ VirtioBlkUninit (
   //
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
 
-  VirtioRingUninit (&Dev->Ring);
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
   SetMem (&Dev->BlockIo,      sizeof Dev->BlockIo,      0x00);
   SetMem (&Dev->BlockIoMedia, sizeof Dev->BlockIoMedia, 0x00);
diff --git a/OvmfPkg/VirtioGpuDxe/Commands.c b/OvmfPkg/VirtioGpuDxe/Commands.c
index 962087cfec97..c2e4d72feb67 100644
--- a/OvmfPkg/VirtioGpuDxe/Commands.c
+++ b/OvmfPkg/VirtioGpuDxe/Commands.c
@@ -3,6 +3,7 @@
   VirtIo GPU initialization, and commands (primitives) for the GPU device.
 
   Copyright (C) 2016, Red Hat, Inc.
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -127,7 +128,7 @@ VirtioGpuInit (
   //
   // [...] population of virtqueues [...]
   //
-  Status = VirtioRingInit (QueueSize, &VgpuDev->Ring);
+  Status = VirtioRingInit (VgpuDev->VirtIo, QueueSize, &VgpuDev->Ring);
   if (EFI_ERROR (Status)) {
     goto Failed;
   }
@@ -148,7 +149,7 @@ VirtioGpuInit (
   return EFI_SUCCESS;
 
 ReleaseQueue:
-  VirtioRingUninit (&VgpuDev->Ring);
+  VirtioRingUninit (VgpuDev->VirtIo, &VgpuDev->Ring);
 
 Failed:
   //
@@ -183,7 +184,7 @@ VirtioGpuUninit (
   // configuration.
   //
   VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);
-  VirtioRingUninit (&VgpuDev->Ring);
+  VirtioRingUninit (VgpuDev->VirtIo, &VgpuDev->Ring);
 }
 
 /**
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index 430670a980f2..6d9b81a9f939 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -5,6 +5,7 @@
 
   Copyright (C) 2013, Red Hat, Inc.
   Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -73,7 +74,7 @@ VirtioNetInitRing (
   if (QueueSize < 2) {
     return EFI_UNSUPPORTED;
   }
-  Status = VirtioRingInit (QueueSize, Ring);
+  Status = VirtioRingInit (Dev->VirtIo, QueueSize, Ring);
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -103,7 +104,7 @@ VirtioNetInitRing (
   return EFI_SUCCESS;
 
 ReleaseQueue:
-  VirtioRingUninit (Ring);
+  VirtioRingUninit (Dev->VirtIo, Ring);
 
   return Status;
 }
@@ -509,10 +510,10 @@ AbortDevice:
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
 
 ReleaseTxRing:
-  VirtioRingUninit (&Dev->TxRing);
+  VirtioRingUninit (Dev->VirtIo, &Dev->TxRing);
 
 ReleaseRxRing:
-  VirtioRingUninit (&Dev->RxRing);
+  VirtioRingUninit (Dev->VirtIo, &Dev->RxRing);
 
 DeviceFailed:
   //
diff --git a/OvmfPkg/VirtioNetDxe/SnpShutdown.c b/OvmfPkg/VirtioNetDxe/SnpShutdown.c
index 01409c0ce714..5e84191fbbdd 100644
--- a/OvmfPkg/VirtioNetDxe/SnpShutdown.c
+++ b/OvmfPkg/VirtioNetDxe/SnpShutdown.c
@@ -4,6 +4,7 @@
 
   Copyright (C) 2013, Red Hat, Inc.
   Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -66,8 +67,8 @@ VirtioNetShutdown (
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
   VirtioNetShutdownRx (Dev);
   VirtioNetShutdownTx (Dev);
-  VirtioRingUninit (&Dev->TxRing);
-  VirtioRingUninit (&Dev->RxRing);
+  VirtioRingUninit (Dev->VirtIo, &Dev->TxRing);
+  VirtioRingUninit (Dev->VirtIo, &Dev->RxRing);
 
   Dev->Snm.State = EfiSimpleNetworkStarted;
   Status = EFI_SUCCESS;
diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.c b/OvmfPkg/VirtioRngDxe/VirtioRng.c
index 1a186d04082a..e20602ac7225 100644
--- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
+++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
@@ -6,6 +6,7 @@
 
   Copyright (C) 2012, Red Hat, Inc.
   Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
 
   This driver:
 
@@ -275,7 +276,7 @@ VirtioRngInit (
     goto Failed;
   }
 
-  Status = VirtioRingInit (QueueSize, &Dev->Ring);
+  Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring);
   if (EFI_ERROR (Status)) {
     goto Failed;
   }
@@ -331,7 +332,7 @@ VirtioRngInit (
   return EFI_SUCCESS;
 
 ReleaseQueue:
-  VirtioRingUninit (&Dev->Ring);
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
 Failed:
   //
@@ -358,7 +359,7 @@ VirtioRngUninit (
   // the old comms area.
   //
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
-  VirtioRingUninit (&Dev->Ring);
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 }
 
 //
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
index c080404330e5..c2f6f412ff40 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
@@ -27,6 +27,7 @@
 
   Copyright (C) 2012, Red Hat, Inc.
   Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -832,7 +833,7 @@ VirtioScsiInit (
     goto Failed;
   }
 
-  Status = VirtioRingInit (QueueSize, &Dev->Ring);
+  Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring);
   if (EFI_ERROR (Status)) {
     goto Failed;
   }
@@ -926,7 +927,7 @@ VirtioScsiInit (
   return EFI_SUCCESS;
 
 ReleaseQueue:
-  VirtioRingUninit (&Dev->Ring);
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
 Failed:
   //
@@ -964,7 +965,7 @@ VirtioScsiUninit (
   Dev->MaxLun         = 0;
   Dev->MaxSectors     = 0;
 
-  VirtioRingUninit (&Dev->Ring);
+  VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
   SetMem (&Dev->PassThru,     sizeof Dev->PassThru,     0x00);
   SetMem (&Dev->PassThruMode, sizeof Dev->PassThruMode, 0x00);
-- 
2.7.4



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

* [PATCH v2 12/23] OvmfPkg/VirtioLib: add functions to map/unmap VRING
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (10 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 11/23] OvmfPkg/VirtioLib: take VirtIo instance in VirtioRingInit/VirtioRingUninit Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16 20:56   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 13/23] OvmfPkg/Virtio: take RingBaseShift in VirtioSetQueueAddress() Brijesh Singh
                   ` (10 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

Add functions to map and unmap the ring buffer with BusMasterCommonBuffer
so that ring can be accessed by both guest and hypervisor.

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/Include/Library/VirtioLib.h   | 25 +++++++++++
 OvmfPkg/Library/VirtioLib/VirtioLib.c | 44 ++++++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
index ca0b217a04eb..1efb02a68cf1 100644
--- a/OvmfPkg/Include/Library/VirtioLib.h
+++ b/OvmfPkg/Include/Library/VirtioLib.h
@@ -62,6 +62,31 @@ VirtioRingInit (
 
 /**
 
+  Map the ring buffer so that it can be accessed equally by both guest
+  and hypervisor.
+
+  @param[in]      VirtIo          The virtio device instance.
+
+  @param[in]      Ring            The virtio ring to map.
+
+  @param[out]     RingBaseShift   
+
+  @param[out]     Mapping         A resulting token to pass to
+                                  VirtIo->UnmapSharedBuffer().
+
+  @return         Status from VirtIo->MapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioRingMap (
+  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
+  IN  VRING                  *Ring,
+  OUT UINT64                 *RingBaseShift,
+  OUT VOID                   **Mapping
+  );
+
+/**
+
   Tear down the internal resources of a configured virtio ring.
 
   The caller is responsible to stop the host from using this ring before
diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
index 5b64d18a8d6f..7d07dcc09d3d 100644
--- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
+++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
@@ -498,3 +498,47 @@ Failed:
   *Mapping = NULL;
   return EFI_OUT_OF_RESOURCES;
 }
+
+/**
+
+  Map the ring buffer so that it can be accessed equally by both guest
+  and hypervisor.
+
+  @param[in]      VirtIo          The virtio device instance.
+
+  @param[in]      Ring            The virtio ring to map.
+
+  @param[out]     RingBaseShift   RingBaseShift
+
+  @param[out]     Mapping         A resulting token to pass to
+                                  VirtIo->UnmapSharedBuffer().
+
+  @return         Status code from VirtIo->MapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioRingMap (
+  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
+  IN  VRING                  *Ring,
+  OUT UINT64                 *RingBaseShift,
+  OUT VOID                   **Mapping
+  )
+{
+  EFI_STATUS        Status;
+  PHYSICAL_ADDRESS  DeviceAddress;
+
+  Status = VirtioMapAllBytesInSharedBuffer (
+             VirtIo,
+             VirtioOperationBusMasterCommonBuffer,
+             Ring->Base,
+             EFI_PAGES_TO_SIZE (Ring->NumPages),
+             &DeviceAddress,
+             Mapping
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *RingBaseShift = DeviceAddress - (UINT64)(UINTN)Ring->Base;
+  return EFI_SUCCESS;
+}
-- 
2.7.4



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

* [PATCH v2 13/23] OvmfPkg/Virtio: take RingBaseShift in VirtioSetQueueAddress()
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (11 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 12/23] OvmfPkg/VirtioLib: add functions to map/unmap VRING Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16 21:43   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 14/23] OvmfPkg/Virtio10Dxe: add the RingBaseShift offset Brijesh Singh
                   ` (9 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

VirtioRingMap() maps the ring buffer system physical to a bus address.
When an IOMMU is used for translating the address then bus address can
start at a different offset from the system physical address.

- MMIO and legacy virtio device does not use IOMMU to translate the
  addresses hence RingBaseShift will always be set to zero.

- modern virtio device use IOMMU to translate the address, in next patch
  we will update the Virtio10Dxe to use RingBaseShift offset.

Suggested-by: Laszlo Ersek <lersek@redhat.com>
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/Include/Protocol/VirtioDevice.h                         | 5 ++++-
 OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h          | 3 ++-
 OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h                    | 3 ++-
 OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c | 5 ++++-
 OvmfPkg/Virtio10Dxe/Virtio10.c                                  | 5 ++++-
 OvmfPkg/VirtioBlkDxe/VirtioBlk.c                                | 2 +-
 OvmfPkg/VirtioGpuDxe/Commands.c                                 | 3 ++-
 OvmfPkg/VirtioNetDxe/SnpInitialize.c                            | 2 +-
 OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c                 | 5 ++++-
 OvmfPkg/VirtioRngDxe/VirtioRng.c                                | 2 +-
 OvmfPkg/VirtioScsiDxe/VirtioScsi.c                              | 2 +-
 11 files changed, 26 insertions(+), 11 deletions(-)

diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
index 14f980d7bf0a..25fd73b847a5 100644
--- a/OvmfPkg/Include/Protocol/VirtioDevice.h
+++ b/OvmfPkg/Include/Protocol/VirtioDevice.h
@@ -156,6 +156,8 @@ EFI_STATUS
   @param[in] Ring             The initialized VRING object to take the
                               addresses from.
 
+  @param[in] RingBaseShift    The offset for the Ring Base address.
+
   @retval EFI_SUCCESS         The data was written successfully.
   @retval EFI_UNSUPPORTED     The underlying IO device doesn't support the
                               provided address offset and write size.
@@ -164,7 +166,8 @@ typedef
 EFI_STATUS
 (EFIAPI *VIRTIO_SET_QUEUE_ADDRESS) (
   IN VIRTIO_DEVICE_PROTOCOL  *This,
-  IN VRING                   *Ring
+  IN VRING                   *Ring,
+  IN UINT64                  RingBaseShift
   );
 
 /**
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
index b69f6d7b7a85..b5cc091fe820 100644
--- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
@@ -113,7 +113,8 @@ VirtioMmioSetQueueSel (
 EFI_STATUS
 VirtioMmioSetQueueAddress (
   IN VIRTIO_DEVICE_PROTOCOL  *This,
-  IN VRING                   *Ring
+  IN VRING                   *Ring,
+  IN UINT64                  RingBaseShift
   );
 
 EFI_STATUS
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
index 41df5a98e560..1f0dc45d501e 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
@@ -126,7 +126,8 @@ EFI_STATUS
 EFIAPI
 VirtioPciSetQueueAddress (
   IN VIRTIO_DEVICE_PROTOCOL  *This,
-  IN VRING                   *Ring
+  IN VRING                   *Ring,
+  IN UINT64                  RingBaseShift
   );
 
 EFI_STATUS
diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
index f3f69f324c6c..3d14b1035e91 100644
--- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
+++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
@@ -183,11 +183,14 @@ VirtioMmioSetQueueSel (
 EFI_STATUS
 VirtioMmioSetQueueAddress (
   IN VIRTIO_DEVICE_PROTOCOL  *This,
-  IN VRING                   *Ring
+  IN VRING                   *Ring,
+  IN UINT64                  RingBaseShift
   )
 {
   VIRTIO_MMIO_DEVICE *Device;
 
+  ASSERT (RingBaseShift == 0);
+
   Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
 
   VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN,
diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
index 413ffa06cf35..d102e1fd8551 100644
--- a/OvmfPkg/Virtio10Dxe/Virtio10.c
+++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
@@ -489,7 +489,8 @@ EFI_STATUS
 EFIAPI
 Virtio10SetQueueAddress (
   IN VIRTIO_DEVICE_PROTOCOL  *This,
-  IN VRING                   *Ring
+  IN VRING                   *Ring,
+  IN UINT64                  RingBaseShift
   )
 {
   VIRTIO_1_0_DEV *Dev;
@@ -497,6 +498,8 @@ Virtio10SetQueueAddress (
   UINT64         Address;
   UINT16         Enable;
 
+  ASSERT (RingBaseShift == 0);
+
   Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
 
   Address = (UINTN)Ring->Desc;
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index 61b9cab4ff02..bff15fe3add1 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -745,7 +745,7 @@ VirtioBlkInit (
   //
   // step 4c -- Report GPFN (guest-physical frame number) of queue.
   //
-  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);
+  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);
   if (EFI_ERROR (Status)) {
     goto ReleaseQueue;
   }
diff --git a/OvmfPkg/VirtioGpuDxe/Commands.c b/OvmfPkg/VirtioGpuDxe/Commands.c
index c2e4d72feb67..df8ded99edff 100644
--- a/OvmfPkg/VirtioGpuDxe/Commands.c
+++ b/OvmfPkg/VirtioGpuDxe/Commands.c
@@ -132,7 +132,8 @@ VirtioGpuInit (
   if (EFI_ERROR (Status)) {
     goto Failed;
   }
-  Status = VgpuDev->VirtIo->SetQueueAddress (VgpuDev->VirtIo, &VgpuDev->Ring);
+  Status = VgpuDev->VirtIo->SetQueueAddress (VgpuDev->VirtIo,
+                              &VgpuDev->Ring, 0);
   if (EFI_ERROR (Status)) {
     goto ReleaseQueue;
   }
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index 6d9b81a9f939..0ecfe044a977 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -96,7 +96,7 @@ VirtioNetInitRing (
   //
   // step 4c -- report GPFN (guest-physical frame number) of queue
   //
-  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring);
+  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring, 0);
   if (EFI_ERROR (Status)) {
     goto ReleaseQueue;
   }
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
index 4597095deb78..86f752e1651f 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
@@ -183,11 +183,14 @@ EFI_STATUS
 EFIAPI
 VirtioPciSetQueueAddress (
   IN VIRTIO_DEVICE_PROTOCOL  *This,
-  IN VRING                   *Ring
+  IN VRING                   *Ring,
+  IN UINT64                  RingBaseShift
   )
 {
   VIRTIO_PCI_DEVICE *Dev;
 
+  ASSERT (RingBaseShift == 0);
+
   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
 
   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.c b/OvmfPkg/VirtioRngDxe/VirtioRng.c
index e20602ac7225..0abca488e6cd 100644
--- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
+++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
@@ -298,7 +298,7 @@ VirtioRngInit (
   //
   // step 4c -- Report GPFN (guest-physical frame number) of queue.
   //
-  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);
+  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);
   if (EFI_ERROR (Status)) {
     goto ReleaseQueue;
   }
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
index c2f6f412ff40..a983b3df7b9c 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
@@ -855,7 +855,7 @@ VirtioScsiInit (
   //
   // step 4c -- Report GPFN (guest-physical frame number) of queue.
   //
-  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);
+  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);
   if (EFI_ERROR (Status)) {
     goto ReleaseQueue;
   }
-- 
2.7.4



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

* [PATCH v2 14/23] OvmfPkg/Virtio10Dxe: add the RingBaseShift offset
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (12 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 13/23] OvmfPkg/Virtio: take RingBaseShift in VirtioSetQueueAddress() Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16 21:57   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 15/23] OvmfPkg/VirtioLib: alloc vring buffer with AllocateSharedPages() Brijesh Singh
                   ` (8 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

virtio drivers uses VirtioRingMap() to map the ring buffer host address
to a device address. If an IOMMU is present then RingBaseShift contains
the offset from the host address.

Suggested-by: Laszlo Ersek <lersek@redhat.com>
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/Virtio10Dxe/Virtio10.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
index d102e1fd8551..e9041dec91a4 100644
--- a/OvmfPkg/Virtio10Dxe/Virtio10.c
+++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
@@ -498,11 +498,10 @@ Virtio10SetQueueAddress (
   UINT64         Address;
   UINT16         Enable;
 
-  ASSERT (RingBaseShift == 0);
-
   Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
 
   Address = (UINTN)Ring->Desc;
+  Address += RingBaseShift;
   Status = Virtio10Transfer (Dev->PciIo, &Dev->CommonConfig, TRUE,
              OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueDesc),
              sizeof Address, &Address);
@@ -511,6 +510,7 @@ Virtio10SetQueueAddress (
   }
 
   Address = (UINTN)Ring->Avail.Flags;
+  Address += RingBaseShift;
   Status = Virtio10Transfer (Dev->PciIo, &Dev->CommonConfig, TRUE,
              OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueAvail),
              sizeof Address, &Address);
@@ -519,6 +519,7 @@ Virtio10SetQueueAddress (
   }
 
   Address = (UINTN)Ring->Used.Flags;
+  Address += RingBaseShift;
   Status = Virtio10Transfer (Dev->PciIo, &Dev->CommonConfig, TRUE,
              OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueUsed),
              sizeof Address, &Address);
-- 
2.7.4



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

* [PATCH v2 15/23] OvmfPkg/VirtioLib: alloc vring buffer with AllocateSharedPages()
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (13 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 14/23] OvmfPkg/Virtio10Dxe: add the RingBaseShift offset Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-16 22:18   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 16/23] OvmfPkg/VirtioRngDxe: map host address to device address Brijesh Singh
                   ` (7 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

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/Library/VirtioLib/VirtioLib.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
index 7d07dcc09d3d..8010b5cf4735 100644
--- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
+++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
@@ -61,6 +61,7 @@ VirtioRingInit (
   OUT VRING                  *Ring
   )
 {
+  EFI_STATUS     Status;
   UINTN          RingSize;
   volatile UINT8 *RingPagesPtr;
 
@@ -79,9 +80,16 @@ VirtioRingInit (
                 sizeof *Ring->Used.AvailEvent,
                 EFI_PAGE_SIZE);
 
+  //
+  // Allocate a shared ring buffer
+  //
   Ring->NumPages = EFI_SIZE_TO_PAGES (RingSize);
-  Ring->Base = AllocatePages (Ring->NumPages);
-  if (Ring->Base == NULL) {
+  Status = VirtIo->AllocateSharedPages (
+                          VirtIo,
+                          Ring->NumPages,
+                          &Ring->Base
+                          );
+  if (EFI_ERROR (Status)) {
     return EFI_OUT_OF_RESOURCES;
   }
   SetMem (Ring->Base, RingSize, 0x00);
@@ -143,7 +151,7 @@ VirtioRingUninit (
   IN OUT VRING                  *Ring
   )
 {
-  FreePages (Ring->Base, Ring->NumPages);
+  VirtIo->FreeSharedPages (VirtIo, Ring->NumPages, Ring->Base);
   SetMem (Ring, sizeof *Ring, 0x00);
 }
 
-- 
2.7.4



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

* [PATCH v2 16/23] OvmfPkg/VirtioRngDxe: map host address to device address
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (14 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 15/23] OvmfPkg/VirtioLib: alloc vring buffer with AllocateSharedPages() Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-21 14:05   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 17/23] OvmfPkg/VirtioBlkDxe: " Brijesh Singh
                   ` (6 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

patch maps the host address to a device address for buffers (including
rings, device specifc request and response pointed by vring descriptor,
and any further 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>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/VirtioRngDxe/VirtioRng.h |  1 +
 OvmfPkg/VirtioRngDxe/VirtioRng.c | 65 +++++++++++++++++---
 2 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.h b/OvmfPkg/VirtioRngDxe/VirtioRng.h
index 998f9fae48c2..b372d84c1ebc 100644
--- a/OvmfPkg/VirtioRngDxe/VirtioRng.h
+++ b/OvmfPkg/VirtioRngDxe/VirtioRng.h
@@ -38,6 +38,7 @@ typedef struct {
   EFI_EVENT                 ExitBoot;       // DriverBindingStart   0
   VRING                     Ring;           // VirtioRingInit       2
   EFI_RNG_PROTOCOL          Rng;            // VirtioRngInit        1
+  VOID                      *RingMap;       // VirtioRngInit        1
 } VIRTIO_RNG_DEV;
 
 #define VIRTIO_ENTROPY_SOURCE_FROM_RNG(RngPointer) \
diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.c b/OvmfPkg/VirtioRngDxe/VirtioRng.c
index 0abca488e6cd..fc01f1996654 100644
--- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
+++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
@@ -140,6 +140,8 @@ VirtioRngGetRNG (
   UINT32                    Len;
   UINT32                    BufferSize;
   EFI_STATUS                Status;
+  EFI_PHYSICAL_ADDRESS      DeviceAddress;
+  VOID                      *Mapping;
 
   if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {
     return EFI_INVALID_PARAMETER;
@@ -159,6 +161,20 @@ VirtioRngGetRNG (
   }
 
   Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
+  //
+  // Map the Buffers system phyiscal address to device address
+  //
+  Status = VirtioMapAllBytesInSharedBuffer (
+             Dev->VirtIo,
+             VirtioOperationBusMasterWrite,
+             (VOID *)Buffer,
+             RNGValueLength,
+             &DeviceAddress,
+             &Mapping
+             );
+  if (EFI_ERROR (Status)) {
+    goto FreeBuffer;
+  }
 
   //
   // The Virtio RNG device may return less data than we asked it to, and can
@@ -170,7 +186,7 @@ VirtioRngGetRNG (
 
     VirtioPrepare (&Dev->Ring, &Indices);
     VirtioAppendDesc (&Dev->Ring,
-      (UINTN)Buffer + Index,
+      (UINTN)DeviceAddress + Index,
       BufferSize,
       VRING_DESC_F_WRITE,
       &Indices);
@@ -178,17 +194,30 @@ VirtioRngGetRNG (
     if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=
         EFI_SUCCESS) {
       Status = EFI_DEVICE_ERROR;
-      goto FreeBuffer;
+      goto UnmapBuffer;
     }
     ASSERT (Len > 0);
     ASSERT (Len <= BufferSize);
   }
 
+  //
+  // Unmap the device buffer before accesing it.
+  //
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
+
   for (Index = 0; Index < RNGValueLength; Index++) {
     RNGValue[Index] = Buffer[Index];
   }
   Status = EFI_SUCCESS;
 
+  //
+  // Buffer is already Unmaped(), goto free it.
+  //
+  goto FreeBuffer;
+
+UnmapBuffer:
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
+
 FreeBuffer:
   FreePool ((VOID *)Buffer);
   return Status;
@@ -205,6 +234,7 @@ VirtioRngInit (
   EFI_STATUS Status;
   UINT16     QueueSize;
   UINT64     Features;
+  UINT64     RingBaseShift;
 
   //
   // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
@@ -281,26 +311,33 @@ VirtioRngInit (
     goto Failed;
   }
 
+  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.
   //
   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;
   }
 
   //
@@ -310,7 +347,7 @@ VirtioRngInit (
     Features &= ~(UINT64)VIRTIO_F_VERSION_1;
     Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
     if (EFI_ERROR (Status)) {
-      goto ReleaseQueue;
+      goto UnmapQueue;
     }
   }
 
@@ -320,7 +357,7 @@ VirtioRngInit (
   NextDevStat |= VSTAT_DRIVER_OK;
   Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
   if (EFI_ERROR (Status)) {
-    goto ReleaseQueue;
+    goto UnmapQueue;
   }
 
   //
@@ -331,6 +368,9 @@ VirtioRngInit (
 
   return EFI_SUCCESS;
 
+UnmapQueue:
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
+
 ReleaseQueue:
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
@@ -359,6 +399,9 @@ VirtioRngUninit (
   // the old comms area.
   //
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
+
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
+
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 }
 
@@ -385,6 +428,12 @@ VirtioRngExitBoot (
   //
   Dev = Context;
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
+
+  //
+  // Umap the ring buffer so that hypervisor will not able to get readable data
+  // after device reset.
+  //
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
 }
 
 
-- 
2.7.4



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

* [PATCH v2 17/23] OvmfPkg/VirtioBlkDxe: map host address to device address
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (15 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 16/23] OvmfPkg/VirtioRngDxe: map host address to device address Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-21 15:24   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 18/23] OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors Brijesh Singh
                   ` (5 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

The SynchronousRequest(), programs the vring descriptor with the buffers
pointed-by virtio-blk requests, status and memory that is referenced
inside the request header.

The patch uses VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer() function to map
host address to device address and programs the vring descriptor with
device addresses.

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.h |   1 +
 OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 121 +++++++++++++++++---
 2 files changed, 109 insertions(+), 13 deletions(-)

diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h
index 6c402ca88ea4..612994d261bc 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                   *RingMapping;         // VirtioBlkInit       1
 } VBLK_DEV;
 
 #define VIRTIO_BLK_FROM_BLOCK_IO(BlockIoPointer) \
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index bff15fe3add1..57baceb20a19 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -251,6 +251,11 @@ SynchronousRequest (
   volatile VIRTIO_BLK_REQ Request;
   volatile UINT8          HostStatus;
   DESC_INDICES            Indices;
+  VOID                    *RequestMapping;
+  VOID                    *StatusMapping;
+  VOID                    *BufferMapping;
+  EFI_PHYSICAL_ADDRESS    DeviceAddress;
+  EFI_STATUS              Status;
 
   BlockSize = Dev->BlockIoMedia.BlockSize;
 
@@ -289,14 +294,30 @@ SynchronousRequest (
   ASSERT (Dev->Ring.QueueSize >= 3);
 
   //
+  // Map virtio-blk request header
+  //
+  Status = VirtioMapAllBytesInSharedBuffer (
+             Dev->VirtIo,
+             VirtioOperationBusMasterRead,
+             (VOID *) &Request,
+             sizeof Request,
+             &DeviceAddress,
+             &RequestMapping
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
   // virtio-blk header in first desc
   //
-  VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,
+  VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress, sizeof Request,
     VRING_DESC_F_NEXT, &Indices);
 
   //
   // data buffer for read/write in second desc
   //
+  BufferMapping = NULL;
   if (BufferSize > 0) {
     //
     // From virtio-0.9.5, 2.3.2 Descriptor Table:
@@ -309,29 +330,86 @@ SynchronousRequest (
     ASSERT (BufferSize <= SIZE_1GB);
 
     //
+    // Map data buffer
+    //
+    if (RequestIsWrite) {
+      Status = VirtioMapAllBytesInSharedBuffer (
+                 Dev->VirtIo,
+                 VirtioOperationBusMasterRead,
+                 (VOID *) Buffer,
+                 BufferSize,
+                 &DeviceAddress,
+                 &BufferMapping
+                 );
+    } else {
+      Status = VirtioMapAllBytesInSharedBuffer (
+                 Dev->VirtIo,
+                 VirtioOperationBusMasterWrite,
+                 (VOID *) Buffer,
+                 BufferSize,
+                 &DeviceAddress,
+                 &BufferMapping
+                 );
+    }
+
+    if (EFI_ERROR (Status)) {
+      goto Unmap_Request_Buffer;
+    }
+
+    //
     // VRING_DESC_F_WRITE is interpreted from the host's point of view.
     //
-    VirtioAppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,
+    VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress, (UINT32) BufferSize,
       VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE),
       &Indices);
   }
 
   //
+  // Map virtio-blk status header
+  //
+  Status = VirtioMapAllBytesInSharedBuffer (
+             Dev->VirtIo,
+             VirtioOperationBusMasterWrite,
+             (VOID *) &HostStatus,
+             sizeof HostStatus,
+             &DeviceAddress,
+             &StatusMapping
+             );
+  if (EFI_ERROR (Status)) {
+    goto Unmap_Data_Buffer;
+  }
+
+  //
   // host status in last (second or third) desc
   //
-  VirtioAppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,
+  VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress, 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 &&
+  if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, NULL) != EFI_SUCCESS) {
+    Status = EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Unmap the HostStatus buffer before accessing it
+  //
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, StatusMapping);
+
+  if (Status != EFI_DEVICE_ERROR &&
       HostStatus == VIRTIO_BLK_S_OK) {
-    return EFI_SUCCESS;
+    Status = EFI_SUCCESS;
+  } else {
+    Status = EFI_DEVICE_ERROR;
   }
 
-  return EFI_DEVICE_ERROR;
+Unmap_Data_Buffer:
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, BufferMapping);
+Unmap_Request_Buffer:
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping);
+
+  return Status;
 }
 
 
@@ -601,6 +679,7 @@ VirtioBlkInit (
   UINT8      AlignmentOffset;
   UINT32     OptIoSize;
   UINT16     QueueSize;
+  UINT64     RingBaseShift;
 
   PhysicalBlockExp = 0;
   AlignmentOffset = 0;
@@ -728,26 +807,33 @@ VirtioBlkInit (
     goto Failed;
   }
 
+  Status = VirtioRingMap (Dev->VirtIo, &Dev->Ring, &RingBaseShift,
+             &Dev->RingMapping);
+  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.
   //
   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 +844,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 +854,7 @@ VirtioBlkInit (
   NextDevStat |= VSTAT_DRIVER_OK;
   Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
   if (EFI_ERROR (Status)) {
-    goto ReleaseQueue;
+    goto UnmapQueue;
   }
 
   //
@@ -811,7 +897,10 @@ VirtioBlkInit (
   }
   return EFI_SUCCESS;
 
+UnmapQueue:
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMapping);
 ReleaseQueue:
+
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
 Failed:
@@ -885,6 +974,12 @@ VirtioBlkExitBoot (
   //
   Dev = Context;
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
+
+  //
+  // Unmap the ring buffer so that hypervisor can not get a readable data
+  // after device is reset.
+  //
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMapping);
 }
 
 /**
-- 
2.7.4



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

* [PATCH v2 18/23] OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (16 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 17/23] OvmfPkg/VirtioBlkDxe: " Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-21 19:08   ` Laszlo Ersek
  2017-08-14 11:36 ` [PATCH v2 19/23] OvmfPkg/VirtioNetDxe: alloc Tx and Rx rings using AllocateSharedPage() Brijesh Singh
                   ` (4 subsequent siblings)
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

The VirtioScsiPassThru(), programs the vring descriptor using the host
addresses pointed-by virtio-scsi request, response and memory that is
referenced inside the request and response header.

The patch uses newly introduced VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer()
function to map system memory to device address and programs the vring
descriptors with device addresses.

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/VirtioScsiDxe/VirtioScsi.h |   1 +
 OvmfPkg/VirtioScsiDxe/VirtioScsi.c | 148 +++++++++++++++++---
 2 files changed, 133 insertions(+), 16 deletions(-)

diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h b/OvmfPkg/VirtioScsiDxe/VirtioScsi.h
index 6d00567e8cb8..bb1c5c70ef74 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.h
@@ -60,6 +60,7 @@ typedef struct {
   VRING                           Ring;           // VirtioRingInit      2
   EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;       // VirtioScsiInit      1
   EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;   // VirtioScsiInit      1
+  VOID                            *RingBufMapping;// VirtioScsiInit      1
 } VSCSI_DEV;
 
 #define VIRTIO_SCSI_FROM_PASS_THRU(PassThruPointer) \
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
index a983b3df7b9c..65e9bda0827a 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
@@ -409,8 +409,13 @@ VirtioScsiPassThru (
   UINT16                    TargetValue;
   EFI_STATUS                Status;
   volatile VIRTIO_SCSI_REQ  Request;
-  volatile VIRTIO_SCSI_RESP Response;
+  VIRTIO_SCSI_RESP          *Response;
   DESC_INDICES              Indices;
+  VOID                      *RequestMapping;
+  VOID                      *ResponseMapping;
+  VOID                      *InDataMapping;
+  VOID                      *OutDataMapping;
+  EFI_PHYSICAL_ADDRESS      DeviceAddress;
 
   ZeroMem ((VOID*) &Request, sizeof (Request));
   ZeroMem ((VOID*) &Response, sizeof (Response));
@@ -418,9 +423,41 @@ VirtioScsiPassThru (
   Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
   CopyMem (&TargetValue, Target, sizeof TargetValue);
 
+  Response = NULL;
+  ResponseMapping = NULL;
+  RequestMapping = NULL;
+  InDataMapping = NULL;
+  OutDataMapping = NULL;
+
+  //
+  // Response header is bi-direction (we preset with host status and expect the
+  // device to update it). Allocate a response buffer which can be mapped to
+  // access equally by both processor and device.
+  //
+  Status = Dev->VirtIo->AllocateSharedPages (
+                          Dev->VirtIo,
+                          EFI_SIZE_TO_PAGES (sizeof *Response),
+                          (VOID *) &Response
+                          );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = VirtioMapAllBytesInSharedBuffer (
+             Dev->VirtIo,
+             VirtioOperationBusMasterCommonBuffer,
+             (VOID *) Response,
+             sizeof (*Response),
+             &DeviceAddress,
+             &ResponseMapping
+             );
+  if (EFI_ERROR (Status)) {
+    goto Free_Response_Buffer;
+  }
+
   Status = PopulateRequest (Dev, TargetValue, Lun, Packet, &Request);
   if (EFI_ERROR (Status)) {
-    return Status;
+    goto Unmap_Response_Buffer;
   }
 
   VirtioPrepare (&Dev->Ring, &Indices);
@@ -428,7 +465,7 @@ VirtioScsiPassThru (
   //
   // preset a host status for ourselves that we do not accept as success
   //
-  Response.Response = VIRTIO_SCSI_S_FAILURE;
+  Response->Response = VIRTIO_SCSI_S_FAILURE;
 
   //
   // ensured by VirtioScsiInit() -- this predicate, in combination with the
@@ -437,23 +474,51 @@ VirtioScsiPassThru (
   ASSERT (Dev->Ring.QueueSize >= 4);
 
   //
+  // Map the scsi-blk request header HostAddress to DeviceAddress
+  //
+  Status = VirtioMapAllBytesInSharedBuffer (
+             Dev->VirtIo,
+             VirtioOperationBusMasterRead,
+             (VOID *) &Request,
+             sizeof Request,
+             &DeviceAddress,
+             &RequestMapping);
+  if (EFI_ERROR (Status)) {
+    goto Unmap_Response_Buffer;
+  }
+
+  //
   // enqueue Request
   //
-  VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,
+  VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress, sizeof Request,
     VRING_DESC_F_NEXT, &Indices);
 
   //
   // enqueue "dataout" if any
   //
   if (Packet->OutTransferLength > 0) {
-    VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->OutDataBuffer,
+    //
+    // Map the buffer address to a device address
+    //
+    Status = VirtioMapAllBytesInSharedBuffer (
+               Dev->VirtIo,
+               VirtioOperationBusMasterRead,
+               Packet->OutDataBuffer,
+               Packet->OutTransferLength,
+               &DeviceAddress,
+               &OutDataMapping
+               );
+    if (EFI_ERROR (Status)) {
+      goto Unmap_Request_Buffer;
+    }
+    VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress,
       Packet->OutTransferLength, VRING_DESC_F_NEXT, &Indices);
   }
 
   //
   // enqueue Response, to be written by the host
   //
-  VirtioAppendDesc (&Dev->Ring, (UINTN) &Response, sizeof Response,
+  VirtioAppendDesc (&Dev->Ring, (UINTN) Response, sizeof *Response,
     VRING_DESC_F_WRITE | (Packet->InTransferLength > 0 ?
                           VRING_DESC_F_NEXT : 0),
     &Indices);
@@ -462,7 +527,22 @@ VirtioScsiPassThru (
   // enqueue "datain" if any, to be written by the host
   //
   if (Packet->InTransferLength > 0) {
-    VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->InDataBuffer,
+    //
+    // Map the buffer address to a device address
+    //
+    Status = VirtioMapAllBytesInSharedBuffer (
+               Dev->VirtIo,
+               VirtioOperationBusMasterWrite,
+               Packet->InDataBuffer,
+               Packet->InTransferLength,
+               &DeviceAddress,
+               &InDataMapping
+               );
+    if (EFI_ERROR (Status)) {
+      goto Unmap_Out_Buffer;
+    }
+
+    VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress,
       Packet->InTransferLength, VRING_DESC_F_WRITE, &Indices);
   }
 
@@ -480,7 +560,29 @@ VirtioScsiPassThru (
     return EFI_DEVICE_ERROR;
   }
 
-  return ParseResponse (Packet, &Response);
+  Status = ParseResponse (Packet, Response);
+
+  if (Packet->InTransferLength > 0) {
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, InDataMapping);
+  }
+
+Unmap_Out_Buffer:
+  if (Packet->OutTransferLength > 0) {
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, OutDataMapping);
+  }
+
+Unmap_Request_Buffer:
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping);
+Unmap_Response_Buffer:
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, ResponseMapping);
+Free_Response_Buffer:
+  Dev->VirtIo->FreeSharedPages (
+                 Dev->VirtIo,
+                 EFI_SIZE_TO_PAGES (sizeof *Response),
+                 (VOID *) Response
+                 );
+
+  return Status;
 }
 
 
@@ -707,7 +809,7 @@ VirtioScsiInit (
 {
   UINT8      NextDevStat;
   EFI_STATUS Status;
-
+  UINT64     RingBaseShift;
   UINT64     Features;
   UINT16     MaxChannel; // for validation only
   UINT32     NumQueues;  // for validation only
@@ -838,18 +940,24 @@ VirtioScsiInit (
     goto Failed;
   }
 
+  Status = VirtioRingMap (Dev->VirtIo, &Dev->Ring, &RingBaseShift,
+             &Dev->RingBufMapping);
+  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.
   //
   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;
   }
 
   //
@@ -857,7 +965,7 @@ VirtioScsiInit (
   //
   Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);
   if (EFI_ERROR (Status)) {
-    goto ReleaseQueue;
+    goto UnmapQueue;
   }
 
   //
@@ -867,7 +975,7 @@ VirtioScsiInit (
     Features &= ~(UINT64)VIRTIO_F_VERSION_1;
     Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
     if (EFI_ERROR (Status)) {
-      goto ReleaseQueue;
+      goto UnmapQueue;
     }
   }
 
@@ -877,11 +985,11 @@ VirtioScsiInit (
   //
   Status = VIRTIO_CFG_WRITE (Dev, CdbSize, VIRTIO_SCSI_CDB_SIZE);
   if (EFI_ERROR (Status)) {
-    goto ReleaseQueue;
+    goto UnmapQueue;
   }
   Status = VIRTIO_CFG_WRITE (Dev, SenseSize, VIRTIO_SCSI_SENSE_SIZE);
   if (EFI_ERROR (Status)) {
-    goto ReleaseQueue;
+    goto UnmapQueue;
   }
 
   //
@@ -890,7 +998,7 @@ VirtioScsiInit (
   NextDevStat |= VSTAT_DRIVER_OK;
   Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
   if (EFI_ERROR (Status)) {
-    goto ReleaseQueue;
+    goto UnmapQueue;
   }
 
   //
@@ -926,6 +1034,8 @@ VirtioScsiInit (
 
   return EFI_SUCCESS;
 
+UnmapQueue:
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingBufMapping);
 ReleaseQueue:
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
@@ -995,6 +1105,12 @@ VirtioScsiExitBoot (
   //
   Dev = Context;
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
+
+  //
+  // If Ring buffer mapping exist then unmap it so that hypervisor can
+  // not get readable data after device reset.
+  //
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingBufMapping);
 }
 
 
-- 
2.7.4



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

* [PATCH v2 19/23] OvmfPkg/VirtioNetDxe: alloc Tx and Rx rings using AllocateSharedPage()
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (17 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 18/23] OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-14 11:36 ` [PATCH v2 20/23] OvmfPkg/VirtioNetDxe: alloc RxBuf using AllocateSharedPages() Brijesh Singh
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

The Tx and Rx rings are accessed by both guest and hypervisor, allocate
the rings using newly added VirtIo->AllocateSharedPages() and map it with
BusMasterCommonBuffer so that it can be accessed by both guest and
hypervisor.

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/VirtioNetDxe/VirtioNet.h     |  2 ++
 OvmfPkg/VirtioNetDxe/Events.c        |  7 +++++
 OvmfPkg/VirtioNetDxe/SnpInitialize.c | 28 +++++++++++++++-----
 3 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.h b/OvmfPkg/VirtioNetDxe/VirtioNet.h
index 710859bc6115..2964c946e26e 100644
--- a/OvmfPkg/VirtioNetDxe/VirtioNet.h
+++ b/OvmfPkg/VirtioNetDxe/VirtioNet.h
@@ -82,10 +82,12 @@ typedef struct {
   EFI_HANDLE                  MacHandle;         // VirtioNetDriverBindingStart
 
   VRING                       RxRing;            // VirtioNetInitRing
+  VOID                        *RxRingMap;        // VirtioNetInitRing
   UINT8                       *RxBuf;            // VirtioNetInitRx
   UINT16                      RxLastUsed;        // VirtioNetInitRx
 
   VRING                       TxRing;            // VirtioNetInitRing
+  VOID                        *TxRingMap;        // VirtioNetInitRing
   UINT16                      TxMaxPending;      // VirtioNetInitTx
   UINT16                      TxCurPending;      // VirtioNetInitTx
   UINT16                      *TxFreeStack;      // VirtioNetInitTx
diff --git a/OvmfPkg/VirtioNetDxe/Events.c b/OvmfPkg/VirtioNetDxe/Events.c
index 5be1af6ffbee..e832d40f7be4 100644
--- a/OvmfPkg/VirtioNetDxe/Events.c
+++ b/OvmfPkg/VirtioNetDxe/Events.c
@@ -88,4 +88,11 @@ VirtioNetExitBoot (
   if (Dev->Snm.State == EfiSimpleNetworkInitialized) {
     Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
   }
+
+  //
+  // Unmap Tx and Rx rings so that hypervisor can not get readable data
+  // after device is reset.
+  //
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->TxRingMap);
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxRingMap);
 }
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index 0ecfe044a977..be2761d3d068 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -35,6 +35,7 @@
                            the network device.
   @param[out]    Ring      The virtio-ring inside the VNET_DEV structure,
                            corresponding to Selector.
+  @param[out]    Mapping   A token return from the Map.
 
   @retval EFI_UNSUPPORTED  The queue size reported by the virtio-net device is
                            too small.
@@ -49,11 +50,13 @@ EFIAPI
 VirtioNetInitRing (
   IN OUT VNET_DEV *Dev,
   IN     UINT16   Selector,
-  OUT    VRING    *Ring
+  OUT    VRING    *Ring,
+  OUT    VOID     **Mapping
   )
 {
   EFI_STATUS Status;
   UINT16     QueueSize;
+  UINT64     RingBaseShift;
 
   //
   // step 4b -- allocate selected queue
@@ -79,30 +82,37 @@ VirtioNetInitRing (
     return Status;
   }
 
+  Status = VirtioRingMap (Dev->VirtIo, Ring, &RingBaseShift, Mapping);
+  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.
   //
   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, Ring, 0);
+  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring, RingBaseShift);
   if (EFI_ERROR (Status)) {
-    goto ReleaseQueue;
+    goto UnmapQueue;
   }
 
   return EFI_SUCCESS;
 
+UnmapQueue:
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
 ReleaseQueue:
   VirtioRingUninit (Dev->VirtIo, Ring);
 
@@ -456,12 +466,14 @@ VirtioNetInitialize (
   //
   // step 4b, 4c -- allocate and report virtqueues
   //
-  Status = VirtioNetInitRing (Dev, VIRTIO_NET_Q_RX, &Dev->RxRing);
+  Status = VirtioNetInitRing (Dev, VIRTIO_NET_Q_RX, &Dev->RxRing,
+             &Dev->RxRingMap);
   if (EFI_ERROR (Status)) {
     goto DeviceFailed;
   }
 
-  Status = VirtioNetInitRing (Dev, VIRTIO_NET_Q_TX, &Dev->TxRing);
+  Status = VirtioNetInitRing (Dev, VIRTIO_NET_Q_TX, &Dev->TxRing,
+             &Dev->TxRingMap);
   if (EFI_ERROR (Status)) {
     goto ReleaseRxRing;
   }
@@ -510,9 +522,11 @@ AbortDevice:
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
 
 ReleaseTxRing:
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->TxRingMap);
   VirtioRingUninit (Dev->VirtIo, &Dev->TxRing);
 
 ReleaseRxRing:
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxRingMap);
   VirtioRingUninit (Dev->VirtIo, &Dev->RxRing);
 
 DeviceFailed:
-- 
2.7.4



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

* [PATCH v2 20/23] OvmfPkg/VirtioNetDxe: alloc RxBuf using AllocateSharedPages()
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (18 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 19/23] OvmfPkg/VirtioNetDxe: alloc Tx and Rx rings using AllocateSharedPage() Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-14 11:36 ` [PATCH v2 21/23] OvmfPkg/VirtioNetDxe: dynamically alloc transmit header Brijesh Singh
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

RxBuf is shared between guest and hypervisor, use AllocateSharedPages()
to allocate this memory region and map it with BusMasterCommonBuffer
operation so that it can be accessed by guest and hypervisor.

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/VirtioNetDxe/VirtioNet.h        |  3 +
 OvmfPkg/VirtioNetDxe/Events.c           |  6 ++
 OvmfPkg/VirtioNetDxe/SnpInitialize.c    | 68 ++++++++++++++++----
 OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c |  6 +-
 4 files changed, 69 insertions(+), 14 deletions(-)

diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.h b/OvmfPkg/VirtioNetDxe/VirtioNet.h
index 2964c946e26e..a4661bd5d2fe 100644
--- a/OvmfPkg/VirtioNetDxe/VirtioNet.h
+++ b/OvmfPkg/VirtioNetDxe/VirtioNet.h
@@ -4,6 +4,7 @@
   Protocol instances for virtio-net devices.
 
   Copyright (C) 2013, Red Hat, Inc.
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -85,6 +86,8 @@ typedef struct {
   VOID                        *RxRingMap;        // VirtioNetInitRing
   UINT8                       *RxBuf;            // VirtioNetInitRx
   UINT16                      RxLastUsed;        // VirtioNetInitRx
+  UINTN                       RxBufNoPages;      // VirtioNetInitRx
+  VOID                        *RxBufMap;         // VirtioNetInitRx
 
   VRING                       TxRing;            // VirtioNetInitRing
   VOID                        *TxRingMap;        // VirtioNetInitRing
diff --git a/OvmfPkg/VirtioNetDxe/Events.c b/OvmfPkg/VirtioNetDxe/Events.c
index e832d40f7be4..2f61da6aece4 100644
--- a/OvmfPkg/VirtioNetDxe/Events.c
+++ b/OvmfPkg/VirtioNetDxe/Events.c
@@ -95,4 +95,10 @@ VirtioNetExitBoot (
   //
   Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->TxRingMap);
   Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxRingMap);
+
+  //
+  // Unmap Rx buffer so that hypervisor can not get readable data after
+  // device is reset.
+  //
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
 }
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index be2761d3d068..db2314446bbb 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -247,13 +247,16 @@ VirtioNetInitRx (
   IN OUT VNET_DEV *Dev
   )
 {
-  EFI_STATUS Status;
-  UINTN      VirtioNetReqSize;
-  UINTN      RxBufSize;
-  UINT16     RxAlwaysPending;
-  UINTN      PktIdx;
-  UINT16     DescIdx;
-  UINT8      *RxPtr;
+  EFI_STATUS            Status;
+  UINTN                 VirtioNetReqSize;
+  UINTN                 RxBufSize;
+  UINT16                RxAlwaysPending;
+  UINTN                 PktIdx;
+  UINT16                DescIdx;
+  UINT8                 *RxPtr;
+  UINTN                 NumBytes;
+  EFI_PHYSICAL_ADDRESS  DeviceAddress;
+  UINT64                BufBaseShift;
 
   //
   // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on
@@ -278,11 +281,37 @@ VirtioNetInitRx (
   //
   RxAlwaysPending = (UINT16) MIN (Dev->RxRing.QueueSize / 2, VNET_MAX_PENDING);
 
-  Dev->RxBuf = AllocatePool (RxAlwaysPending * RxBufSize);
-  if (Dev->RxBuf == NULL) {
-    return EFI_OUT_OF_RESOURCES;
+  //
+  // The RxBuf is shared between guest and hypervisor, use SharedPages() to
+  // allocate this memory region and Map() it using BusMasterCommonBuffer
+  // operation so that it can be accessed equally by both guest and
+  // hypervisor.
+  //
+  NumBytes = RxAlwaysPending * RxBufSize;
+  Dev->RxBufNoPages = EFI_SIZE_TO_PAGES (NumBytes);
+  Status = Dev->VirtIo->AllocateSharedPages (
+                          Dev->VirtIo,
+                          Dev->RxBufNoPages,
+                          (VOID *) &Dev->RxBuf
+                          );
+  if (EFI_ERROR (Status)) {
+    return Status;
   }
 
+  Status = VirtioMapAllBytesInSharedBuffer (
+             Dev->VirtIo,
+             VirtioOperationBusMasterCommonBuffer,
+             Dev->RxBuf,
+             NumBytes,
+             &DeviceAddress,
+             &Dev->RxBufMap
+             );
+  if (EFI_ERROR (Status)) {
+    goto FreeSharedBuffer;
+  }
+
+  BufBaseShift = (UINT64) (UINTN)Dev->RxBuf - (UINT64) DeviceAddress;
+
   //
   // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
   //
@@ -304,6 +333,11 @@ VirtioNetInitRx (
   DescIdx = 0;
   RxPtr = Dev->RxBuf;
   for (PktIdx = 0; PktIdx < RxAlwaysPending; ++PktIdx) {
+    UINT64    Address;
+
+    Address = (UINTN) RxPtr;
+    Address += BufBaseShift;
+
     //
     // virtio-0.9.5, 2.4.1.2 Updating the Available Ring
     // invisible to the host until we update the Index Field
@@ -313,13 +347,13 @@ VirtioNetInitRx (
     //
     // virtio-0.9.5, 2.4.1.1 Placing Buffers into the Descriptor Table
     //
-    Dev->RxRing.Desc[DescIdx].Addr  = (UINTN) RxPtr;
+    Dev->RxRing.Desc[DescIdx].Addr  = (UINTN) Address;
     Dev->RxRing.Desc[DescIdx].Len   = (UINT32) VirtioNetReqSize;
     Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;
     Dev->RxRing.Desc[DescIdx].Next  = (UINT16) (DescIdx + 1);
     RxPtr += Dev->RxRing.Desc[DescIdx++].Len;
 
-    Dev->RxRing.Desc[DescIdx].Addr  = (UINTN) RxPtr;
+    Dev->RxRing.Desc[DescIdx].Addr  = (UINTN) Address;
     Dev->RxRing.Desc[DescIdx].Len   = (UINT32) (RxBufSize - VirtioNetReqSize);
     Dev->RxRing.Desc[DescIdx].Flags = VRING_DESC_F_WRITE;
     RxPtr += Dev->RxRing.Desc[DescIdx++].Len;
@@ -343,10 +377,18 @@ VirtioNetInitRx (
   Status = Dev->VirtIo->SetQueueNotify (Dev->VirtIo, VIRTIO_NET_Q_RX);
   if (EFI_ERROR (Status)) {
     Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
-    FreePool (Dev->RxBuf);
+    goto UnmapSharedBuffer;
   }
 
   return Status;
+
+UnmapSharedBuffer:
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
+
+FreeSharedBuffer:
+  Dev->VirtIo->FreeSharedPages (Dev->VirtIo, Dev->RxBufNoPages,
+                 (VOID *) Dev->RxBuf);
+  return Status;
 }
 
 
diff --git a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
index 9fedb72fdbd4..ec8e63ebdc32 100644
--- a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
+++ b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
@@ -39,7 +39,11 @@ VirtioNetShutdownRx (
   IN OUT VNET_DEV *Dev
   )
 {
-  FreePool (Dev->RxBuf);
+  Dev->VirtIo->FreeSharedPages (
+                 Dev->VirtIo,
+                 Dev->RxBufNoPages,
+                 (VOID *) Dev->RxBuf
+                 );
 }
 
 
-- 
2.7.4



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

* [PATCH v2 21/23] OvmfPkg/VirtioNetDxe: dynamically alloc transmit header
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (19 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 20/23] OvmfPkg/VirtioNetDxe: alloc RxBuf using AllocateSharedPages() Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-14 11:36 ` [PATCH v2 22/23] OvmfPkg/VirtioNetDxe: map transmit buffer host address to device address Brijesh Singh
  2017-08-14 11:36 ` [PATCH v2 23/23] OvmfPkg/Virtio: define VIRITO_F_IOMMU_PLATFORM feature bit Brijesh Singh
  22 siblings, 0 replies; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

A network packets are transmitted by placing then into a transmit queue,
each packet is preceded by a VIRTIO_1_0_NET_REQ header. VirtioNetInitTx(),
builds the header once and fills the vring descriptors with the system
physical address of header.

The patch uses VirtIo->AllocateSharedPages() to allocate the header buffer
and map it with BusMasterCommonBuffer so that it can be equally accessed by
both processor and device.

We could map it with  BusMasterRead but since the header pointer is
used after it was added into vring hence I choose to dynamically allocate
it and map it with BusMasterCommonBuffer to avoid the code complexity.

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/VirtioNetDxe/VirtioNet.h        |  3 +-
 OvmfPkg/VirtioNetDxe/Events.c           |  6 ++
 OvmfPkg/VirtioNetDxe/SnpInitialize.c    | 60 +++++++++++++++++---
 OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c |  6 ++
 4 files changed, 66 insertions(+), 9 deletions(-)

diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.h b/OvmfPkg/VirtioNetDxe/VirtioNet.h
index a4661bd5d2fe..873069e9de82 100644
--- a/OvmfPkg/VirtioNetDxe/VirtioNet.h
+++ b/OvmfPkg/VirtioNetDxe/VirtioNet.h
@@ -94,7 +94,8 @@ typedef struct {
   UINT16                      TxMaxPending;      // VirtioNetInitTx
   UINT16                      TxCurPending;      // VirtioNetInitTx
   UINT16                      *TxFreeStack;      // VirtioNetInitTx
-  VIRTIO_1_0_NET_REQ          TxSharedReq;       // VirtioNetInitTx
+  VIRTIO_1_0_NET_REQ          *TxSharedReq;      // VirtioNetInitTx
+  VOID                        *TxSharedReqMap;   // VirtioNetInitTx
   UINT16                      TxLastUsed;        // VirtioNetInitTx
 } VNET_DEV;
 
diff --git a/OvmfPkg/VirtioNetDxe/Events.c b/OvmfPkg/VirtioNetDxe/Events.c
index 2f61da6aece4..21468f44a3f0 100644
--- a/OvmfPkg/VirtioNetDxe/Events.c
+++ b/OvmfPkg/VirtioNetDxe/Events.c
@@ -101,4 +101,10 @@ VirtioNetExitBoot (
   // device is reset.
   //
   Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
+
+  //
+  // Unmap shared Tx request mapping so that hypervisor can not get readable
+  // data after device is reset.
+  //
+  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->TxSharedReqMap);
 }
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index db2314446bbb..9bac19f8e3d1 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -18,6 +18,7 @@
 **/
 
 #include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 
@@ -149,8 +150,11 @@ VirtioNetInitTx (
   IN OUT VNET_DEV *Dev
   )
 {
-  UINTN TxSharedReqSize;
-  UINTN PktIdx;
+  UINTN                 TxSharedReqSize;
+  UINTN                 PktIdx;
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  DeviceAddress;
+  UINT64                BufBaseShift;
 
   Dev->TxMaxPending = (UINT16) MIN (Dev->TxRing.QueueSize / 2,
                                  VNET_MAX_PENDING);
@@ -162,24 +166,57 @@ VirtioNetInitTx (
   }
 
   //
+  // Allocate TxSharedReq header and map with BusMasterCommonBuffer so that it
+  // can be accessed equally by both processor and device.
+  //
+  Status = Dev->VirtIo->AllocateSharedPages (
+                          Dev->VirtIo,
+                          EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)),
+                          (VOID *) &Dev->TxSharedReq
+                          );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = VirtioMapAllBytesInSharedBuffer (
+             Dev->VirtIo,
+             VirtioOperationBusMasterCommonBuffer,
+             (VOID *) Dev->TxSharedReq,
+             sizeof *(Dev->TxSharedReq),
+             &DeviceAddress,
+             &Dev->TxSharedReqMap
+             );
+  if (EFI_ERROR (Status)) {
+    goto FreeBuffer;
+  }
+
+  BufBaseShift = (UINT64) (UINTN)Dev->TxSharedReq - (UINT64) DeviceAddress;
+
+  ZeroMem ((VOID *) Dev->TxSharedReq, sizeof *(Dev->TxSharedReq));
+
+  //
   // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on
   // VIRTIO_NET_F_MRG_RXBUF, which we never negotiate.
   //
   TxSharedReqSize = (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) ?
-                    sizeof Dev->TxSharedReq.V0_9_5 :
-                    sizeof Dev->TxSharedReq;
+                    sizeof ((Dev->TxSharedReq)->V0_9_5) :
+                    sizeof *(Dev->TxSharedReq);
 
   for (PktIdx = 0; PktIdx < Dev->TxMaxPending; ++PktIdx) {
     UINT16 DescIdx;
+    UINT64 Address;
 
     DescIdx = (UINT16) (2 * PktIdx);
     Dev->TxFreeStack[PktIdx] = DescIdx;
 
+    Address = (UINTN) Dev->TxSharedReq;
+    Address += BufBaseShift;
+
     //
     // For each possibly pending packet, lay out the descriptor for the common
     // (unmodified by the host) virtio-net request header.
     //
-    Dev->TxRing.Desc[DescIdx].Addr  = (UINTN) &Dev->TxSharedReq;
+    Dev->TxRing.Desc[DescIdx].Addr  = (UINTN) Address;
     Dev->TxRing.Desc[DescIdx].Len   = (UINT32) TxSharedReqSize;
     Dev->TxRing.Desc[DescIdx].Flags = VRING_DESC_F_NEXT;
     Dev->TxRing.Desc[DescIdx].Next  = (UINT16) (DescIdx + 1);
@@ -194,13 +231,13 @@ VirtioNetInitTx (
   //
   // virtio-0.9.5, Appendix C, Packet Transmission
   //
-  Dev->TxSharedReq.V0_9_5.Flags   = 0;
-  Dev->TxSharedReq.V0_9_5.GsoType = VIRTIO_NET_HDR_GSO_NONE;
+  Dev->TxSharedReq->V0_9_5.Flags   = 0;
+  Dev->TxSharedReq->V0_9_5.GsoType = VIRTIO_NET_HDR_GSO_NONE;
 
   //
   // For VirtIo 1.0 only -- the field exists, but it is unused
   //
-  Dev->TxSharedReq.NumBuffers = 0;
+  Dev->TxSharedReq->NumBuffers = 0;
 
   //
   // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
@@ -215,6 +252,13 @@ VirtioNetInitTx (
   *Dev->TxRing.Avail.Flags = (UINT16) VRING_AVAIL_F_NO_INTERRUPT;
 
   return EFI_SUCCESS;
+FreeBuffer:
+  Dev->VirtIo->FreeSharedPages (
+                 Dev->VirtIo,
+                 EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)),
+                 (VOID *) Dev->TxSharedReq
+                 );
+  return Status;
 }
 
 
diff --git a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
index ec8e63ebdc32..6e7166144f2d 100644
--- a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
+++ b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
@@ -53,5 +53,11 @@ VirtioNetShutdownTx (
   IN OUT VNET_DEV *Dev
   )
 {
+  Dev->VirtIo->FreeSharedPages (
+                 Dev->VirtIo,
+                 EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)),
+                 (VOID *) Dev->TxSharedReq
+                 );
+
   FreePool (Dev->TxFreeStack);
 }
-- 
2.7.4



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

* [PATCH v2 22/23] OvmfPkg/VirtioNetDxe: map transmit buffer host address to device address
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (20 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 21/23] OvmfPkg/VirtioNetDxe: dynamically alloc transmit header Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-14 11:36 ` [PATCH v2 23/23] OvmfPkg/Virtio: define VIRITO_F_IOMMU_PLATFORM feature bit Brijesh Singh
  22 siblings, 0 replies; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

Update VirtioNetTransmit() to map the callers transmit buffer to a device
address and use the DeviceAddress in vring descriptors.

Since the transmit buffers are returned back to caller in
VirtioNetGetStatus() hence we maintain a simple list to map DeviceAddress
to HostAddress. The list is used for mapping to HostAddress after the
data is succesfully transmitted.

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/VirtioNetDxe/VirtioNet.h        |  17 +++
 OvmfPkg/VirtioNetDxe/SnpGetStatus.c     |  19 +++-
 OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c | 115 ++++++++++++++++++++
 OvmfPkg/VirtioNetDxe/SnpTransmit.c      |  26 ++++-
 OvmfPkg/VirtioRngDxe/VirtioRng.c        |   2 +-
 5 files changed, 169 insertions(+), 10 deletions(-)

diff --git a/OvmfPkg/VirtioNetDxe/VirtioNet.h b/OvmfPkg/VirtioNetDxe/VirtioNet.h
index 873069e9de82..6c5129f178cd 100644
--- a/OvmfPkg/VirtioNetDxe/VirtioNet.h
+++ b/OvmfPkg/VirtioNetDxe/VirtioNet.h
@@ -269,6 +269,23 @@ VirtioNetShutdownTx (
   IN OUT VNET_DEV *Dev
   );
 
+EFI_STATUS
+EFIAPI
+VirtioMapTxBuf (
+  IN  VNET_DEV              *Dev,
+  IN  EFI_PHYSICAL_ADDRESS  HostAddress,
+  IN  UINTN                 NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress
+  );
+
+EFI_STATUS
+EFIAPI
+VirtioUnmapTxBuf (
+  IN  VNET_DEV              *Dev,
+  OUT EFI_PHYSICAL_ADDRESS  *HostAddress,
+  IN  EFI_PHYSICAL_ADDRESS  DeviceAddress
+  );
+
 //
 // event callbacks
 //
diff --git a/OvmfPkg/VirtioNetDxe/SnpGetStatus.c b/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
index 694940ea1d97..ddea29e65d57 100644
--- a/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
+++ b/OvmfPkg/VirtioNetDxe/SnpGetStatus.c
@@ -5,6 +5,7 @@
 
   Copyright (C) 2013, Red Hat, Inc.
   Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
 
   This program and the accompanying materials are licensed and made available
   under the terms and conditions of the BSD License which accompanies this
@@ -126,8 +127,10 @@ VirtioNetGetStatus (
       *TxBuf = NULL;
     }
     else {
-      UINT16 UsedElemIdx;
-      UINT32 DescIdx;
+      UINT16                UsedElemIdx;
+      UINT32                DescIdx;
+      EFI_PHYSICAL_ADDRESS  DeviceAddress;
+      EFI_PHYSICAL_ADDRESS  HostAddress;
 
       //
       // fetch the first descriptor among those that the hypervisor reports
@@ -141,9 +144,19 @@ VirtioNetGetStatus (
       ASSERT (DescIdx < (UINT32) (2 * Dev->TxMaxPending - 1));
 
       //
+      // Unmap the DeviceAddress
+      //
+      DeviceAddress = Dev->TxRing.Desc[DescIdx + 1].Addr;
+      Status = VirtioUnmapTxBuf (Dev, &HostAddress, DeviceAddress);
+      if (EFI_ERROR (Status)) {
+        goto Exit;
+      }
+
+      //
+      //
       // report buffer address to caller that has been enqueued by caller
       //
-      *TxBuf = (VOID *)(UINTN) Dev->TxRing.Desc[DescIdx + 1].Addr;
+      *TxBuf = (VOID *)(UINTN) HostAddress;
 
       //
       // now this descriptor can be used again to enqueue a transmit buffer
diff --git a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
index 6e7166144f2d..3dbfc272980a 100644
--- a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
+++ b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
@@ -14,10 +14,29 @@
 
 **/
 
+#include <Library/BaseLib.h>
 #include <Library/MemoryAllocationLib.h>
 
 #include "VirtioNet.h"
 
+#define PRIVATE_TXBUF_SIGNATURE  SIGNATURE_32 ('t', 'x', 'b', 'f')
+typedef struct {
+  UINT32                Signature;
+  LIST_ENTRY            Link;
+  EFI_PHYSICAL_ADDRESS  HostAddress;
+  EFI_PHYSICAL_ADDRESS  DeviceAddress;
+  VOID                  *Mapping;
+} PRIVATE_TXBUF_ENTRY;
+#define PRIVATE_TXBUF_FROM_LINK(a) CR (a, PRIVATE_TXBUF_ENTRY, Link, \
+                                       PRIVATE_TXBUF_SIGNATURE)
+
+//
+// List of Txbuf queued
+//
+STATIC LIST_ENTRY mTxBufMapList = INITIALIZE_LIST_HEAD_VARIABLE (
+                                    mTxBufMapList
+                                    );
+
 /**
   Release RX and TX resources on the boundary of the
   EfiSimpleNetworkInitialized state.
@@ -61,3 +80,99 @@ VirtioNetShutdownTx (
 
   FreePool (Dev->TxFreeStack);
 }
+
+EFI_STATUS
+EFIAPI
+VirtioMapTxBuf (
+  IN  VNET_DEV               *Dev,
+  IN  EFI_PHYSICAL_ADDRESS   HostAddress,
+  IN  UINTN                  NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS   *DeviceAddress
+  )
+{
+  EFI_STATUS             Status;
+  PRIVATE_TXBUF_ENTRY   *Private;
+
+  Private = AllocatePool (sizeof (*Private));
+  if (Private == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Private->Signature = PRIVATE_TXBUF_SIGNATURE;
+  Private->HostAddress = HostAddress;
+
+  Status = VirtioMapAllBytesInSharedBuffer (
+             Dev->VirtIo,
+             VirtioOperationBusMasterRead,
+             (VOID *) (UINTN) Private->HostAddress,
+             NumberOfBytes,
+             &Private->DeviceAddress,
+             &Private->Mapping
+             );
+  if (EFI_ERROR (Status)) {
+    goto FreePool;
+  }
+
+  *DeviceAddress = Private->DeviceAddress;
+
+  //
+  // Add the mapping information into internal list so that we can retrieve
+  // the HostAddress from Unmap().
+  //
+  InsertTailList (&mTxBufMapList, &Private->Link);
+
+  return EFI_SUCCESS;
+
+FreePool:
+  FreePool (Private);
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioUnmapTxBuf (
+  IN  VNET_DEV               *Dev,
+  OUT EFI_PHYSICAL_ADDRESS   *HostAddress,
+  IN  EFI_PHYSICAL_ADDRESS   DeviceAddress
+  )
+{
+  EFI_STATUS             Status;
+  PRIVATE_TXBUF_ENTRY   *Private;
+  LIST_ENTRY            *Link;
+  BOOLEAN                Found;
+
+  Found = FALSE;
+
+  //
+  // Iterate through internal txbuf list to find mapping for a given
+  // DeviceAddress.
+  //
+  for (Link = GetFirstNode (&mTxBufMapList)
+       ; !IsNull (&mTxBufMapList, Link)
+       ; Link = GetNextNode (&mTxBufMapList, Link)
+      ) {
+    Private = PRIVATE_TXBUF_FROM_LINK (Link);
+    if (Private->DeviceAddress == DeviceAddress) {
+      Found = TRUE;
+      break;
+    }
+  }
+
+  //
+  // We failed to find mapping for the given DeviceAddress
+  // (this should never happen)
+  //
+  ASSERT (Found);
+
+  Status = Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Private->Mapping);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *HostAddress = Private->HostAddress;
+
+  RemoveEntryList (&Private->Link);
+  FreePool (Private);
+
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/VirtioNetDxe/SnpTransmit.c b/OvmfPkg/VirtioNetDxe/SnpTransmit.c
index 7ca40d5d0650..9d7d017d5a6f 100644
--- a/OvmfPkg/VirtioNetDxe/SnpTransmit.c
+++ b/OvmfPkg/VirtioNetDxe/SnpTransmit.c
@@ -73,11 +73,12 @@ VirtioNetTransmit (
   IN UINT16                      *Protocol OPTIONAL
   )
 {
-  VNET_DEV   *Dev;
-  EFI_TPL    OldTpl;
-  EFI_STATUS Status;
-  UINT16     DescIdx;
-  UINT16     AvailIdx;
+  VNET_DEV              *Dev;
+  EFI_TPL               OldTpl;
+  EFI_STATUS            Status;
+  UINT16                DescIdx;
+  UINT16                AvailIdx;
+  EFI_PHYSICAL_ADDRESS  DeviceAddress;
 
   if (This == NULL || BufferSize == 0 || Buffer == NULL) {
     return EFI_INVALID_PARAMETER;
@@ -144,10 +145,23 @@ VirtioNetTransmit (
   }
 
   //
+  // Map the transmit buffer HostAddress to a DeviceAddress
+  //
+  Status = VirtioMapTxBuf (
+             Dev,
+             (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer,
+             BufferSize,
+             &DeviceAddress
+             );
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  //
   // virtio-0.9.5, 2.4.1 Supplying Buffers to The Device
   //
   DescIdx = Dev->TxFreeStack[Dev->TxCurPending++];
-  Dev->TxRing.Desc[DescIdx + 1].Addr  = (UINTN) Buffer;
+  Dev->TxRing.Desc[DescIdx + 1].Addr  = (UINTN) DeviceAddress;
   Dev->TxRing.Desc[DescIdx + 1].Len   = (UINT32) BufferSize;
 
   //
diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.c b/OvmfPkg/VirtioRngDxe/VirtioRng.c
index fc01f1996654..b19d90901430 100644
--- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
+++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
@@ -162,7 +162,7 @@ VirtioRngGetRNG (
 
   Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
   //
-  // Map the Buffers system phyiscal address to device address
+  // Map the Buffer host address to device address
   //
   Status = VirtioMapAllBytesInSharedBuffer (
              Dev->VirtIo,
-- 
2.7.4



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

* [PATCH v2 23/23] OvmfPkg/Virtio: define VIRITO_F_IOMMU_PLATFORM feature bit
  2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
                   ` (21 preceding siblings ...)
  2017-08-14 11:36 ` [PATCH v2 22/23] OvmfPkg/VirtioNetDxe: map transmit buffer host address to device address Brijesh Singh
@ 2017-08-14 11:36 ` Brijesh Singh
  2017-08-21 15:40   ` Laszlo Ersek
  22 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-14 11:36 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

This feature indicates that the device is behind an IOMMU that translates
bus addresses from the device into physical addresses in memory.  If this
feature bit is set to 0, then the device emits physical addresses which
are not translated further, even though an IOMMU may be present.
see [1] for more infromation

[1] https://lists.oasis-open.org/archives/virtio-dev/201610/msg00121.html

In previous patches, we have implemented IOMMU-like member functions in
VIRTIO_DEVICE_PROTOCOL to translate the physical address to bus address
and virtio drivers are updated to use those member functions. 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.

Suggested-by: Laszlo Ersek <lersek@redhat.com>
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/Include/IndustryStandard/Virtio10.h | 5 +++++
 OvmfPkg/VirtioBlkDxe/VirtioBlk.c            | 3 ++-
 OvmfPkg/VirtioNetDxe/SnpInitialize.c        | 3 ++-
 OvmfPkg/VirtioRngDxe/VirtioRng.c            | 2 +-
 OvmfPkg/VirtioScsiDxe/VirtioScsi.c          | 3 ++-
 5 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/OvmfPkg/Include/IndustryStandard/Virtio10.h b/OvmfPkg/Include/IndustryStandard/Virtio10.h
index 4c9b62a3cf59..c62429d94432 100644
--- a/OvmfPkg/Include/IndustryStandard/Virtio10.h
+++ b/OvmfPkg/Include/IndustryStandard/Virtio10.h
@@ -83,4 +83,9 @@ typedef struct {
 //
 #define VIRTIO_F_VERSION_1 BIT32
 
+//
+// VirtIo 1.0 reserved iommu platform feature bits
+//
+#define VIRTIO_F_IOMMU_PLATFORM BIT33
+
 #endif // _VIRTIO_1_0_H_
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
index 57baceb20a19..a78ec0df9c7b 100644
--- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
+++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
@@ -773,7 +773,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
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index 9bac19f8e3d1..b389f6243661 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -536,7 +536,8 @@ VirtioNetInitialize (
   ASSERT (Dev->Snm.MediaPresentSupported ==
     !!(Features & VIRTIO_NET_F_STATUS));
 
-  Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | VIRTIO_F_VERSION_1;
+  Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | VIRTIO_F_VERSION_1 |
+              VIRTIO_F_IOMMU_PLATFORM;
 
   //
   // In virtio-1.0, feature negotiation is expected to complete before queue
diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.c b/OvmfPkg/VirtioRngDxe/VirtioRng.c
index b19d90901430..81d8c7facc10 100644
--- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
+++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
@@ -273,7 +273,7 @@ VirtioRngInit (
     goto Failed;
   }
 
-  Features &= VIRTIO_F_VERSION_1;
+  Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM;
 
   //
   // In virtio-1.0, feature negotiation is expected to complete before queue
diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
index 65e9bda0827a..286b005c994c 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
@@ -903,7 +903,8 @@ VirtioScsiInit (
     goto Failed;
   }
 
-  Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1;
+  Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1 |
+              VIRTIO_F_IOMMU_PLATFORM;
 
   //
   // In virtio-1.0, feature negotiation is expected to complete before queue
-- 
2.7.4



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

* Re: [PATCH v2 01/23] OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute
  2017-08-14 11:36 ` [PATCH v2 01/23] OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute Brijesh Singh
@ 2017-08-16  0:34   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16  0:34 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> 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/VirtioPciDeviceDxe/VirtioPciDevice.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
> index bc4f6fe8bfa3..e41730456471 100644
> --- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
> +++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
> @@ -460,7 +460,9 @@ VirtioPciDeviceBindingStart (
>  
>    Status = Device->PciIo->Attributes (Device->PciIo,
>                           EfiPciIoAttributeOperationEnable,
> -                         EFI_PCI_IO_ATTRIBUTE_IO, NULL);
> +                         (EFI_PCI_IO_ATTRIBUTE_IO |
> +                          EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
> +                         NULL);
>    if (EFI_ERROR (Status)) {
>      goto ClosePciIo;
>    }
> 

[lersek@redhat.com: expand commit message body]
[lersek@redhat.com: fix up line breaking style (original code too)]
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>

Commit 78ef454b8c6108d330e066653039ad824cc041f1.

Thanks
Laszlo


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

* Re: [PATCH v2 02/23] OvmfPkg/Virtio10Dxe: supply missing BUS_MASTER attribute
  2017-08-14 11:36 ` [PATCH v2 02/23] OvmfPkg/Virtio10Dxe: " Brijesh Singh
@ 2017-08-16  0:36   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16  0:36 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> 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/Virtio10Dxe/Virtio10.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
> index a8a6a58c3f1d..43dcfd7cb2a4 100644
> --- a/OvmfPkg/Virtio10Dxe/Virtio10.c
> +++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
> @@ -906,7 +906,7 @@ Virtio10BindingStart (
>      goto ClosePciIo;
>    }
>  
> -  SetAttributes = 0;
> +  SetAttributes =  EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
>    UpdateAttributes (&Device->CommonConfig, &SetAttributes);
>    UpdateAttributes (&Device->NotifyConfig, &SetAttributes);
>    UpdateAttributes (&Device->SpecificConfig, &SetAttributes);
> 

[lersek@redhat.com: expand commit message body]
[lersek@redhat.com: remove superfluous whitespace in assignment]
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>

Commit 365b9433458e96df71e1583035d462b5f18d051d.

Thanks
Laszlo


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

* Re: [PATCH v2 03/23] OvmfPkg/VirtioPciDeviceDxe: add missing IN and OUT decoration
  2017-08-14 11:36 ` [PATCH v2 03/23] OvmfPkg/VirtioPciDeviceDxe: add missing IN and OUT decoration Brijesh Singh
@ 2017-08-16  0:36   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16  0:36 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> 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/VirtioPciDeviceDxe/VirtioPciDevice.h    | 24 ++++++++++----------
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c | 24 ++++++++++----------
>  2 files changed, 24 insertions(+), 24 deletions(-)
> 
> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
> index 8f17a16c88f5..6f51f816ef0f 100644
> --- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
> +++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
> @@ -96,15 +96,15 @@ VirtioPciGetQueueSize (
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetQueueAlignment (
> -  VIRTIO_DEVICE_PROTOCOL         *This,
> -  UINT32                         Alignment
> +  IN  VIRTIO_DEVICE_PROTOCOL         *This,
> +  IN  UINT32                         Alignment
>    );
>  
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetPageSize (
> -  VIRTIO_DEVICE_PROTOCOL         *This,
> -  UINT32                         PageSize
> +  IN  VIRTIO_DEVICE_PROTOCOL         *This,
> +  IN  UINT32                         PageSize
>    );
>  
>  EFI_STATUS
> @@ -131,29 +131,29 @@ VirtioPciSetQueueAddress (
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetQueueSel (
> -  VIRTIO_DEVICE_PROTOCOL         *This,
> -  UINT16                         Sel
> +  IN  VIRTIO_DEVICE_PROTOCOL         *This,
> +  IN  UINT16                         Sel
>    );
>  
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetQueueNotify (
> -  VIRTIO_DEVICE_PROTOCOL         *This,
> -  UINT16                         Index
> +  IN  VIRTIO_DEVICE_PROTOCOL         *This,
> +  IN  UINT16                         Index
>    );
>  
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetQueueSize (
> -  VIRTIO_DEVICE_PROTOCOL         *This,
> -  UINT16                         Size
> +  IN  VIRTIO_DEVICE_PROTOCOL         *This,
> +  IN  UINT16                         Size
>    );
>  
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetDeviceStatus (
> -  VIRTIO_DEVICE_PROTOCOL         *This,
> -  UINT8                          DeviceStatus
> +  IN  VIRTIO_DEVICE_PROTOCOL         *This,
> +  IN  UINT8                          DeviceStatus
>    );
>  
>  #endif // _VIRTIO_PCI_DEVICE_DXE_H_
> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
> index 243aa14c2421..5f86914265ea 100644
> --- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
> +++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
> @@ -196,8 +196,8 @@ VirtioPciSetQueueAddress (
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetQueueSel (
> -  VIRTIO_DEVICE_PROTOCOL    *This,
> -  UINT16                    Sel
> +  IN  VIRTIO_DEVICE_PROTOCOL    *This,
> +  IN  UINT16                    Sel
>    )
>  {
>    VIRTIO_PCI_DEVICE *Dev;
> @@ -211,8 +211,8 @@ VirtioPciSetQueueSel (
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetQueueAlignment (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT32                  Alignment
> +  IN  VIRTIO_DEVICE_PROTOCOL *This,
> +  IN  UINT32                  Alignment
>    )
>  {
>    return EFI_SUCCESS;
> @@ -221,8 +221,8 @@ VirtioPciSetQueueAlignment (
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetPageSize (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT32                  PageSize
> +  IN  VIRTIO_DEVICE_PROTOCOL *This,
> +  IN  UINT32                  PageSize
>    )
>  {
>    return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
> @@ -231,8 +231,8 @@ VirtioPciSetPageSize (
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetQueueNotify (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT16                 Index
> +  IN  VIRTIO_DEVICE_PROTOCOL *This,
> +  IN  UINT16                 Index
>    )
>  {
>    VIRTIO_PCI_DEVICE *Dev;
> @@ -246,8 +246,8 @@ VirtioPciSetQueueNotify (
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetQueueSize (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT16                 Size
> +  IN  VIRTIO_DEVICE_PROTOCOL *This,
> +  IN  UINT16                 Size
>    )
>  {
>    //
> @@ -260,8 +260,8 @@ VirtioPciSetQueueSize (
>  EFI_STATUS
>  EFIAPI
>  VirtioPciSetDeviceStatus (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT8                  DeviceStatus
> +  IN  VIRTIO_DEVICE_PROTOCOL *This,
> +  IN  UINT8                  DeviceStatus
>    )
>  {
>    VIRTIO_PCI_DEVICE *Dev;
> 


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

Commit e5251fecb931763c90a032266fdd8ab5ec527744.

Thanks
Laszlo


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

* Re: [PATCH v2 04/23] OvmfPkg/VirtioMmioDeviceLib: add missing IN and OUT decoration
  2017-08-14 11:36 ` [PATCH v2 04/23] OvmfPkg/VirtioMmioDeviceLib: " Brijesh Singh
@ 2017-08-16  0:37   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16  0:37 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> 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/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h          | 28 ++++++++++----------
>  OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c | 28 ++++++++++----------
>  2 files changed, 28 insertions(+), 28 deletions(-)
> 
> diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
> index 4130dbc043df..bedd635e1a86 100644
> --- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
> +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
> @@ -85,29 +85,29 @@ VirtioMmioGetDeviceStatus (
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetQueueSize (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT16                  QueueSize
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT16                  QueueSize
>    );
>  
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetDeviceStatus (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT8                   DeviceStatus
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT8                   DeviceStatus
>    );
>  
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetQueueNotify (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT16                  QueueNotify
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT16                  QueueNotify
>    );
>  
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetQueueSel (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT16                  Sel
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT16                  Sel
>    );
>  
>  EFI_STATUS
> @@ -119,22 +119,22 @@ VirtioMmioSetQueueAddress (
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetQueueAlignment (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT32                  Alignment
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT32                  Alignment
>    );
>  
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetPageSize (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT32                  PageSize
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT32                  PageSize
>    );
>  
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetGuestFeatures (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT64                  Features
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT64                  Features
>    );
>  
>  #endif // _VIRTIO_MMIO_DEVICE_INTERNAL_H_
> diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
> index 53c734f6b1af..9142d4a162c0 100644
> --- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
> +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
> @@ -81,8 +81,8 @@ VirtioMmioGetDeviceStatus (
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetQueueSize (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT16                  QueueSize
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT16                  QueueSize
>    )
>  {
>    VIRTIO_MMIO_DEVICE *Device;
> @@ -97,8 +97,8 @@ VirtioMmioSetQueueSize (
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetDeviceStatus (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT8                   DeviceStatus
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT8                   DeviceStatus
>    )
>  {
>    VIRTIO_MMIO_DEVICE *Device;
> @@ -113,8 +113,8 @@ VirtioMmioSetDeviceStatus (
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetQueueNotify (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT16                  QueueNotify
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT16                  QueueNotify
>    )
>  {
>    VIRTIO_MMIO_DEVICE *Device;
> @@ -129,8 +129,8 @@ VirtioMmioSetQueueNotify (
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetQueueAlignment (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT32                  Alignment
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT32                  Alignment
>    )
>  {
>    VIRTIO_MMIO_DEVICE *Device;
> @@ -145,8 +145,8 @@ VirtioMmioSetQueueAlignment (
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetPageSize (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT32                  PageSize
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT32                  PageSize
>    )
>  {
>    VIRTIO_MMIO_DEVICE *Device;
> @@ -165,8 +165,8 @@ VirtioMmioSetPageSize (
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetQueueSel (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT16                  Sel
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT16                  Sel
>    )
>  {
>    VIRTIO_MMIO_DEVICE *Device;
> @@ -197,8 +197,8 @@ VirtioMmioSetQueueAddress (
>  EFI_STATUS
>  EFIAPI
>  VirtioMmioSetGuestFeatures (
> -  VIRTIO_DEVICE_PROTOCOL *This,
> -  UINT64                  Features
> +  IN VIRTIO_DEVICE_PROTOCOL *This,
> +  IN UINT64                  Features
>    )
>  {
>    VIRTIO_MMIO_DEVICE *Device;
> 

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

Commit 22701a3d4dd1fd3eed385215d6e2dad0ad069b7f.

Thanks
Laszlo


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

* Re: [PATCH v2 05/23] OvmfPkg/Virtio: fix comment style
  2017-08-14 11:36 ` [PATCH v2 05/23] OvmfPkg/Virtio: fix comment style Brijesh Singh
@ 2017-08-16  0:41   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16  0:41 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> 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/Include/Protocol/VirtioDevice.h | 22 +++++++++++++-------
>  1 file changed, 14 insertions(+), 8 deletions(-)
> 
> diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
> index 910a4866e7ac..edb20c18822c 100644
> --- a/OvmfPkg/Include/Protocol/VirtioDevice.h
> +++ b/OvmfPkg/Include/Protocol/VirtioDevice.h
> @@ -320,16 +320,22 @@ EFI_STATUS
>    );
>  
>  
> -///
> -///  This protocol provides an abstraction over the VirtIo transport layer
> -///
> -///  DISCLAIMER: this protocol is a work in progress, and should not be used
> -///  outside of the EDK II tree.
> -///
> +/**
> +
> +  This protocol provides an abstraction over the VirtIo transport layer
> +
> +  DISCLAIMER: this protocol is a work in progress, and should not be used
> +  outside of the EDK II tree.
> +**/
> +
>  struct _VIRTIO_DEVICE_PROTOCOL {
> -  /// VirtIo Specification Revision encoded with VIRTIO_SPEC_REVISION()
> +  //
> +  // VirtIo Specification Revision encoded with VIRTIO_SPEC_REVISION()
> +  //
>    UINT32                      Revision;
> -  /// From the Virtio Spec
> +  //
> +  // From the Virtio Spec
> +  //
>    INT32                       SubSystemDeviceId;
>  
>    VIRTIO_GET_DEVICE_FEATURES  GetDeviceFeatures;
> 

In
<http://mid.mail-archive.com/f953ec03-b160-726b-b9ed-5e3122642815@redhat.com>,
point (18), I meant to identify all the comments that I thought would
benefit from clean-ups. The above patch misses some of those comments,
but reformats comments that (IMO) were fine (e.g. consistent with MdePkg
protocol includes). I've fixed up the patch.

[lersek@redhat.com: clarify subject line]
[lersek@redhat.com: adjust the set of comments updated by the patch]
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>

Commit a136bc3ccfa479ec8a3fc9afcbd00283339101fa.

Thank you for these miscellaneous fixes (patches 1 through 5)! I'll
strive to continue the review soon.

Thanks
Laszlo


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

* Re: [PATCH v2 06/23] OvmfPkg/Virtio: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL
  2017-08-14 11:36 ` [PATCH v2 06/23] OvmfPkg/Virtio: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL Brijesh Singh
@ 2017-08-16 14:37   ` Laszlo Ersek
  2017-08-16 15:58     ` Brijesh Singh
  0 siblings, 1 reply; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16 14:37 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

(1) In my previous review (msgid
<f953ec03-b160-726b-b9ed-5e3122642815@redhat.com>) point (1), I
suggested the following subject line:

"OvmfPkg: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL"

This subject was 72 characters long (within the 74 chars limit).

Your current subject is:

"OvmfPkg/Virtio: introduce IOMMU-like member functions to
VIRTIO_DEVICE_PROTOCOL"

It is too long (79 chars).

So please drop the "/Virtio" string, as I requested.

On 08/14/17 13:36, Brijesh Singh wrote:
> The patch extends VIRTIO_DEVICE_PROTOCOL to provide the following new
> member functions:
> 
> - AllocateSharedPages : allocate a memory region suitable for sharing
>    between guest and hypervisor (e.g ring buffer).
> 
> - FreeSharedPages: free the memory allocated using AllocateSharedPages ().
> 
> - MapSharedBuffer: map a host address to device address suitable to share
>    with device for bus master operations.
> 
> - UnmapSharedBuffer: unmap the device address obtained through the
>    MapSharedBuffer().

(2) You missed point (20) of my above-referenced v1 review. Again,
please append the following to the commit message:

---------
We're free to extend the protocol structure without changing the
protocol GUID, or bumping any protocol version fields (of which we
currently have none), because VIRTIO_DEVICE_PROTOCOL is internal to edk2
by design -- see the disclaimers in "VirtioDevice.h".
---------

> 
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> 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/Include/Protocol/VirtioDevice.h | 143 ++++++++++++++++++++
>  1 file changed, 143 insertions(+)
> 
> diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
> index edb20c18822c..14f980d7bf0a 100644
> --- a/OvmfPkg/Include/Protocol/VirtioDevice.h
> +++ b/OvmfPkg/Include/Protocol/VirtioDevice.h
> @@ -5,6 +5,7 @@
>    and should not be used outside of the EDK II tree.
>  
>    Copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
> +  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
>  
>    This program and the accompanying materials are licensed and made available
>    under the terms and conditions of the BSD License which accompanies this
> @@ -31,6 +32,25 @@
>  
>  typedef struct _VIRTIO_DEVICE_PROTOCOL  VIRTIO_DEVICE_PROTOCOL;
>  
> +//
> +// VIRTIO Operation for VIRTIO_MAP_SHARED
> +//
> +typedef enum {
> +  //
> +  // A read operation from system memory by a bus master
> +  //
> +  VirtioOperationBusMasterRead,
> +  //
> +  // A write operation to system memory by a bus master
> +  //
> +  VirtioOperationBusMasterWrite,
> +  //
> +  // Provides both read and write access to system memory by both the
> +  // processor and a bus master
> +  //
> +  VirtioOperationBusMasterCommonBuffer,
> +} VIRTIO_MAP_OPERATION;
> +
>  /**
>  
>    Read a word from the device-specific I/O region of the Virtio Header.
> @@ -319,6 +339,121 @@ EFI_STATUS
>    IN UINT8                   DeviceStatus
>    );
>  
> +/**
> +
> +  Allocates pages that are suitable for an VirtioOperationBusMasterCommonBuffer
> +  mapping. This means that the buffer allocated by this function supports
> +  simultaneous access by both the processor and the bus master. The device
> +  address that the bus master uses to access the buffer must be retrieved with
> +  a call to VIRTIO_MAP_SHARED.
> +
> +  @param[in]      This              The protocol instance pointer.
> +
> +  @param[in]      Pages             The number of pages to allocate.
> +
> +  @param[in,out]  HostAddress       A pointer to store the system memory base
> +                                    address of the allocated range.
> +
> +  @retval EFI_SUCCESS               The requested memory pages were allocated.
> +  @retval EFI_OUT_OF_RESOURCES      The memory pages could not be allocated.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *VIRTIO_ALLOCATE_SHARED)(
> +  IN     VIRTIO_DEVICE_PROTOCOL                   *This,
> +  IN     UINTN                                    Pages,
> +  IN OUT VOID                                     **HostAddress
> +  );
> +
> +/**
> +  Frees memory that was allocated with VIRTIO_ALLOCATE_SHARED.
> +
> +  @param[in]  This           The protocol instance pointer.
> +
> +  @param[in]  Pages          The number of pages to free.
> +
> +  @param[in]  HostAddress    The system memory base address of the allocated
> +                             range.
> +
> +**/
> +typedef
> +VOID
> +(EFIAPI *VIRTIO_FREE_SHARED)(
> +  IN  VIRTIO_DEVICE_PROTOCOL                   *This,
> +  IN  UINTN                                    Pages,
> +  IN  VOID                                     *HostAddress
> +  );
> +
> +/**
> +  Provides the virtio device address required to access system memory from a
> +  DMA bus master.
> +
> +  The interface follows the same usage pattern as defined in UEFI spec 2.6
> +  (Section 13.2 PCI Root Bridge I/O Protocol)
> +
> +  @param[in]     This             The protocol instance pointer.
> +
> +  @param[in]     Operation        Indicates if the bus master is going to
> +                                  read or write to system memory.
> +
> +  @param[in]     HostAddress      The system memory address to map to shared
> +                                  buffer address.
> +
> +  @param[in,out] NumberOfBytes    On input the number of bytes to map.
> +                                  On output the number of bytes that were
> +                                  mapped.
> +
> +  @param[out]    DeviceAddress    The resulting shared map address for the
> +                                  bus master to access the hosts HostAddress.
> +
> +  @param[out]    Mapping          A resulting taken to pass to

(3) s/taken/token/

The rest looks fine!

Thanks,
Laszlo

> +                                  VIRTIO_UNMAP_SHARED.
> +
> +  @retval EFI_SUCCESS             The range was mapped for the returned
> +                                  NumberOfBytes.
> +  @retval EFI_UNSUPPORTED         The HostAddress cannot be mapped as a
> +                                  common buffer.
> +  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
> +  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to
> +                                  a lack of resources.
> +  @retval EFI_DEVICE_ERROR        The system hardware could not map the
> +                                  requested address.
> +**/
> +
> +typedef
> +EFI_STATUS
> +(EFIAPI *VIRTIO_MAP_SHARED) (
> +  IN     VIRTIO_DEVICE_PROTOCOL       *This,
> +  IN     VIRTIO_MAP_OPERATION         Operation,
> +  IN     VOID                         *HostAddress,
> +  IN OUT UINTN                        *NumberOfBytes,
> +  OUT    EFI_PHYSICAL_ADDRESS         *DeviceAddress,
> +  OUT    VOID                         **Mapping
> +  );
> +
> +/**
> +  Completes the VIRTIO_MAP_SHARED operation and releases any corresponding
> +  resources.
> +
> +  @param[in]  This               The protocol instance pointer.
> +
> +  @param[in]  Mapping            The mapping token returned from
> +                                 VIRTIO_MAP_SHARED.
> +
> +  @retval EFI_SUCCESS            The range was unmapped.
> +  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by
> +                                 VIRTIO_MAP_SHARED. Passing an invalid Mapping
> +                                 token can cause undefined behavior.
> +  @retval EFI_DEVICE_ERROR       The data was not committed to the target
> +                                 system memory.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *VIRTIO_UNMAP_SHARED)(
> +  IN  VIRTIO_DEVICE_PROTOCOL    *This,
> +  IN  VOID                      *Mapping
> +  );
>  
>  /**
>  
> @@ -359,6 +494,14 @@ struct _VIRTIO_DEVICE_PROTOCOL {
>    // Functions to read/write Device Specific headers
>    VIRTIO_DEVICE_WRITE         WriteDevice;
>    VIRTIO_DEVICE_READ          ReadDevice;
> +
> +  //
> +  // Functions to allocate, free, map and unmap shared buffer
> +  //
> +  VIRTIO_ALLOCATE_SHARED      AllocateSharedPages;
> +  VIRTIO_FREE_SHARED          FreeSharedPages;
> +  VIRTIO_MAP_SHARED           MapSharedBuffer;
> +  VIRTIO_UNMAP_SHARED         UnmapSharedBuffer;
>  };
>  
>  extern EFI_GUID gVirtioDeviceProtocolGuid;
> 



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

* Re: [PATCH v2 07/23] OvmfPkg/Virtio10Dxe: implement IOMMU-like member functions
  2017-08-14 11:36 ` [PATCH v2 07/23] OvmfPkg/Virtio10Dxe: implement IOMMU-like member functions Brijesh Singh
@ 2017-08-16 14:59   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16 14:59 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> The patch implements the newly added IOMMU-like member functions by
> respectively delegating the job to:
> 
> - VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages() ->
>     EFI_PCI_IO_PROTOCOL.AllocateBuffer()
> 
> - VIRTIO_DEVICE_PROTOCOL.FreeSharedPages() ->
>     EFI_PCI_IO_PROTOCOL.FreeBuffer()
> 
> - VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer() ->
>     EFI_PCI_IO_PROTOCOL.Map()
> 
> - VIRTIO_DEVICE_PROTOCOL.UnmapSharedBuffer() ->
>     EFI_PCI_IO_PROTOCOL.Unmap()
> 
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> 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/Virtio10Dxe/Virtio10.c | 121 +++++++++++++++++++-
>  1 file changed, 119 insertions(+), 2 deletions(-)
> 
> diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
> index 43dcfd7cb2a4..413ffa06cf35 100644
> --- a/OvmfPkg/Virtio10Dxe/Virtio10.c
> +++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
> @@ -2,6 +2,7 @@
>    A non-transitional driver for VirtIo 1.0 PCI devices.
>  
>    Copyright (C) 2016, Red Hat, Inc.
> +  Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
>  
>    This program and the accompanying materials are licensed and made available
>    under the terms and conditions of the BSD License which accompanies this
> @@ -15,6 +16,7 @@
>  #include <IndustryStandard/Pci.h>
>  #include <IndustryStandard/Virtio.h>
>  #include <Protocol/PciIo.h>
> +#include <Protocol/PciRootBridgeIo.h>
>  #include <Protocol/VirtioDevice.h>
>  #include <Library/BaseMemoryLib.h>
>  #include <Library/DebugLib.h>
> @@ -772,6 +774,117 @@ Virtio10ReadDevice (
>    return Status;
>  }
>  
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +Virtio10AllocateSharedPages (
> +  IN     VIRTIO_DEVICE_PROTOCOL  *This,
> +  IN     UINTN                   Pages,
> +  IN OUT VOID                    **HostAddress
> +  )
> +{
> +  VIRTIO_1_0_DEV *Dev;
> +  EFI_STATUS     Status;
> +
> +  Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
> +
> +  Status = Dev->PciIo->AllocateBuffer (
> +                         Dev->PciIo,
> +                         AllocateAnyPages,
> +                         EfiBootServicesData,
> +                         Pages,
> +                         HostAddress,
> +                         EFI_PCI_ATTRIBUTE_MEMORY_CACHED
> +                         );
> +  return Status;
> +}
> +
> +STATIC
> +VOID
> +EFIAPI
> +Virtio10FreeSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *This,
> +  IN  UINTN                   Pages,
> +  IN  VOID                    *HostAddress
> +  )
> +{
> +  VIRTIO_1_0_DEV *Dev;
> +
> +  Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
> +
> +  Dev->PciIo->FreeBuffer (
> +                Dev->PciIo,
> +                Pages,
> +                HostAddress
> +                );
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +Virtio10MapSharedBuffer (
> +  IN     VIRTIO_DEVICE_PROTOCOL  *This,
> +  IN     VIRTIO_MAP_OPERATION    Operation,
> +  IN     VOID                    *HostAddress,
> +  IN OUT UINTN                   *NumberOfBytes,
> +  OUT    EFI_PHYSICAL_ADDRESS    *DeviceAddress,
> +  OUT    VOID                    **Mapping
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  VIRTIO_1_0_DEV                *Dev;
> +  EFI_PCI_IO_PROTOCOL_OPERATION PciIoOperation;
> +
> +  Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
> +
> +  //
> +  // Map VIRTIO_MAP_OPERATION to EFI_PCI_IO_PROTOCOL_OPERATION
> +  //
> +  switch (Operation) {
> +  case VirtioOperationBusMasterRead:
> +    PciIoOperation = EfiPciIoOperationBusMasterRead;
> +    break;
> +  case VirtioOperationBusMasterWrite:
> +    PciIoOperation = EfiPciIoOperationBusMasterWrite;
> +    break;
> +  case VirtioOperationBusMasterCommonBuffer:
> +    PciIoOperation = EfiPciIoOperationBusMasterCommonBuffer;
> +    break;
> +  default:
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = Dev->PciIo->Map (
> +                         Dev->PciIo,
> +                         PciIoOperation,
> +                         HostAddress,
> +                         NumberOfBytes,
> +                         DeviceAddress,
> +                         Mapping
> +                         );
> +  return Status;
> +}
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +Virtio10UnmapSharedBuffer (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *This,
> +  IN  VOID                    *Mapping
> +  )
> +{
> +  EFI_STATUS      Status;
> +  VIRTIO_1_0_DEV  *Dev;
> +
> +  Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
> +
> +  Status = Dev->PciIo->Unmap (
> +                         Dev->PciIo,
> +                         Mapping
> +                         );
> +
> +  return Status;
> +}
>  
>  STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = {
>    VIRTIO_SPEC_REVISION (1, 0, 0),
> @@ -788,7 +901,11 @@ STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = {
>    Virtio10GetDeviceStatus,
>    Virtio10SetDeviceStatus,
>    Virtio10WriteDevice,
> -  Virtio10ReadDevice
> +  Virtio10ReadDevice,
> +  Virtio10AllocateSharedPages,
> +  Virtio10FreeSharedPages,
> +  Virtio10MapSharedBuffer,
> +  Virtio10UnmapSharedBuffer
>  };
>  
>  
> @@ -906,7 +1023,7 @@ Virtio10BindingStart (
>      goto ClosePciIo;
>    }
>  
> -  SetAttributes =  EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
> +  SetAttributes =  EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
>    UpdateAttributes (&Device->CommonConfig, &SetAttributes);
>    UpdateAttributes (&Device->NotifyConfig, &SetAttributes);
>    UpdateAttributes (&Device->SpecificConfig, &SetAttributes);
> 

(1) This patch is almost complete in my opinion, except the last hunk is
incorrect -- I think it may be due to an incorrect conflict resolution
during rebase.

Namely, we shouldn't assign "SetAttributes" the value

  EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE

but the value

  (EFI_PCI_IO_ATTRIBUTE_BUS_MASTER |
   EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE)

IOW, adding EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE is good, but
EFI_PCI_IO_ATTRIBUTE_BUS_MASTER should be preserved too.

Please refer to the following sentence in my v1 review
<http://mid.mail-archive.com/659fe2f7-0d17-cde7-c3d3-36e541ff7805@redhat.com>,
point (5):

"(And then do point (4) on top of that, separately.)"

Thank you!
Laszlo


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

* Re: [PATCH v2 08/23] OvmfPkg/VirtioPciDeviceDxe: implement IOMMU-like member functions
  2017-08-14 11:36 ` [PATCH v2 08/23] OvmfPkg/VirtioPciDeviceDxe: " Brijesh Singh
@ 2017-08-16 15:32   ` Laszlo Ersek
  2017-08-16 15:53     ` Brijesh Singh
  0 siblings, 1 reply; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16 15:32 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> The patch implements the newly added IOMMU-like member functions by
> respectively delegating the job to:
> 
> - VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages () ->
>     MemoryAllocationLib.AllocatePages()
> 
> - VIRTIO_DEVICE_PROTOCOL.FreeSharedPages () ->
>     MemoryAllocationLib.FreePages ()
> 
> - VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer () -> no-op
> 
> - VIRTIO_DEVICE_PROTOCOL.UnmapSharedBuffer () -> no-op
> 
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> 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/VirtioPciDeviceDxe/VirtioPciDevice.h    | 34 ++++++++++++
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c    |  7 ++-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c | 58 ++++++++++++++++++++
>  3 files changed, 98 insertions(+), 1 deletion(-)
> 
> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
> index 6f51f816ef0f..41df5a98e560 100644
> --- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
> +++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
> @@ -3,6 +3,7 @@
>    Internal definitions for the VirtIo PCI Device driver
>  
>    Copyright (C) 2013, ARM Ltd
> +  Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
>  
>    This program and the accompanying materials are licensed and made available
>    under the terms and conditions of the BSD License which accompanies this
> @@ -156,4 +157,37 @@ VirtioPciSetDeviceStatus (
>    IN  UINT8                          DeviceStatus
>    );
>  
> +EFI_STATUS
> +EFIAPI
> +VirtioPciAllocateSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL        *This,
> +  IN  UINTN                         NumPages,
> +  OUT VOID                          **HostAddress
> +  );
> +
> +VOID
> +EFIAPI
> +VirtioPciFreeSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL        *This,
> +  IN  UINTN                         NumPages,
> +  IN  VOID                          *HostAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioPciMapSharedBuffer (
> +  IN      VIRTIO_DEVICE_PROTOCOL        *This,
> +  IN      VIRTIO_MAP_OPERATION          Operation,
> +  IN      VOID                          *HostAddress,
> +  IN OUT  UINTN                         *NumberOfBytes,
> +  OUT     EFI_PHYSICAL_ADDRESS          *DeviceAddress,
> +  OUT     VOID                          **Mapping
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioPciUnmapSharedBuffer (
> +  IN  VIRTIO_DEVICE_PROTOCOL        *This,
> +  IN  VOID                          *Mapping
> +  );
>  #endif // _VIRTIO_PCI_DEVICE_DXE_H_
> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
> index e41730456471..b847f3c02528 100644
> --- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
> +++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
> @@ -5,6 +5,7 @@
>    Copyright (C) 2012, Red Hat, Inc.
>    Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
>    Copyright (C) 2013, ARM Ltd.
> +  Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
>  
>    This program and the accompanying materials are licensed and made available
>    under the terms and conditions of the BSD License which accompanies this
> @@ -40,7 +41,11 @@ STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate = {
>    VirtioPciGetDeviceStatus,             // GetDeviceStatus
>    VirtioPciSetDeviceStatus,             // SetDeviceStatus
>    VirtioPciDeviceWrite,                 // WriteDevice
> -  VirtioPciDeviceRead                   // ReadDevice
> +  VirtioPciDeviceRead,                  // ReadDevice
> +  VirtioPciAllocateSharedPages,         // AllocateSharedPages
> +  VirtioPciFreeSharedPages,             // FreeSharedPages
> +  VirtioPciMapSharedBuffer,             // MapSharedBuffer
> +  VirtioPciUnmapSharedBuffer,           // UnmapSharedBuffer
>  };
>  
>  /**
> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
> index 5f86914265ea..4597095deb78 100644
> --- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
> +++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
> @@ -5,6 +5,7 @@
>    Copyright (C) 2012, Red Hat, Inc.
>    Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
>    Copyright (C) 2013, ARM Ltd.
> +  Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
>  
>    This program and the accompanying materials are licensed and made available
>    under the terms and conditions of the BSD License which accompanies this
> @@ -271,3 +272,60 @@ VirtioPciSetDeviceStatus (
>    return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
>        sizeof (UINT8), DeviceStatus);
>  }
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioPciAllocateSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *This,
> +  IN  UINTN                   NumPages,
> +  OUT VOID                    **HostAddress
> +  )
> +{
> +  VOID        *Buffer;
> +
> +  Buffer = AllocatePages (NumPages);
> +  if (Buffer == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  *HostAddress = Buffer;
> +  return EFI_SUCCESS;
> +}
> +
> +VOID
> +EFIAPI
> +VirtioPciFreeSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *This,
> +  IN  UINTN                   NumPages,
> +  IN  VOID                    *HostAddress
> +  )
> +{
> +  FreePages (HostAddress, NumPages);
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioPciMapSharedBuffer (
> +  IN      VIRTIO_DEVICE_PROTOCOL  *This,
> +  IN      VIRTIO_MAP_OPERATION    Operation,
> +  IN      VOID                    *HostAddress,
> +  IN OUT  UINTN                   *NumberOfBytes,
> +  OUT     EFI_PHYSICAL_ADDRESS    *DeviceAddress,
> +  OUT     VOID                    **Mapping
> +  )
> +{
> +  *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
> +  *Mapping = NULL;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioPciUnmapSharedBuffer (
> +  IN  VIRTIO_DEVICE_PROTOCOL    *This,
> +  OUT VOID                      *Mapping
> +  )

(1) Is this an Easter egg for your reviewer? :) "Mapping" should be IN,
not OUT.

This oversight is surprising -- or, well, an Easter egg :) -- because
the function declaration, in
"OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h" above, is correct.

The patch is good otherwise.

Thanks!
Laszlo



> +{
> +  return EFI_SUCCESS;
> +}
> 



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

* Re: [PATCH v2 08/23] OvmfPkg/VirtioPciDeviceDxe: implement IOMMU-like member functions
  2017-08-16 15:32   ` Laszlo Ersek
@ 2017-08-16 15:53     ` Brijesh Singh
  0 siblings, 0 replies; 51+ messages in thread
From: Brijesh Singh @ 2017-08-16 15:53 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Tom Lendacky, Ard Biesheuvel



On 08/16/2017 10:32 AM, Laszlo Ersek wrote:
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +VirtioPciUnmapSharedBuffer (
>> +  IN  VIRTIO_DEVICE_PROTOCOL    *This,
>> +  OUT VOID                      *Mapping
>> +  )
> 
> (1) Is this an Easter egg for your reviewer? :) "Mapping" should be IN,
> not OUT.
> 
> This oversight is surprising -- or, well, an Easter egg :) -- because
> the function declaration, in
> "OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h" above, is correct.
> 

Surprisingly, it didn't took you long time to find hidden Easter Egg,
I should work harder next time :)

Since now you have found it hence I will quietly go and fix patch 9 as well ;)

-Brijesh


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

* Re: [PATCH v2 06/23] OvmfPkg/Virtio: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL
  2017-08-16 14:37   ` Laszlo Ersek
@ 2017-08-16 15:58     ` Brijesh Singh
  0 siblings, 0 replies; 51+ messages in thread
From: Brijesh Singh @ 2017-08-16 15:58 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Tom Lendacky, Ard Biesheuvel



On 08/16/2017 09:37 AM, Laszlo Ersek wrote:
> (1) In my previous review (msgid
> <f953ec03-b160-726b-b9ed-5e3122642815@redhat.com>) point (1), I
> suggested the following subject line:
> 
> "OvmfPkg: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL"
> 
> This subject was 72 characters long (within the 74 chars limit).
> 
> Your current subject is:
> 
> "OvmfPkg/Virtio: introduce IOMMU-like member functions to
> VIRTIO_DEVICE_PROTOCOL"
> 
> It is too long (79 chars).
> 
> So please drop the "/Virtio" string, as I requested.
> 

Will do

> On 08/14/17 13:36, Brijesh Singh wrote:
>> The patch extends VIRTIO_DEVICE_PROTOCOL to provide the following new
>> member functions:
>>
>> - AllocateSharedPages : allocate a memory region suitable for sharing
>>     between guest and hypervisor (e.g ring buffer).
>>
>> - FreeSharedPages: free the memory allocated using AllocateSharedPages ().
>>
>> - MapSharedBuffer: map a host address to device address suitable to share
>>     with device for bus master operations.
>>
>> - UnmapSharedBuffer: unmap the device address obtained through the
>>     MapSharedBuffer().
> 
> (2) You missed point (20) of my above-referenced v1 review. Again,
> please append the following to the commit message:
> 
> ---------
> We're free to extend the protocol structure without changing the
> protocol GUID, or bumping any protocol version fields (of which we
> currently have none), because VIRTIO_DEVICE_PROTOCOL is internal to edk2
> by design -- see the disclaimers in "VirtioDevice.h".
> ---------
> 

I will add this text in commit message.

[snip]

> 
> (3) s/taken/token/

I think I will have his error in all the place (due to copy/paste). I will go through
each patches and fix them all.

-Brijesh


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

* Re: [PATCH v2 09/23] OvmfPkg/VirtioMmioDeviceLib: implement IOMMU-like member functions
  2017-08-14 11:36 ` [PATCH v2 09/23] OvmfPkg/VirtioMmioDeviceLib: " Brijesh Singh
@ 2017-08-16 15:58   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16 15:58 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> The patch implements the newly added IOMMU-like member functions by
> respectively delegating the job to:
> 
> - VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages () ->
>     MemoryAllocationLib.AllocatePages()
> 
> - VIRTIO_DEVICE_PROTOCOL.FreeSharedPages () ->
>     MemoryAllocationLib.FreePages ()
> 
> - VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer () -> no-op
> 
> - VIRTIO_DEVICE_PROTOCOL.UnmapSharedBuffer () -> no-op
> 
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> 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/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h          | 34 +++++++++++
>  OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c | 59 ++++++++++++++++++++
>  2 files changed, 93 insertions(+)
> 
> diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
> index bedd635e1a86..b69f6d7b7a85 100644
> --- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
> +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
> @@ -137,4 +137,38 @@ VirtioMmioSetGuestFeatures (
>    IN UINT64                  Features
>    );
>  
> +EFI_STATUS
> +EFIAPI
> +VirtioMmioAllocateSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL        *This,
> +  IN  UINTN                         NumPages,
> +  OUT VOID                          **HostAddress
> +  );
> +
> +VOID
> +EFIAPI
> +VirtioMmioFreeSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL        *This,
> +  IN  UINTN                         NumPages,
> +  IN  VOID                          *HostAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioMmioMapSharedBuffer (
> +  IN      VIRTIO_DEVICE_PROTOCOL        *This,
> +  IN      VIRTIO_MAP_OPERATION          Operation,
> +  IN      VOID                          *HostAddress,
> +  IN OUT  UINTN                         *NumberOfBytes,
> +  OUT     EFI_PHYSICAL_ADDRESS          *DeviceAddress,
> +  OUT     VOID                          **Mapping
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioMmioUnmapSharedBuffer (
> +  IN  VIRTIO_DEVICE_PROTOCOL        *This,
> +  IN  VOID                          *Mapping
> +  );
> +
>  #endif // _VIRTIO_MMIO_DEVICE_INTERNAL_H_
> diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
> index 9142d4a162c0..f3f69f324c6c 100644
> --- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
> +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
> @@ -16,6 +16,8 @@
>  
>  **/
>  
> +#include <Library/MemoryAllocationLib.h>
> +
>  #include "VirtioMmioDevice.h"
>  

(1) The "VirtioMmioDevice.h" header includes the header files that are
used by both "VirtioMmioDevice.c" and "VirtioMmioDeviceFunctions.c".

Before your patch, "MemoryAllocationLib.h" was needed only by the former
C file. After your patch, "MemoryAllocationLib.h" is needed by both C files.

Therefore, rather than adding this #include directive here, please move
the same #include directive from "VirtioMmioDevice.c" to
"VirtioMmioDevice.h".

>  EFI_STATUS
> @@ -293,3 +295,60 @@ VirtioMmioDeviceRead (
>  
>    return EFI_SUCCESS;
>  }
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioMmioAllocateSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *This,
> +  IN  UINTN                   NumPages,
> +  OUT VOID                    **HostAddress
> +  )
> +{
> +  VOID        *Buffer;
> +
> +  Buffer = AllocatePages (NumPages);
> +  if (Buffer == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  *HostAddress = Buffer;
> +  return EFI_SUCCESS;
> +}
> +
> +VOID
> +EFIAPI
> +VirtioMmioFreeSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *This,
> +  IN  UINTN                   NumPages,
> +  IN  VOID                    *HostAddress
> +  )
> +{
> +  FreePages (HostAddress, NumPages);
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioMmioMapSharedBuffer (
> +  IN      VIRTIO_DEVICE_PROTOCOL  *This,
> +  IN      VIRTIO_MAP_OPERATION    Operation,
> +  IN      VOID                    *HostAddress,
> +  IN OUT  UINTN                   *NumberOfBytes,
> +  OUT     EFI_PHYSICAL_ADDRESS    *DeviceAddress,
> +  OUT     VOID                    **Mapping
> +  )
> +{
> +  *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
> +  *Mapping = NULL;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioMmioUnmapSharedBuffer (
> +  IN  VIRTIO_DEVICE_PROTOCOL    *This,
> +  OUT VOID                      *Mapping

(2) "Mapping" should be "IN".

(The function declaration is correct, only the definition has this wart.)

> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> 

(3) You forgot to populate the IOMMU-like member functions in the
"mMmioDeviceProtocolTemplate" structure, in
"OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c".

(I realize this wasn't caught on your side due to difficulties with
aarch64 testing.)

(4) You might want to add AMD copyright notices to these files as well.
(Not sure what your company policy requires -- nowadays the git history
should be totally enough for preexistent files, but some companies
require their associates to add explicit (C) notices to every file they
touch.)

Thanks!
Laszlo


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

* Re: [PATCH v2 10/23] OvmfPkg/VirtioLib: add VirtioMapAllBytesInSharedBuffer() helper function
  2017-08-14 11:36 ` [PATCH v2 10/23] OvmfPkg/VirtioLib: add VirtioMapAllBytesInSharedBuffer() helper function Brijesh Singh
@ 2017-08-16 16:47   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16 16:47 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> The function can be used for mapping the system physical address to virtio
> device address using VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer (). The
> function helps centralizing error handling, and it allows caller to pass

(1) some grammar bikeshedding:

- s/helps centralizing/helps with centralizing/

- s/allows caller/allows the caller/

> in constant or other evaluated expression for NumberOfBytes.

- s/expression/expressions/

> 
> 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/Include/Library/VirtioLib.h   | 44 +++++++++++
>  OvmfPkg/Library/VirtioLib/VirtioLib.c | 78 ++++++++++++++++++++
>  2 files changed, 122 insertions(+)
> 
> diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
> index 5badfb32917f..d8f24a5d68b1 100644
> --- a/OvmfPkg/Include/Library/VirtioLib.h
> +++ b/OvmfPkg/Include/Library/VirtioLib.h
> @@ -3,6 +3,7 @@
>    Declarations of utility functions used by virtio device drivers.
>  
>    Copyright (C) 2012-2016, Red Hat, Inc.
> +  Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
>  
>    This program and the accompanying materials are licensed and made available
>    under the terms and conditions of the BSD License which accompanies this
> @@ -235,4 +236,47 @@ Virtio10WriteFeatures (
>    IN OUT UINT8                  *DeviceStatus
>    );
>  
> +/**
> +  Provides the virtio device address required to access system memory from a
> +  DMA bus master.
> +

This part is slightly out of synch with the protocol definition itself
(i.e., with VIRTIO_MAP_SHARED): the UEFI spec reference is missing.

However, that's fine: this function diverges slightly from the spec --
that's exactly where the extra convenience comes from. So this is OK.

> +  @param[in]     This             The protocol instance pointer.
> +

(2) This should say instead:

  @param[in] VirtIo  The virtio device for which the mapping is
                     requested.

> +  @param[in]     Operation        Indicates if the bus master is going to
> +                                  read or write to system memory.
> +
> +  @param[in]     HostAddress      The system memory address to map to shared
> +                                  buffer address.
> +
> +  @param[in,out] NumberOfBytes    On input the number of bytes to map.
> +                                  On output the number of bytes that were
> +                                  mapped.

(3) This is wrong. In my v1 review
<http://mid.mail-archive.com/9e743ec8-f2fe-65f2-9594-4731d2481a88@redhat.com>,
point (3), I wrote,

    Basically you can copy the MapSharedBuffer() documentation, just
    point out the extra logic for NumberOfBytes.

That description is missing -- NumberOfBytes is an IN-only parameter
here, and it is interpreted as a hard requirement.

> +
> +  @param[out]    DeviceAddress    The resulting shared map address for the
> +                                  bus master to access the hosts HostAddress.
> +
> +  @param[out]    Mapping          A resulting taken to pass to
> +                                  VIRTIO_UNMAP_SHARED.

(4) s/taken/token/, as discussed before

> +
> +
> +  @retval EFI_SUCCESS             The range was mapped for the returned
> +                                  NumberOfBytes.

(5) This too should be adapted to our particular NumberOfBytes
interpretation.

> +  @retval EFI_UNSUPPORTED         The HostAddress cannot be mapped as a
> +                                  common buffer.
> +  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
> +  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to
> +                                  a lack of resources.

(6) Please add, "This includes the case when NumberOfBytes bytes cannot
be mapped in one consecutive range."

> +  @retval EFI_DEVICE_ERROR        The system hardware could not map the
> +                                  requested address.
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioMapAllBytesInSharedBuffer (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  VIRTIO_MAP_OPERATION    Operation,
> +  IN  VOID                    *HostAddress,
> +  IN  UINTN                   NumberOfBytes,
> +  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
> +  OUT VOID                    **Mapping
> +  );
>  #endif // _VIRTIO_LIB_H_
> diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
> index 845f206369a3..ac0ae97f3692 100644
> --- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
> +++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
> @@ -4,6 +4,7 @@
>  
>    Copyright (C) 2012-2016, Red Hat, Inc.
>    Portion of Copyright (C) 2013, ARM Ltd.
> +  Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
>  
>    This program and the accompanying materials are licensed and made available
>    under the terms and conditions of the BSD License which accompanies this
> @@ -414,3 +415,80 @@ Virtio10WriteFeatures (
>  
>    return Status;
>  }
> +
> +/**
> +  Provides the virtio device address required to access system memory from a
> +  DMA bus master.
> +
> +  @param[in]     This             The protocol instance pointer.
> +
> +  @param[in]     Operation        Indicates if the bus master is going to
> +                                  read or write to system memory.
> +
> +  @param[in]     HostAddress      The system memory address to map to shared
> +                                  buffer address.
> +
> +  @param[in,out] NumberOfBytes    On input the number of bytes to map.
> +                                  On output the number of bytes that were
> +                                  mapped.
> +
> +  @param[out]    DeviceAddress    The resulting shared map address for the
> +                                  bus master to access the hosts HostAddress.
> +
> +  @param[out]    Mapping          A resulting taken to pass to
> +                                  VIRTIO_UNMAP_SHARED.
> +
> +
> +  @retval EFI_SUCCESS             The range was mapped for the returned
> +                                  NumberOfBytes.
> +  @retval EFI_UNSUPPORTED         The HostAddress cannot be mapped as a
> +                                  common buffer.
> +  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
> +  @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to
> +                                  a lack of resources.
> +  @retval EFI_DEVICE_ERROR        The system hardware could not map the
> +                                  requested address.
> +**/

(7) Please sync this with points (2) through (6) above.

> +EFI_STATUS
> +EFIAPI
> +VirtioMapAllBytesInSharedBuffer (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  VIRTIO_MAP_OPERATION    Operation,
> +  IN  VOID                    *HostAddress,
> +  IN  UINTN                   NumberOfBytes,
> +  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
> +  OUT VOID                    **Mapping
> +  )
> +{
> +  EFI_STATUS            Status;
> +  VOID                  *MapInfo;
> +  UINTN                 Size;
> +  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
> +
> +  Size = NumberOfBytes;
> +  Status = VirtIo->MapSharedBuffer (
> +                     VirtIo,
> +                     Operation,
> +                     HostAddress,
> +                     &Size,
> +                     &PhysicalAddress,
> +                     &MapInfo
> +                     );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  if (Size < NumberOfBytes) {
> +    goto Failed;
> +  }
> +
> +  *Mapping = MapInfo;
> +  *DeviceAddress = PhysicalAddress;
> +
> +  return EFI_SUCCESS;
> +
> +Failed:
> +  VirtIo->UnmapSharedBuffer (VirtIo, MapInfo);
> +  *Mapping = NULL;
> +  return EFI_OUT_OF_RESOURCES;
> +}
> 

(8) The logic differs slightly from the previous version: in this
version you set Mapping to NULL on error.

I liked the previous version more; IMO we should not touch output
parameters on error (that's why you introduced MapInfo earlier, to begin
with).

So I suggest dropping the NULL-ing on error.

Thanks
Laszlo


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

* Re: [PATCH v2 11/23] OvmfPkg/VirtioLib: take VirtIo instance in VirtioRingInit/VirtioRingUninit
  2017-08-14 11:36 ` [PATCH v2 11/23] OvmfPkg/VirtioLib: take VirtIo instance in VirtioRingInit/VirtioRingUninit Brijesh Singh
@ 2017-08-16 16:53   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16 16:53 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> Passing the VirtIo protocol instance will allow the vring to use
> VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages () to allocate vring buffer.
> 
> 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/Include/Library/VirtioLib.h   | 14 ++++++++++----
>  OvmfPkg/Library/VirtioLib/VirtioLib.c | 14 ++++++++++----
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.c      |  7 ++++---
>  OvmfPkg/VirtioGpuDxe/Commands.c       |  7 ++++---
>  OvmfPkg/VirtioNetDxe/SnpInitialize.c  |  9 +++++----
>  OvmfPkg/VirtioNetDxe/SnpShutdown.c    |  5 +++--
>  OvmfPkg/VirtioRngDxe/VirtioRng.c      |  7 ++++---
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.c    |  7 ++++---
>  8 files changed, 44 insertions(+), 26 deletions(-)

All comments from my previous review have been addressed, so:

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

Thanks!
Laszlo


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

* Re: [PATCH v2 12/23] OvmfPkg/VirtioLib: add functions to map/unmap VRING
  2017-08-14 11:36 ` [PATCH v2 12/23] OvmfPkg/VirtioLib: add functions to map/unmap VRING Brijesh Singh
@ 2017-08-16 20:56   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16 20:56 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> Add functions to map and unmap the ring buffer with BusMasterCommonBuffer
> so that ring can be accessed by both guest and hypervisor.
> 
> 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/Include/Library/VirtioLib.h   | 25 +++++++++++
>  OvmfPkg/Library/VirtioLib/VirtioLib.c | 44 ++++++++++++++++++++
>  2 files changed, 69 insertions(+)

(1) The subject and the commit message both should say "a function"
(singular) now -- we've only kept VirtioRingMap().

Unmap shoud not be referenced in either the subject or the commit message.

> 
> diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
> index ca0b217a04eb..1efb02a68cf1 100644
> --- a/OvmfPkg/Include/Library/VirtioLib.h
> +++ b/OvmfPkg/Include/Library/VirtioLib.h
> @@ -62,6 +62,31 @@ VirtioRingInit (
>  
>  /**
>  
> +  Map the ring buffer so that it can be accessed equally by both guest
> +  and hypervisor.
> +
> +  @param[in]      VirtIo          The virtio device instance.
> +
> +  @param[in]      Ring            The virtio ring to map.
> +
> +  @param[out]     RingBaseShift   

The fact that you either forgot, or had difficulties with, the
explanation of the RingBaseShift output parameter, is not random. It has
a deeper cause.

The cause is that placing this patch at this exact position in the
series constitutes a layering violation.

In my previous review
<http://mid.mail-archive.com/01220a3b-565b-8a36-406d-cfcc63265fb7@redhat.com>,
point (10), I tried to clarify this ("*Then* please include the present
patch", emphasis added now), but I must have been unclear.

So, the idea is that
- the VirtioLib helper functions (code, comments, and commit messages)
are allowed to reference VIRTIO_DEVICE_PROTOCOL specifics,
- but references in the opposite direction should be avoided if possible.

You are introducing this patch at position 12 in the series, and in the
next patch, for the virtio protocol, you refer to VirtioRingMap() in the
commit message. This should not be done -- the opposite dependency
should be constructed.

(2) So please, move this patch two positions toward the tail of the series:

  OvmfPkg/VirtioLib: add functions to map/unmap VRING -----------+
  OvmfPkg/Virtio: take RingBaseShift in VirtioSetQueueAddress()  |
  OvmfPkg/Virtio10Dxe: add the RingBaseShift offset              |
  <HERE> <-------------------------------------------------------+
  OvmfPkg/VirtioLib: alloc vring buffer with AllocateSharedPages()

(3) Then you can document the RingBaseShift parameter simply like this,
in this patch:

  @param[out] RingBaseShift  A resulting translation offset, to be
                             passed to VirtIo->SetQueueAddress().


> +
> +  @param[out]     Mapping         A resulting token to pass to
> +                                  VirtIo->UnmapSharedBuffer().
> +
> +  @return         Status from VirtIo->MapSharedBuffer()

(4) This is an improvement on the previous version of the patch, but the
.c and .h files differ ("Status code" vs "Status").

So please sync the full comment blocks (after addressing (3) as well).

> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioRingMap (
> +  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
> +  IN  VRING                  *Ring,
> +  OUT UINT64                 *RingBaseShift,
> +  OUT VOID                   **Mapping
> +  );
> +
> +/**
> +
>    Tear down the internal resources of a configured virtio ring.
>  
>    The caller is responsible to stop the host from using this ring before
> diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
> index 5b64d18a8d6f..7d07dcc09d3d 100644
> --- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
> +++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
> @@ -498,3 +498,47 @@ Failed:
>    *Mapping = NULL;
>    return EFI_OUT_OF_RESOURCES;
>  }
> +
> +/**
> +
> +  Map the ring buffer so that it can be accessed equally by both guest
> +  and hypervisor.
> +
> +  @param[in]      VirtIo          The virtio device instance.
> +
> +  @param[in]      Ring            The virtio ring to map.
> +
> +  @param[out]     RingBaseShift   RingBaseShift
> +
> +  @param[out]     Mapping         A resulting token to pass to
> +                                  VirtIo->UnmapSharedBuffer().
> +
> +  @return         Status code from VirtIo->MapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioRingMap (
> +  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
> +  IN  VRING                  *Ring,
> +  OUT UINT64                 *RingBaseShift,
> +  OUT VOID                   **Mapping
> +  )
> +{
> +  EFI_STATUS        Status;
> +  PHYSICAL_ADDRESS  DeviceAddress;

(5) Technically this is correct (both EFI_PHYSICAL_ADDRESS and
PHYSICAL_ADDRESS are typedefs for UINT64).

For consistency with the prototype of VirtioMapAllBytesInSharedBuffer(),
EFI_PHYSICAL_ADDRESS would be slightly better in my opinion.

> +
> +  Status = VirtioMapAllBytesInSharedBuffer (
> +             VirtIo,
> +             VirtioOperationBusMasterCommonBuffer,
> +             Ring->Base,
> +             EFI_PAGES_TO_SIZE (Ring->NumPages),
> +             &DeviceAddress,
> +             Mapping

This is fine -- we're passing "Mapping" directly to
VirtioMapAllBytesInSharedBuffer(), but we know that said function won't
modify Mapping if it fails.

(Just please address point (8) in my "PATCH v2 10/23" feedback -- i.e.,
VirtioMapAllBytesInSharedBuffer() should not null "Mapping" on error.)

> +             );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  *RingBaseShift = DeviceAddress - (UINT64)(UINTN)Ring->Base;
> +  return EFI_SUCCESS;
> +}
> 

Looks good!

Thank you!
Laszlo


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

* Re: [PATCH v2 13/23] OvmfPkg/Virtio: take RingBaseShift in VirtioSetQueueAddress()
  2017-08-14 11:36 ` [PATCH v2 13/23] OvmfPkg/Virtio: take RingBaseShift in VirtioSetQueueAddress() Brijesh Singh
@ 2017-08-16 21:43   ` Laszlo Ersek
  2017-08-16 21:51     ` Laszlo Ersek
  0 siblings, 1 reply; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16 21:43 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

(1) The "VirtioSetQueueAddress" identifier does not exist in the edk2
tree as a function or protocol member name, so I suggest at least
replacing "VirtioSetQueueAddress" with "SetQueueAddress".

On 08/14/17 13:36, Brijesh Singh wrote:
> VirtioRingMap() maps the ring buffer system physical to a bus address.
> When an IOMMU is used for translating the address then bus address can
> start at a different offset from the system physical address.

(2) I suggest the following wording in order to keep our references
within the virtio device protocol:

    For the case when an IOMMU is used for translating system physical
    addresses to DMA bus master addresses, the transport-independent
    virtio device drivers will be required to map their VRING areas to
    bus addresses with VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer() calls.

> - MMIO and legacy virtio device does not use IOMMU to translate the
>   addresses hence RingBaseShift will always be set to zero.

(3) s/device does not use/transports do not support/

>
> - modern virtio device use IOMMU to translate the address, in next patch

(4) s/device use/transport supports/

>   we will update the Virtio10Dxe to use RingBaseShift offset.
>
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> 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/Include/Protocol/VirtioDevice.h                         | 5 ++++-
>  OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h          | 3 ++-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h                    | 3 ++-
>  OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c | 5 ++++-
>  OvmfPkg/Virtio10Dxe/Virtio10.c                                  | 5 ++++-
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.c                                | 2 +-
>  OvmfPkg/VirtioGpuDxe/Commands.c                                 | 3 ++-
>  OvmfPkg/VirtioNetDxe/SnpInitialize.c                            | 2 +-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c                 | 5 ++++-
>  OvmfPkg/VirtioRngDxe/VirtioRng.c                                | 2 +-
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.c                              | 2 +-
>  11 files changed, 26 insertions(+), 11 deletions(-)
>
> diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
> index 14f980d7bf0a..25fd73b847a5 100644
> --- a/OvmfPkg/Include/Protocol/VirtioDevice.h
> +++ b/OvmfPkg/Include/Protocol/VirtioDevice.h
> @@ -156,6 +156,8 @@ EFI_STATUS
>    @param[in] Ring             The initialized VRING object to take the
>                                addresses from.
>
> +  @param[in] RingBaseShift    The offset for the Ring Base address.
> +

OK, so this comment block is critical.

(5) Please update the documentation of the "Ring" parameter like this:

  @param[in] Ring             The initialized VRING object to take the
                              addresses from. The caller is responsible for
                              ensuring that on input, all Ring->NumPages pages,
                              starting at Ring->Base, have been successfully
                              mapped with a single call to
                              This->MapSharedBuffer().

(This documentation basically provides the specification for our
VirtioRingMap() function.)

(6) Then we can simply define RingBaseShift like this:

  @param[in] RingBaseShift    Adding this value using UINT64 arithmetic to the
                              addresses found in Ring translates them from
                              system memory to bus addresses. The caller shall
                              calculate RingBaseShift as
                              (DeviceAddress - (UINT64)(UINTN)HostAddress),
                              where DeviceAddress and HostAddress (i.e.,
                              Ring->Base) were output and input parameters of
                              This->MapSharedBuffer(), respectively.

>    @retval EFI_SUCCESS         The data was written successfully.
>    @retval EFI_UNSUPPORTED     The underlying IO device doesn't support the
>                                provided address offset and write size.
> @@ -164,7 +166,8 @@ typedef
>  EFI_STATUS
>  (EFIAPI *VIRTIO_SET_QUEUE_ADDRESS) (
>    IN VIRTIO_DEVICE_PROTOCOL  *This,
> -  IN VRING                   *Ring
> +  IN VRING                   *Ring,
> +  IN UINT64                  RingBaseShift
>    );
>
>  /**
> diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
> index b69f6d7b7a85..b5cc091fe820 100644
> --- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
> +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h
> @@ -113,7 +113,8 @@ VirtioMmioSetQueueSel (
>  EFI_STATUS
>  VirtioMmioSetQueueAddress (
>    IN VIRTIO_DEVICE_PROTOCOL  *This,
> -  IN VRING                   *Ring
> +  IN VRING                   *Ring,
> +  IN UINT64                  RingBaseShift
>    );
>
>  EFI_STATUS
> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
> index 41df5a98e560..1f0dc45d501e 100644
> --- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
> +++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
> @@ -126,7 +126,8 @@ EFI_STATUS
>  EFIAPI
>  VirtioPciSetQueueAddress (
>    IN VIRTIO_DEVICE_PROTOCOL  *This,
> -  IN VRING                   *Ring
> +  IN VRING                   *Ring,
> +  IN UINT64                  RingBaseShift
>    );
>
>  EFI_STATUS
> diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
> index f3f69f324c6c..3d14b1035e91 100644
> --- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
> +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
> @@ -183,11 +183,14 @@ VirtioMmioSetQueueSel (
>  EFI_STATUS
>  VirtioMmioSetQueueAddress (
>    IN VIRTIO_DEVICE_PROTOCOL  *This,
> -  IN VRING                   *Ring
> +  IN VRING                   *Ring,
> +  IN UINT64                  RingBaseShift
>    )
>  {
>    VIRTIO_MMIO_DEVICE *Device;
>
> +  ASSERT (RingBaseShift == 0);
> +
>    Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);
>
>    VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN,
> diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
> index 413ffa06cf35..d102e1fd8551 100644
> --- a/OvmfPkg/Virtio10Dxe/Virtio10.c
> +++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
> @@ -489,7 +489,8 @@ EFI_STATUS
>  EFIAPI
>  Virtio10SetQueueAddress (
>    IN VIRTIO_DEVICE_PROTOCOL  *This,
> -  IN VRING                   *Ring
> +  IN VRING                   *Ring,
> +  IN UINT64                  RingBaseShift
>    )
>  {
>    VIRTIO_1_0_DEV *Dev;
> @@ -497,6 +498,8 @@ Virtio10SetQueueAddress (
>    UINT64         Address;
>    UINT16         Enable;
>
> +  ASSERT (RingBaseShift == 0);
> +
>    Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
>
>    Address = (UINTN)Ring->Desc;
> diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> index 61b9cab4ff02..bff15fe3add1 100644
> --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> @@ -745,7 +745,7 @@ VirtioBlkInit (
>    //
>    // step 4c -- Report GPFN (guest-physical frame number) of queue.
>    //
> -  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);
> +  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);
>    if (EFI_ERROR (Status)) {
>      goto ReleaseQueue;
>    }
> diff --git a/OvmfPkg/VirtioGpuDxe/Commands.c b/OvmfPkg/VirtioGpuDxe/Commands.c
> index c2e4d72feb67..df8ded99edff 100644
> --- a/OvmfPkg/VirtioGpuDxe/Commands.c
> +++ b/OvmfPkg/VirtioGpuDxe/Commands.c
> @@ -132,7 +132,8 @@ VirtioGpuInit (
>    if (EFI_ERROR (Status)) {
>      goto Failed;
>    }
> -  Status = VgpuDev->VirtIo->SetQueueAddress (VgpuDev->VirtIo, &VgpuDev->Ring);
> +  Status = VgpuDev->VirtIo->SetQueueAddress (VgpuDev->VirtIo,
> +                              &VgpuDev->Ring, 0);

(7) Please break all arguments to separate lines (and the closing paren
to another separate line).

The rest looks fine, thanks!
Laszlo

>    if (EFI_ERROR (Status)) {
>      goto ReleaseQueue;
>    }
> diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
> index 6d9b81a9f939..0ecfe044a977 100644
> --- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
> +++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
> @@ -96,7 +96,7 @@ VirtioNetInitRing (
>    //
>    // step 4c -- report GPFN (guest-physical frame number) of queue
>    //
> -  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring);
> +  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, Ring, 0);
>    if (EFI_ERROR (Status)) {
>      goto ReleaseQueue;
>    }
> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
> index 4597095deb78..86f752e1651f 100644
> --- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
> +++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
> @@ -183,11 +183,14 @@ EFI_STATUS
>  EFIAPI
>  VirtioPciSetQueueAddress (
>    IN VIRTIO_DEVICE_PROTOCOL  *This,
> -  IN VRING                   *Ring
> +  IN VRING                   *Ring,
> +  IN UINT64                  RingBaseShift
>    )
>  {
>    VIRTIO_PCI_DEVICE *Dev;
>
> +  ASSERT (RingBaseShift == 0);
> +
>    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
>
>    return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
> diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.c b/OvmfPkg/VirtioRngDxe/VirtioRng.c
> index e20602ac7225..0abca488e6cd 100644
> --- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
> +++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
> @@ -298,7 +298,7 @@ VirtioRngInit (
>    //
>    // step 4c -- Report GPFN (guest-physical frame number) of queue.
>    //
> -  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);
> +  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);
>    if (EFI_ERROR (Status)) {
>      goto ReleaseQueue;
>    }
> diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> index c2f6f412ff40..a983b3df7b9c 100644
> --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> @@ -855,7 +855,7 @@ VirtioScsiInit (
>    //
>    // step 4c -- Report GPFN (guest-physical frame number) of queue.
>    //
> -  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);
> +  Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);
>    if (EFI_ERROR (Status)) {
>      goto ReleaseQueue;
>    }
>



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

* Re: [PATCH v2 13/23] OvmfPkg/Virtio: take RingBaseShift in VirtioSetQueueAddress()
  2017-08-16 21:43   ` Laszlo Ersek
@ 2017-08-16 21:51     ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16 21:51 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/16/17 23:43, Laszlo Ersek wrote:
> (1) The "VirtioSetQueueAddress" identifier does not exist in the edk2
> tree as a function or protocol member name, so I suggest at least
> replacing "VirtioSetQueueAddress" with "SetQueueAddress".
> 
> On 08/14/17 13:36, Brijesh Singh wrote:
>> VirtioRingMap() maps the ring buffer system physical to a bus address.
>> When an IOMMU is used for translating the address then bus address can
>> start at a different offset from the system physical address.
> 
> (2) I suggest the following wording in order to keep our references
> within the virtio device protocol:
> 
>     For the case when an IOMMU is used for translating system physical
>     addresses to DMA bus master addresses, the transport-independent
>     virtio device drivers will be required to map their VRING areas to
>     bus addresses with VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer() calls.
> 
>> - MMIO and legacy virtio device does not use IOMMU to translate the
>>   addresses hence RingBaseShift will always be set to zero.
> 
> (3) s/device does not use/transports do not support/
> 
>>
>> - modern virtio device use IOMMU to translate the address, in next patch
> 
> (4) s/device use/transport supports/
> 
>>   we will update the Virtio10Dxe to use RingBaseShift offset.
>>
>> Suggested-by: Laszlo Ersek <lersek@redhat.com>
>> 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/Include/Protocol/VirtioDevice.h                         | 5 ++++-
>>  OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.h          | 3 ++-
>>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h                    | 3 ++-
>>  OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c | 5 ++++-
>>  OvmfPkg/Virtio10Dxe/Virtio10.c                                  | 5 ++++-
>>  OvmfPkg/VirtioBlkDxe/VirtioBlk.c                                | 2 +-
>>  OvmfPkg/VirtioGpuDxe/Commands.c                                 | 3 ++-
>>  OvmfPkg/VirtioNetDxe/SnpInitialize.c                            | 2 +-
>>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c                 | 5 ++++-
>>  OvmfPkg/VirtioRngDxe/VirtioRng.c                                | 2 +-
>>  OvmfPkg/VirtioScsiDxe/VirtioScsi.c                              | 2 +-
>>  11 files changed, 26 insertions(+), 11 deletions(-)
>>
>> diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
>> index 14f980d7bf0a..25fd73b847a5 100644
>> --- a/OvmfPkg/Include/Protocol/VirtioDevice.h
>> +++ b/OvmfPkg/Include/Protocol/VirtioDevice.h
>> @@ -156,6 +156,8 @@ EFI_STATUS
>>    @param[in] Ring             The initialized VRING object to take the
>>                                addresses from.
>>
>> +  @param[in] RingBaseShift    The offset for the Ring Base address.
>> +
> 
> OK, so this comment block is critical.
> 
> (5) Please update the documentation of the "Ring" parameter like this:
> 
>   @param[in] Ring             The initialized VRING object to take the
>                               addresses from. The caller is responsible for
>                               ensuring that on input, all Ring->NumPages pages,
>                               starting at Ring->Base, have been successfully
>                               mapped with a single call to
>                               This->MapSharedBuffer().

(5a) oops, small (but important) omission: please append "for
CommonBuffer bus master operation".

Thanks
Laszlo


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

* Re: [PATCH v2 14/23] OvmfPkg/Virtio10Dxe: add the RingBaseShift offset
  2017-08-14 11:36 ` [PATCH v2 14/23] OvmfPkg/Virtio10Dxe: add the RingBaseShift offset Brijesh Singh
@ 2017-08-16 21:57   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16 21:57 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> virtio drivers uses VirtioRingMap() to map the ring buffer host address

(1) Please replace

  "drivers uses VirtioRingMap()"

with

  "drivers use VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer()"

The rest looks fine, thanks!
Laszlo

> to a device address. If an IOMMU is present then RingBaseShift contains
> the offset from the host address.
> 
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> 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/Virtio10Dxe/Virtio10.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
> index d102e1fd8551..e9041dec91a4 100644
> --- a/OvmfPkg/Virtio10Dxe/Virtio10.c
> +++ b/OvmfPkg/Virtio10Dxe/Virtio10.c
> @@ -498,11 +498,10 @@ Virtio10SetQueueAddress (
>    UINT64         Address;
>    UINT16         Enable;
>  
> -  ASSERT (RingBaseShift == 0);
> -
>    Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
>  
>    Address = (UINTN)Ring->Desc;
> +  Address += RingBaseShift;
>    Status = Virtio10Transfer (Dev->PciIo, &Dev->CommonConfig, TRUE,
>               OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueDesc),
>               sizeof Address, &Address);
> @@ -511,6 +510,7 @@ Virtio10SetQueueAddress (
>    }
>  
>    Address = (UINTN)Ring->Avail.Flags;
> +  Address += RingBaseShift;
>    Status = Virtio10Transfer (Dev->PciIo, &Dev->CommonConfig, TRUE,
>               OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueAvail),
>               sizeof Address, &Address);
> @@ -519,6 +519,7 @@ Virtio10SetQueueAddress (
>    }
>  
>    Address = (UINTN)Ring->Used.Flags;
> +  Address += RingBaseShift;
>    Status = Virtio10Transfer (Dev->PciIo, &Dev->CommonConfig, TRUE,
>               OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueUsed),
>               sizeof Address, &Address);
> 



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

* Re: [PATCH v2 15/23] OvmfPkg/VirtioLib: alloc vring buffer with AllocateSharedPages()
  2017-08-14 11:36 ` [PATCH v2 15/23] OvmfPkg/VirtioLib: alloc vring buffer with AllocateSharedPages() Brijesh Singh
@ 2017-08-16 22:18   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-16 22:18 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> 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/Library/VirtioLib/VirtioLib.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)

(1) Where did the commit message go? :) It was pretty good. Here's my
suggestion for reinstating it:

    The VRING buffer is a communication area between guest and
    hypervisor. Allocate it using
    VIRTIO_DEVICE_PROTOCOL.AllocateSharedPages() so that it can be
    mapped later with VirtioRingMap() for bi-directional access.

(This is a VirtioLib patch so we can refer to VirtioRingMap() -- after
the reordering that I requested under [PATCH v2 12/23], point (2), the
VirtioRingMap() function will be introduced just before this patch.)

> diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
> index 7d07dcc09d3d..8010b5cf4735 100644
> --- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
> +++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
> @@ -61,6 +61,7 @@ VirtioRingInit (
>    OUT VRING                  *Ring
>    )
>  {
> +  EFI_STATUS     Status;
>    UINTN          RingSize;
>    volatile UINT8 *RingPagesPtr;
>
> @@ -79,9 +80,16 @@ VirtioRingInit (
>                  sizeof *Ring->Used.AvailEvent,
>                  EFI_PAGE_SIZE);
>
> +  //
> +  // Allocate a shared ring buffer
> +  //
>    Ring->NumPages = EFI_SIZE_TO_PAGES (RingSize);
> -  Ring->Base = AllocatePages (Ring->NumPages);
> -  if (Ring->Base == NULL) {
> +  Status = VirtIo->AllocateSharedPages (
> +                          VirtIo,
> +                          Ring->NumPages,
> +                          &Ring->Base
> +                          );
> +  if (EFI_ERROR (Status)) {
>      return EFI_OUT_OF_RESOURCES;
>    }
>    SetMem (Ring->Base, RingSize, 0x00);
> @@ -143,7 +151,7 @@ VirtioRingUninit (
>    IN OUT VRING                  *Ring
>    )
>  {
> -  FreePages (Ring->Base, Ring->NumPages);
> +  VirtIo->FreeSharedPages (VirtIo, Ring->NumPages, Ring->Base);
>    SetMem (Ring, sizeof *Ring, 0x00);
>  }
>
>

You seem to have missed my points (2), (3) and (4) from my previous
review
<http://mid.mail-archive.com/26a6be37-9983-7a34-afbf-d25e5501b138@redhat.com>:

> (2) Please update the documentation of "@retval EFI_OUT_OF_RESOURCES"
> -- replace it with
>
>   @return  Status codes propagated from VirtIo->AllocateSharedPages().
>
> (3) Accordingly, please forward the Status received, on the error
> branch.
>
> (4) Please remove MemoryAllocationLib from the #includes and also from
> [LibraryClasses].

(5) In addition, the indentation of the AllocateSharedPages() arguments
is incorrect.

To be continued.

Thanks,
Laszlo


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

* Re: [PATCH v2 16/23] OvmfPkg/VirtioRngDxe: map host address to device address
  2017-08-14 11:36 ` [PATCH v2 16/23] OvmfPkg/VirtioRngDxe: map host address to device address Brijesh Singh
@ 2017-08-21 14:05   ` Laszlo Ersek
  2017-08-22 15:44     ` Brijesh Singh
  0 siblings, 1 reply; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-21 14:05 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> patch maps the host address to a device address for buffers (including
> rings, device specifc request and response pointed by vring descriptor,
> and any further 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>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  OvmfPkg/VirtioRngDxe/VirtioRng.h |  1 +
>  OvmfPkg/VirtioRngDxe/VirtioRng.c | 65 +++++++++++++++++---
>  2 files changed, 58 insertions(+), 8 deletions(-)
> 
> diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.h b/OvmfPkg/VirtioRngDxe/VirtioRng.h
> index 998f9fae48c2..b372d84c1ebc 100644
> --- a/OvmfPkg/VirtioRngDxe/VirtioRng.h
> +++ b/OvmfPkg/VirtioRngDxe/VirtioRng.h
> @@ -38,6 +38,7 @@ typedef struct {
>    EFI_EVENT                 ExitBoot;       // DriverBindingStart   0
>    VRING                     Ring;           // VirtioRingInit       2
>    EFI_RNG_PROTOCOL          Rng;            // VirtioRngInit        1
> +  VOID                      *RingMap;       // VirtioRngInit        1
>  } VIRTIO_RNG_DEV;

(1) Please change the "depth" value from 1 to 2 on the right-hand side.
"RingMap" has the same initialization depth as "Ring".

Also, please change the function name from "VirtioRngInit" to
"VirtioRingMap".

>  
>  #define VIRTIO_ENTROPY_SOURCE_FROM_RNG(RngPointer) \
> diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.c b/OvmfPkg/VirtioRngDxe/VirtioRng.c
> index 0abca488e6cd..fc01f1996654 100644
> --- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
> +++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
> @@ -140,6 +140,8 @@ VirtioRngGetRNG (
>    UINT32                    Len;
>    UINT32                    BufferSize;
>    EFI_STATUS                Status;
> +  EFI_PHYSICAL_ADDRESS      DeviceAddress;
> +  VOID                      *Mapping;
>  
>    if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {
>      return EFI_INVALID_PARAMETER;
> @@ -159,6 +161,20 @@ VirtioRngGetRNG (
>    }
>  
>    Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
> +  //
> +  // Map the Buffers system phyiscal address to device address
> +  //

(2) s/the Buffers/Buffer's/

> +  Status = VirtioMapAllBytesInSharedBuffer (
> +             Dev->VirtIo,
> +             VirtioOperationBusMasterWrite,
> +             (VOID *)Buffer,
> +             RNGValueLength,
> +             &DeviceAddress,
> +             &Mapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    goto FreeBuffer;
> +  }
>  
>    //
>    // The Virtio RNG device may return less data than we asked it to, and can
> @@ -170,7 +186,7 @@ VirtioRngGetRNG (
>  
>      VirtioPrepare (&Dev->Ring, &Indices);
>      VirtioAppendDesc (&Dev->Ring,
> -      (UINTN)Buffer + Index,
> +      (UINTN)DeviceAddress + Index,

(3) Please insert a new VirtioLib patch in the series, before this
patch. The new patch should:

(3a) change the "BufferPhysAddr" parameter of VirtioAppendDesc() from
     type UINTN to UINT64,

(3b) rename the same parameter to "BufferDeviceAddress",

(3c) replace the following parameter documentation string:

     "(Guest pseudo-physical)"

     with the string

     "Bus master device"

Justification:

UINTN is appropriate as long as we pass system memory references. After
the introduction of this feature, that's no longer the case in general.
Should we implement "real" IOMMU support at some point, UINTN could
break in 32-bit builds of OVMF.

The definition of VirtioAppendDesc() itself needs no update (beyond the
parameter rename), because the VRING_DESC.Addr field already has type
UINT64.


(4) In this patch, please remove the UINTN cast, and just say

  DeviceAddress + Index

Same for the rest of the patches. (I haven't seen them yet, but I assume
the same pattern is repeated in them.)

>        BufferSize,
>        VRING_DESC_F_WRITE,
>        &Indices);
> @@ -178,17 +194,30 @@ VirtioRngGetRNG (
>      if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=
>          EFI_SUCCESS) {
>        Status = EFI_DEVICE_ERROR;
> -      goto FreeBuffer;
> +      goto UnmapBuffer;
>      }
>      ASSERT (Len > 0);
>      ASSERT (Len <= BufferSize);
>    }
>  
> +  //
> +  // Unmap the device buffer before accesing it.
> +  //
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
> +

(5) In the following messages:

-
http://mid.mail-archive.com/f953ec03-b160-726b-b9ed-5e3122642815@redhat.com
- http://mid.mail-archive.com/35b958de-ed97-6275-be96-1cbb93a99d97@amd.com

we agreed that EFI_STATUS was the appropriate return type for
VIRTIO_UNMAP_SHARED. We also agreed that we'd check the return value
when necessary -- that is, when we are after a bus master write
operation and want to consume the data produced by the device.

So, please check the return status here, and jump to FreeBuffer if the
unmap fails.

(With VIRTIO_UNMAP_SHARED, we imitate EFI_PCI_IO_PROTOCOL.Unmap(). The
specification says, "Any resources used for the mapping are freed" --
this is unconditional. The part that can fail is "committing the data to
target system memory". So, if the UnmapSharedBuffer() call fails, we
must skip consuming the data, but still proceed with freeing the buffer.)

Ignoring the return value of UnmapSharedBuffer() is OK on error handling
paths.

>    for (Index = 0; Index < RNGValueLength; Index++) {
>      RNGValue[Index] = Buffer[Index];
>    }
>    Status = EFI_SUCCESS;
>  
> +  //
> +  // Buffer is already Unmaped(), goto free it.
> +  //
> +  goto FreeBuffer;

(6) We restrict "goto" statements to error handling:

https://edk2-docs.gitbooks.io/edk-ii-c-coding-standards-specification/content/5_source_files/57_c_programming.html

> 5.7.3.8 Goto Statements should not be used (in general)
> [...]
> It is common to use goto for error handling and thus, exiting a
> routine in an error case is the only legal use of a goto. [...]

So please open-code the FreePool() call and the "return" statement here.

> +
> +UnmapBuffer:
> +    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
> +

(7) The function call is incorrectly indented.

>  FreeBuffer:
>    FreePool ((VOID *)Buffer);
>    return Status;
> @@ -205,6 +234,7 @@ VirtioRngInit (
>    EFI_STATUS Status;
>    UINT16     QueueSize;
>    UINT64     Features;
> +  UINT64     RingBaseShift;
>  
>    //
>    // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
> @@ -281,26 +311,33 @@ VirtioRngInit (
>      goto Failed;
>    }
>  

(8) Please add a comment here:

  //
  // If anything fails from here on, we must release the ring resources.
  //

> +  Status = VirtioRingMap (Dev->VirtIo, &Dev->Ring, &RingBaseShift,
> +             &Dev->RingMap);

(9) Please break each argument to a separate line.

(As much as I personally prefer the style visible above, it is not (one
of) the edk2 coding style(s). :( Not yet, anyway.)

> +  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.
>    //

(10) Please replace the word "release" with "unmap", in the above comment.

>    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);

(11) Please break each argument to a separate line.

>    if (EFI_ERROR (Status)) {
> -    goto ReleaseQueue;
> +    goto UnmapQueue;
>    }
>  
>    //
> @@ -310,7 +347,7 @@ VirtioRngInit (
>      Features &= ~(UINT64)VIRTIO_F_VERSION_1;
>      Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
>      if (EFI_ERROR (Status)) {
> -      goto ReleaseQueue;
> +      goto UnmapQueue;
>      }
>    }
>  
> @@ -320,7 +357,7 @@ VirtioRngInit (
>    NextDevStat |= VSTAT_DRIVER_OK;
>    Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
>    if (EFI_ERROR (Status)) {
> -    goto ReleaseQueue;
> +    goto UnmapQueue;
>    }
>  
>    //
> @@ -331,6 +368,9 @@ VirtioRngInit (
>  
>    return EFI_SUCCESS;
>  
> +UnmapQueue:
> +    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
> +

(12) The function call is incorrectly indented.

>  ReleaseQueue:
>    VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
>  
> @@ -359,6 +399,9 @@ VirtioRngUninit (
>    // the old comms area.
>    //
>    Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
> +
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
> +
>    VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
>  }
>  
> @@ -385,6 +428,12 @@ VirtioRngExitBoot (
>    //
>    Dev = Context;
>    Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
> +
> +  //
> +  // Umap the ring buffer so that hypervisor will not able to get readable data

(13) s/Umap/Unmap/; also s/will not able/will not be able/

(Please make sure the line doesn't become overlong.)

> +  // after device reset.
> +  //
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
>  }
>  
>  
> 

The logic seems fine otherwise.

Thanks!
Laszlo


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

* Re: [PATCH v2 17/23] OvmfPkg/VirtioBlkDxe: map host address to device address
  2017-08-14 11:36 ` [PATCH v2 17/23] OvmfPkg/VirtioBlkDxe: " Brijesh Singh
@ 2017-08-21 15:24   ` Laszlo Ersek
  2017-08-22  1:42     ` Brijesh Singh
  0 siblings, 1 reply; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-21 15:24 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> The SynchronousRequest(), programs the vring descriptor with the buffers

(1) you likely meant "The SynchronousRequest() function"

> pointed-by virtio-blk requests, status and memory that is referenced
> inside the request header.
> 
> The patch uses VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer() function to map
> host address to device address and programs the vring descriptor with
> device addresses.
> 
> 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.h |   1 +
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 121 +++++++++++++++++---
>  2 files changed, 109 insertions(+), 13 deletions(-)
> 
> diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h
> index 6c402ca88ea4..612994d261bc 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                   *RingMapping;         // VirtioBlkInit       1
>  } VBLK_DEV;

(2) If possible, please use consistent field names between the drivers.
So this should be "RingMap" as well (to follow the pattern set in the
virtio-rng driver).

(3) My earlier comments apply -- depth should be 2, and "VirtioBlkInit"
should be replaced with "VirtioRingMap".

>  
>  #define VIRTIO_BLK_FROM_BLOCK_IO(BlockIoPointer) \
> diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> index bff15fe3add1..57baceb20a19 100644
> --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> @@ -251,6 +251,11 @@ SynchronousRequest (
>    volatile VIRTIO_BLK_REQ Request;
>    volatile UINT8          HostStatus;
>    DESC_INDICES            Indices;
> +  VOID                    *RequestMapping;
> +  VOID                    *StatusMapping;
> +  VOID                    *BufferMapping;
> +  EFI_PHYSICAL_ADDRESS    DeviceAddress;
> +  EFI_STATUS              Status;
>  
>    BlockSize = Dev->BlockIoMedia.BlockSize;
>  
> @@ -289,14 +294,30 @@ SynchronousRequest (
>    ASSERT (Dev->Ring.QueueSize >= 3);
>  
>    //
> +  // Map virtio-blk request header
> +  //
> +  Status = VirtioMapAllBytesInSharedBuffer (
> +             Dev->VirtIo,
> +             VirtioOperationBusMasterRead,
> +             (VOID *) &Request,
> +             sizeof Request,
> +             &DeviceAddress,
> +             &RequestMapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }

(4) You should return EFI_DEVICE_ERROR here, regardless of the Status
received from VirtioMapAllBytesInSharedBuffer().

Please consult the leading comment block on return values.

(5) In fact, please extend the documentation for the EFI_DEVICE_ERROR
retval -- it now includes any case when a mapping for a bus master
operation fails.

> +
> +  //
>    // virtio-blk header in first desc
>    //
> -  VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,
> +  VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress, sizeof Request,
>      VRING_DESC_F_NEXT, &Indices);

(6) Please break every argument to a separate line.

(7) As mentioned earlier, please remove the (UINTN) cast from
"DeviceAddress".

(8) Please do not mix the mapping operations with the virtio ring
manipulation:

(8a) Rather than reusing DeviceAddress, please introduce three local
address variables.

(8b) Concentrate the mapping operations, for all three areas, to one
sequence, before touching the virtio ring.

For this, you might want to move the VirtioPrepare() call as well just
before the first VirtioAppendDesc() call.

(8c) If possible, the virtio ring manipulation code should *only* be
updated with the device addresses; control flow should not be changed.

Basically, the VirtioPrepare() -> VirtioAppendDesc() -> VirtioFlush()
sequence should never be interrupted (due to error conditions or
anything else). All preparations should be done earlier and all errors
should be caught earlier.

This will require quite a bit of reorganization for this patch, so my
remaining comments, for this function anyway, will be somewhat superficial:

>  
>    //
>    // data buffer for read/write in second desc
>    //
> +  BufferMapping = NULL;

(9) This is not useful. As discussed earlier, a NULL mapping can be
valid, dependent on VIRTIO_DEVICE_PROTOCOL implementation, so it
shouldn't be used for control flow.

Instead, please use the (BufferSize > 0) condition to tell a flush
request apart from read/write requests. (See the leading comment block
on the SynchronousRequest() function.)

>    if (BufferSize > 0) {
>      //
>      // From virtio-0.9.5, 2.3.2 Descriptor Table:
> @@ -309,29 +330,86 @@ SynchronousRequest (
>      ASSERT (BufferSize <= SIZE_1GB);
>  
>      //
> +    // Map data buffer
> +    //
> +    if (RequestIsWrite) {
> +      Status = VirtioMapAllBytesInSharedBuffer (
> +                 Dev->VirtIo,
> +                 VirtioOperationBusMasterRead,
> +                 (VOID *) Buffer,
> +                 BufferSize,
> +                 &DeviceAddress,
> +                 &BufferMapping
> +                 );
> +    } else {
> +      Status = VirtioMapAllBytesInSharedBuffer (
> +                 Dev->VirtIo,
> +                 VirtioOperationBusMasterWrite,
> +                 (VOID *) Buffer,
> +                 BufferSize,
> +                 &DeviceAddress,
> +                 &BufferMapping
> +                 );
> +    }
> +
> +    if (EFI_ERROR (Status)) {
> +      goto Unmap_Request_Buffer;
> +    }
> +
> +    //
>      // VRING_DESC_F_WRITE is interpreted from the host's point of view.
>      //
> -    VirtioAppendDesc (&Dev->Ring, (UINTN) Buffer, (UINT32) BufferSize,
> +    VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress, (UINT32) BufferSize,
>        VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE),
>        &Indices);
>    }

(10) Please break every argument to a separate line.

(11) Please remove the (UINTN) cast from the device address.

>  
>    //
> +  // Map virtio-blk status header
> +  //
> +  Status = VirtioMapAllBytesInSharedBuffer (
> +             Dev->VirtIo,
> +             VirtioOperationBusMasterWrite,
> +             (VOID *) &HostStatus,
> +             sizeof HostStatus,
> +             &DeviceAddress,
> +             &StatusMapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    goto Unmap_Data_Buffer;
> +  }
> +
> +  //
>    // host status in last (second or third) desc
>    //
> -  VirtioAppendDesc (&Dev->Ring, (UINTN) &HostStatus, sizeof HostStatus,
> +  VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress, sizeof HostStatus,
>      VRING_DESC_F_WRITE, &Indices);

(12) Please break every argument to a separate line.

(13) Please remove the (UINTN) cast from the device address.

>  
>    //
>    // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
>    //
> -  if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices,
> -        NULL) == EFI_SUCCESS &&
> +  if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, NULL) != EFI_SUCCESS) {
> +    Status = EFI_DEVICE_ERROR;
> +  }
> +

(14) The original code isn't very idiomatic here, please use the
EFI_ERROR() macro instead. (This was the first virtio driver I wrote.)

> +  //
> +  // Unmap the HostStatus buffer before accessing it
> +  //
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, StatusMapping);

(15) Please check the return status.

(16) This is where all three (or all two) mappings should be undone
(with return statuses checked), in reverse order of mapping. If any one
of them fails, you can jump to the corresponding error handling label
(which will continue to unmap stuff, but without checking error statuses).

> +
> +  if (Status != EFI_DEVICE_ERROR &&
>        HostStatus == VIRTIO_BLK_S_OK) {
> -    return EFI_SUCCESS;
> +    Status = EFI_SUCCESS;
> +  } else {
> +    Status = EFI_DEVICE_ERROR;
>    }
>  
> -  return EFI_DEVICE_ERROR;
> +Unmap_Data_Buffer:

(17) Please don't use underscores whenever the coding style requires
CamelCase -- the label should be "UnmapDataBuffer".

> +    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, BufferMapping);

(18) incorrect indentation

> +Unmap_Request_Buffer:

(19) should be "UnmapRequestBuffer".

> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping);
> +
> +  return Status;
>  }
>  
>  
> @@ -601,6 +679,7 @@ VirtioBlkInit (
>    UINT8      AlignmentOffset;
>    UINT32     OptIoSize;
>    UINT16     QueueSize;
> +  UINT64     RingBaseShift;
>  
>    PhysicalBlockExp = 0;
>    AlignmentOffset = 0;
> @@ -728,26 +807,33 @@ VirtioBlkInit (
>      goto Failed;
>    }
>  

(20) Please add a comment here:

  //
  // If anything fails from here on, we must release the ring resources.
  //

> +  Status = VirtioRingMap (Dev->VirtIo, &Dev->Ring, &RingBaseShift,
> +             &Dev->RingMapping);

(21) Please break each argument to a separate line.

> +  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.
>    //

(22) Please replace the word "release" with "unmap", in the above comment.

>    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);

(23) Please break each argument to a separate line.

>    if (EFI_ERROR (Status)) {
> -    goto ReleaseQueue;
> +    goto UnmapQueue;
>    }
>  
>  
> @@ -758,7 +844,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 +854,7 @@ VirtioBlkInit (
>    NextDevStat |= VSTAT_DRIVER_OK;
>    Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
>    if (EFI_ERROR (Status)) {
> -    goto ReleaseQueue;
> +    goto UnmapQueue;
>    }
>  
>    //
> @@ -811,7 +897,10 @@ VirtioBlkInit (
>    }
>    return EFI_SUCCESS;
>  
> +UnmapQueue:
> +    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMapping);

(24) incorrect indentation

>  ReleaseQueue:
> +

(25) I think you intended to add the empty line above the "ReleaseQueue"
label, not below it.

>    VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
>  
>  Failed:

(26) You forgot to call UnmapSharedBuffer() in the VirtioBlkUninit()
function. Each ring must be unmapped in three places:

- in the device init function, if there is an error and we're past
mapping the ring,
- in the device uninit function,
- in the ExitBootServices notify function.

> @@ -885,6 +974,12 @@ VirtioBlkExitBoot (
>    //
>    Dev = Context;
>    Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
> +
> +  //
> +  // Unmap the ring buffer so that hypervisor can not get a readable data
> +  // after device is reset.
> +  //
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMapping);
>  }
>  
>  /**
> 
I think I'm skipping the rest of the series for now (except the last
patch, I have comments for that).

Please rework the rest of the transport-independent virtio drivers (scsi
and net) based on my comments for this (blk) and the previous (rng) patch.

Thanks!
Laszlo


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

* Re: [PATCH v2 23/23] OvmfPkg/Virtio: define VIRITO_F_IOMMU_PLATFORM feature bit
  2017-08-14 11:36 ` [PATCH v2 23/23] OvmfPkg/Virtio: define VIRITO_F_IOMMU_PLATFORM feature bit Brijesh Singh
@ 2017-08-21 15:40   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-21 15:40 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/14/17 13:36, Brijesh Singh wrote:
> This feature indicates that the device is behind an IOMMU that translates
> bus addresses from the device into physical addresses in memory.  If this
> feature bit is set to 0, then the device emits physical addresses which
> are not translated further, even though an IOMMU may be present.
> see [1] for more infromation
> 
> [1] https://lists.oasis-open.org/archives/virtio-dev/201610/msg00121.html
> 
> In previous patches, we have implemented IOMMU-like member functions in
> VIRTIO_DEVICE_PROTOCOL to translate the physical address to bus address
> and virtio drivers are updated to use those member functions. 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.
> 
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> 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/Include/IndustryStandard/Virtio10.h | 5 +++++
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.c            | 3 ++-
>  OvmfPkg/VirtioNetDxe/SnpInitialize.c        | 3 ++-
>  OvmfPkg/VirtioRngDxe/VirtioRng.c            | 2 +-
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.c          | 3 ++-
>  5 files changed, 12 insertions(+), 4 deletions(-)
> 
> diff --git a/OvmfPkg/Include/IndustryStandard/Virtio10.h b/OvmfPkg/Include/IndustryStandard/Virtio10.h
> index 4c9b62a3cf59..c62429d94432 100644
> --- a/OvmfPkg/Include/IndustryStandard/Virtio10.h
> +++ b/OvmfPkg/Include/IndustryStandard/Virtio10.h
> @@ -83,4 +83,9 @@ typedef struct {
>  //
>  #define VIRTIO_F_VERSION_1 BIT32
>  
> +//
> +// VirtIo 1.0 reserved iommu platform feature bits
> +//
> +#define VIRTIO_F_IOMMU_PLATFORM BIT33
> +
>  #endif // _VIRTIO_1_0_H_

(1) The comment is not necessary. Namely, the comment that you see just
above the VIRTIO_F_VERSION_1 macro:

//
// VirtIo 1.0 reserved (device-independent) feature bits
//

is meant as the introduction for the *full set* of such bits.

Given that VIRTIO_F_IOMMU_PLATFORM is just another bit in that set,
please just add it right below VIRTIO_F_VERSION_1.

(2) Please update the whitespace for VIRTIO_F_VERSION_1 as well, so that
the replacement texts (BIT32, BIT33) line up nicely.

(3) Please split this change out to a separate patch.

> diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> index 57baceb20a19..a78ec0df9c7b 100644
> --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c
> @@ -773,7 +773,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

(4) The modifications for this file (VirtioBlk.c) are incomplete.

Namely, in message
<http://mid.mail-archive.com/841bec5f-6f6e-8b1f-25ba-0fd37a915b72@redhat.com>,
points (3) and (5.3), I requested that

> [...] VIRTIO_F_IOMMU_PLATFORM should be treated in OVMF *precisely* in
> parallel with VIRTIO_F_VERSION_1.

Therefore please locate *all* occurrences of VIRTIO_F_VERSION_1, and act
accordingly. In particular, in addition to the above location, we also have:

  //
  // step 5 -- Report understood features.
  //
  if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
    Features &= ~(UINT64)VIRTIO_F_VERSION_1;
    Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
    if (EFI_ERROR (Status)) {
      goto ReleaseQueue;
    }
  }

which should now be changed to:

    Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM);

Same for all the other drivers.

(5) Please split each VIRTIO_F_IOMMU_PLATFORM change to a separate
patch. (That is, one patch per driver.)

- OvmfPkg/Virtio10: define VIRITO_F_IOMMU_PLATFORM feature bit
- OvmfPkg/VirtioBlkDxe: negotiate VIRITO_F_IOMMU_PLATFORM
- OvmfPkg/VirtioNetDxe: negotiate VIRITO_F_IOMMU_PLATFORM
- ...

Thanks,
Laszlo

> diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
> index 9bac19f8e3d1..b389f6243661 100644
> --- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
> +++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
> @@ -536,7 +536,8 @@ VirtioNetInitialize (
>    ASSERT (Dev->Snm.MediaPresentSupported ==
>      !!(Features & VIRTIO_NET_F_STATUS));
>  
> -  Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | VIRTIO_F_VERSION_1;
> +  Features &= VIRTIO_NET_F_MAC | VIRTIO_NET_F_STATUS | VIRTIO_F_VERSION_1 |
> +              VIRTIO_F_IOMMU_PLATFORM;
>  
>    //
>    // In virtio-1.0, feature negotiation is expected to complete before queue
> diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.c b/OvmfPkg/VirtioRngDxe/VirtioRng.c
> index b19d90901430..81d8c7facc10 100644
> --- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
> +++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
> @@ -273,7 +273,7 @@ VirtioRngInit (
>      goto Failed;
>    }
>  
> -  Features &= VIRTIO_F_VERSION_1;
> +  Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM;
>  
>    //
>    // In virtio-1.0, feature negotiation is expected to complete before queue
> diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> index 65e9bda0827a..286b005c994c 100644
> --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> @@ -903,7 +903,8 @@ VirtioScsiInit (
>      goto Failed;
>    }
>  
> -  Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1;
> +  Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1 |
> +              VIRTIO_F_IOMMU_PLATFORM;
>  
>    //
>    // In virtio-1.0, feature negotiation is expected to complete before queue
> 



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

* Re: [PATCH v2 18/23] OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors
  2017-08-14 11:36 ` [PATCH v2 18/23] OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors Brijesh Singh
@ 2017-08-21 19:08   ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-21 19:08 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

After all, I've taken a look here as well. I'm not going to point out
all the earlier remarks (please do address them here anyway, because
they certainly apply), I'll just say what I feel is specific to this patch:

On 08/14/17 13:36, Brijesh Singh wrote:
> The VirtioScsiPassThru(), programs the vring descriptor using the host
> addresses pointed-by virtio-scsi request, response and memory that is
> referenced inside the request and response header.
> 
> The patch uses newly introduced VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer()
> function to map system memory to device address and programs the vring
> descriptors with device addresses.
> 
> 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/VirtioScsiDxe/VirtioScsi.h |   1 +
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.c | 148 +++++++++++++++++---
>  2 files changed, 133 insertions(+), 16 deletions(-)
> 
> diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h b/OvmfPkg/VirtioScsiDxe/VirtioScsi.h
> index 6d00567e8cb8..bb1c5c70ef74 100644
> --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.h
> +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.h
> @@ -60,6 +60,7 @@ typedef struct {
>    VRING                           Ring;           // VirtioRingInit      2
>    EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;       // VirtioScsiInit      1
>    EFI_EXT_SCSI_PASS_THRU_MODE     PassThruMode;   // VirtioScsiInit      1
> +  VOID                            *RingBufMapping;// VirtioScsiInit      1
>  } VSCSI_DEV;
>  
>  #define VIRTIO_SCSI_FROM_PASS_THRU(PassThruPointer) \
> diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> index a983b3df7b9c..65e9bda0827a 100644
> --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
> @@ -409,8 +409,13 @@ VirtioScsiPassThru (
>    UINT16                    TargetValue;
>    EFI_STATUS                Status;
>    volatile VIRTIO_SCSI_REQ  Request;
> -  volatile VIRTIO_SCSI_RESP Response;
> +  VIRTIO_SCSI_RESP          *Response;

(1) Please don't drop the volatile qualification. If you want to turn it
into a pointer, that might be OK, but the target of the pointer should
remain volatile.

>    DESC_INDICES              Indices;
> +  VOID                      *RequestMapping;
> +  VOID                      *ResponseMapping;
> +  VOID                      *InDataMapping;
> +  VOID                      *OutDataMapping;
> +  EFI_PHYSICAL_ADDRESS      DeviceAddress;
>  
>    ZeroMem ((VOID*) &Request, sizeof (Request));
>    ZeroMem ((VOID*) &Response, sizeof (Response));

(2) Hmm, this ZeroMem() now nulls the pointer. Probably not what you
intended.

> @@ -418,9 +423,41 @@ VirtioScsiPassThru (
>    Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
>    CopyMem (&TargetValue, Target, sizeof TargetValue);
>  
> +  Response = NULL;
> +  ResponseMapping = NULL;
> +  RequestMapping = NULL;
> +  InDataMapping = NULL;
> +  OutDataMapping = NULL;
> +
> +  //
> +  // Response header is bi-direction (we preset with host status and expect the
> +  // device to update it). Allocate a response buffer which can be mapped to
> +  // access equally by both processor and device.
> +  //

Good point!

(3) In that case however, please do the same for "HostStatus" in the
VirtioBlkDxe driver as well. We also pre-set that value for ourselves.

> +  Status = Dev->VirtIo->AllocateSharedPages (
> +                          Dev->VirtIo,
> +                          EFI_SIZE_TO_PAGES (sizeof *Response),
> +                          (VOID *) &Response
> +                          );

(4) In general I abhor this kind of pointer type punning (it is
undefined behavior in standard C), but it is so pervasive in edk2, when
looking up protocol interfaces, that I guess we can live with it.

However, the type that we cast &Response to should be (VOID **), not
(VOID *). The compiler didn't complain to you because (VOID *) silently
converts to and from other object pointer types -- assuming same const /
volatile qualification.

The cleanest solution for this would be, IMO:

  volatile VIRTIO_SCSI_RESP *Response;
  VOID                      *ResponseBuffer;

  Status = Dev->VirtIo->AllocateSharedPages (
                          Dev->VirtIo,
                          EFI_SIZE_TO_PAGES (sizeof *Response),
                          &ResponseBuffer
                          );
  ...
  Response = ResponseBuffer;

... I think this is all I wanted to say about this patch for now, on top
of my earlier comments for virtio-rng and virtio-blk, which also apply here.

Thanks,
Laszlo

> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = VirtioMapAllBytesInSharedBuffer (
> +             Dev->VirtIo,
> +             VirtioOperationBusMasterCommonBuffer,
> +             (VOID *) Response,
> +             sizeof (*Response),
> +             &DeviceAddress,
> +             &ResponseMapping
> +             );
> +  if (EFI_ERROR (Status)) {
> +    goto Free_Response_Buffer;
> +  }
> +
>    Status = PopulateRequest (Dev, TargetValue, Lun, Packet, &Request);
>    if (EFI_ERROR (Status)) {
> -    return Status;
> +    goto Unmap_Response_Buffer;
>    }
>  
>    VirtioPrepare (&Dev->Ring, &Indices);
> @@ -428,7 +465,7 @@ VirtioScsiPassThru (
>    //
>    // preset a host status for ourselves that we do not accept as success
>    //
> -  Response.Response = VIRTIO_SCSI_S_FAILURE;
> +  Response->Response = VIRTIO_SCSI_S_FAILURE;
>  
>    //
>    // ensured by VirtioScsiInit() -- this predicate, in combination with the
> @@ -437,23 +474,51 @@ VirtioScsiPassThru (
>    ASSERT (Dev->Ring.QueueSize >= 4);
>  
>    //
> +  // Map the scsi-blk request header HostAddress to DeviceAddress
> +  //
> +  Status = VirtioMapAllBytesInSharedBuffer (
> +             Dev->VirtIo,
> +             VirtioOperationBusMasterRead,
> +             (VOID *) &Request,
> +             sizeof Request,
> +             &DeviceAddress,
> +             &RequestMapping);
> +  if (EFI_ERROR (Status)) {
> +    goto Unmap_Response_Buffer;
> +  }
> +
> +  //
>    // enqueue Request
>    //
> -  VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,
> +  VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress, sizeof Request,
>      VRING_DESC_F_NEXT, &Indices);
>  
>    //
>    // enqueue "dataout" if any
>    //
>    if (Packet->OutTransferLength > 0) {
> -    VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->OutDataBuffer,
> +    //
> +    // Map the buffer address to a device address
> +    //
> +    Status = VirtioMapAllBytesInSharedBuffer (
> +               Dev->VirtIo,
> +               VirtioOperationBusMasterRead,
> +               Packet->OutDataBuffer,
> +               Packet->OutTransferLength,
> +               &DeviceAddress,
> +               &OutDataMapping
> +               );
> +    if (EFI_ERROR (Status)) {
> +      goto Unmap_Request_Buffer;
> +    }
> +    VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress,
>        Packet->OutTransferLength, VRING_DESC_F_NEXT, &Indices);
>    }
>  
>    //
>    // enqueue Response, to be written by the host
>    //
> -  VirtioAppendDesc (&Dev->Ring, (UINTN) &Response, sizeof Response,
> +  VirtioAppendDesc (&Dev->Ring, (UINTN) Response, sizeof *Response,
>      VRING_DESC_F_WRITE | (Packet->InTransferLength > 0 ?
>                            VRING_DESC_F_NEXT : 0),
>      &Indices);
> @@ -462,7 +527,22 @@ VirtioScsiPassThru (
>    // enqueue "datain" if any, to be written by the host
>    //
>    if (Packet->InTransferLength > 0) {
> -    VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->InDataBuffer,
> +    //
> +    // Map the buffer address to a device address
> +    //
> +    Status = VirtioMapAllBytesInSharedBuffer (
> +               Dev->VirtIo,
> +               VirtioOperationBusMasterWrite,
> +               Packet->InDataBuffer,
> +               Packet->InTransferLength,
> +               &DeviceAddress,
> +               &InDataMapping
> +               );
> +    if (EFI_ERROR (Status)) {
> +      goto Unmap_Out_Buffer;
> +    }
> +
> +    VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress,
>        Packet->InTransferLength, VRING_DESC_F_WRITE, &Indices);
>    }
>  
> @@ -480,7 +560,29 @@ VirtioScsiPassThru (
>      return EFI_DEVICE_ERROR;
>    }
>  
> -  return ParseResponse (Packet, &Response);
> +  Status = ParseResponse (Packet, Response);
> +
> +  if (Packet->InTransferLength > 0) {
> +    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, InDataMapping);
> +  }
> +
> +Unmap_Out_Buffer:
> +  if (Packet->OutTransferLength > 0) {
> +    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, OutDataMapping);
> +  }
> +
> +Unmap_Request_Buffer:
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping);
> +Unmap_Response_Buffer:
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, ResponseMapping);
> +Free_Response_Buffer:
> +  Dev->VirtIo->FreeSharedPages (
> +                 Dev->VirtIo,
> +                 EFI_SIZE_TO_PAGES (sizeof *Response),
> +                 (VOID *) Response
> +                 );
> +
> +  return Status;
>  }
>  
>  
> @@ -707,7 +809,7 @@ VirtioScsiInit (
>  {
>    UINT8      NextDevStat;
>    EFI_STATUS Status;
> -
> +  UINT64     RingBaseShift;
>    UINT64     Features;
>    UINT16     MaxChannel; // for validation only
>    UINT32     NumQueues;  // for validation only
> @@ -838,18 +940,24 @@ VirtioScsiInit (
>      goto Failed;
>    }
>  
> +  Status = VirtioRingMap (Dev->VirtIo, &Dev->Ring, &RingBaseShift,
> +             &Dev->RingBufMapping);
> +  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.
>    //
>    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;
>    }
>  
>    //
> @@ -857,7 +965,7 @@ VirtioScsiInit (
>    //
>    Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);
>    if (EFI_ERROR (Status)) {
> -    goto ReleaseQueue;
> +    goto UnmapQueue;
>    }
>  
>    //
> @@ -867,7 +975,7 @@ VirtioScsiInit (
>      Features &= ~(UINT64)VIRTIO_F_VERSION_1;
>      Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
>      if (EFI_ERROR (Status)) {
> -      goto ReleaseQueue;
> +      goto UnmapQueue;
>      }
>    }
>  
> @@ -877,11 +985,11 @@ VirtioScsiInit (
>    //
>    Status = VIRTIO_CFG_WRITE (Dev, CdbSize, VIRTIO_SCSI_CDB_SIZE);
>    if (EFI_ERROR (Status)) {
> -    goto ReleaseQueue;
> +    goto UnmapQueue;
>    }
>    Status = VIRTIO_CFG_WRITE (Dev, SenseSize, VIRTIO_SCSI_SENSE_SIZE);
>    if (EFI_ERROR (Status)) {
> -    goto ReleaseQueue;
> +    goto UnmapQueue;
>    }
>  
>    //
> @@ -890,7 +998,7 @@ VirtioScsiInit (
>    NextDevStat |= VSTAT_DRIVER_OK;
>    Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
>    if (EFI_ERROR (Status)) {
> -    goto ReleaseQueue;
> +    goto UnmapQueue;
>    }
>  
>    //
> @@ -926,6 +1034,8 @@ VirtioScsiInit (
>  
>    return EFI_SUCCESS;
>  
> +UnmapQueue:
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingBufMapping);
>  ReleaseQueue:
>    VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
>  
> @@ -995,6 +1105,12 @@ VirtioScsiExitBoot (
>    //
>    Dev = Context;
>    Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
> +
> +  //
> +  // If Ring buffer mapping exist then unmap it so that hypervisor can
> +  // not get readable data after device reset.
> +  //
> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingBufMapping);
>  }
>  
>  
> 



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

* Re: [PATCH v2 17/23] OvmfPkg/VirtioBlkDxe: map host address to device address
  2017-08-21 15:24   ` Laszlo Ersek
@ 2017-08-22  1:42     ` Brijesh Singh
       [not found]       ` <1387174d-0040-0072-5e36-c133fd7ec934@redhat.com>
  0 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-22  1:42 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Tom Lendacky, Ard Biesheuvel



On 8/21/17 10:24 AM, Laszlo Ersek wrote:

[Snip]...

> (25) I think you intended to add the empty line above the "ReleaseQueue"
> label, not below it.
>
>>    VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
>>  
>>  Failed:
> (26) You forgot to call UnmapSharedBuffer() in the VirtioBlkUninit()
> function. Each ring must be unmapped in three places:
>
> - in the device init function, if there is an error and we're past
> mapping the ring,
> - in the device uninit function,
> - in the ExitBootServices notify function.

I will go through each of your comments and try to address them in v3
but I would like to understand this code flow a bit more. When we invoke
PciIo->UnmapBuffer(...,Map) [1], it searches for Mapping in its internal
list and if found then unmaps the buffer. So idea is each Map() should
have exactly one Unmap().

So the question: is it possible that we may get called from both
ExitBootService notify and device uninit functions ? If so, then we will
have issue because now we will end up calling Unmap() twice (once from
ExitBootServices then device uninit). In my debug statement I saw the
call to ExitBootServices but was never able to trigger code path where
the device uninit is called. I am wondering if you know any method to
trigger the device uninit code flow so that I can verify both the path.

[1]
https://github.com/tianocore/edk2/blob/master/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c#L316


>> @@ -885,6 +974,12 @@ VirtioBlkExitBoot (
>>    //
>>    Dev = Context;
>>    Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
>> +
>> +  //
>> +  // Unmap the ring buffer so that hypervisor can not get a readable data
>> +  // after device is reset.
>> +  //
>> +  Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMapping);
>>  }
>>  
>>  /**
>>
> I think I'm skipping the rest of the series for now (except the last
> patch, I have comments for that).
>
> Please rework the rest of the transport-independent virtio drivers (scsi
> and net) based on my comments for this (blk) and the previous (rng) patch.
>
> Thanks!
> Laszlo



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

* Re: [PATCH v2 17/23] OvmfPkg/VirtioBlkDxe: map host address to device address
       [not found]       ` <1387174d-0040-0072-5e36-c133fd7ec934@redhat.com>
@ 2017-08-22 14:29         ` Brijesh Singh
  2017-08-22 15:53           ` Laszlo Ersek
  0 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-22 14:29 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Tom Lendacky, Ard Biesheuvel

Hi Laszlo,

On 08/22/2017 06:14 AM, Laszlo Ersek wrote:

> 
>> So the question: is it possible that we may get called from both
>> ExitBootService notify and device uninit functions ?
> 
> This is a valid problem statement / question, and I verified your code
> with regard to it, in the patches that I reviewed.
> 
> Let's use VirtioBlkDxe as an example:
> 
> (1) The VirtioBlkDriverBindingStart() function calls VirtioBlkInit().
> 
> (2) If, and only if, VirtioBlkInit() returns with success, then the ring
> has been mapped.
> 
> (3) If, and only if, VirtioBlkInit() has returned with success, then we
> create the Dev->ExitBoot event (EVT_SIGNAL_EXIT_BOOT_SERVICES) in
> VirtioBlkDriverBindingStart(), the notification function being
> VirtioBlkExitBoot(). The task priority level at which the notification
> function will be enqueued is TPL_CALLBACK (just above TPL_APPLICATION).
> 
> (4) If the protocol interface installation fails in
> VirtioBlkDriverBindingStart(), then the Dev->ExitBoot is closed first
> (which unregisters the notification function), and VirtioBlkUninit() is
> called second (more on this below).
> 
> (5) Side topic:
> 
> According to "Table 23. TPL Restrictions" in the UEFI spec v2.7,
> ExitBootServices() may only be called at TPL_APPLICATION. This means
> that the notification function will actually be executed before
> ExitBootServices() returns.
> 
> I'm only mentioning this because in some cases the installation of a
> protocol interface has to be done very carefully. Some other module may
> have set up a protocol notify e.g. at TPL_CALLBACK. If the driver
> installs the protocol interface at TPL_APPLICATION (the default), the
> protocol notify in the other driver may be invoked immediately, and that
> driver might call back into the first driver, in order to use the
> just-installed protocol. This requires that the first driver either
> raise the TPL temporarily (so that the protocol installation not result
> in an immediate notification in the other driver), or make sure that the
> protocol being installed be immediately usable.
> 
> With regard to ExitBootServices() however, this is irrelevant. Any
> protocol install notification function invoked like above runs at
> TPL_CALLBACK, or at a higher task priority level. Therefore it *must
> not* call ExitBootServices().
> 
> Which, ultimately, guarantees that our BlockIo installation in
> VirtioBlkDriverBindingStart() will never result in a direct callback to
> VirtioBlkExitBoot().
> 
> (6) Now consider VirtioBlkUninit(). With the feature in place,
> VirtioBlkUninit() both unmaps and frees the ring. It is called from two
> contexts: (a) when we get "far enough" in VirtioBlkDriverBindingStart()
> but then fail ultimately (see point (4), and the label "UninitDev"), and
> (b) when the binding succeeds just fine, and then later the driver is
> asked to unbind (disconnect from) the device -- in
> VirtioBlkDriverBindingStop().
> 
> In VirtioBlkDriverBindingStop(), we close Dev->ExitBoot, before we call
> VirtioBlkUninit() and unmap the vring. Closing the event deregisters the
> notification function, and also clears any invocations for the notify
> function originally enqueued via this event.
> 
> (FWIW, I don't see how any such invocations could be pending here,
> because that would imply that some agent called *both*
> ExitBootServices() and our VirtioBlkDriverBindingStop() at a TPL higher
> than TPL_APPLICATION -- it would be totally invalid. Nonetheless, this
> is how closing an event works.)
> 
> 
> The upshot is that three scenarios are possible:
> 
> - VirtioBlkDriverBindingStart() fails. On return from that function, the
> vring is not mapped, and the exit-boot-services callback does not exit.
> 
> - VirtioBlkDriverBindingStart() succeeds. On return from the function,
> the vring is mapped, and the exit-boot-services callback is live. Then,
> the driver is requested to unbind the device
> (VirtioBlkDriverBindingStop()). The callback is removed, and the vring
> is unmapped in VirtioBlkUninit(). If ExitBootServices() is called
> sometime after this, then the callback is not there any longer.
> 
> - VirtioBlkDriverBindingStart() succeeds. On return from the function,
> the vring is mapped, and the exit-boot-services callback is live. Then,
> ExitBootServices() is called. VirtioBlkExitBoot() runs, resetting the
> virtio device, and unmapping its vring. VirtioBlkDriverBindingStop() may
> never be called after this point, because boot services will have been
> exited after all the callbacks run and ExitBootServices() returns.
> 
> 
> In general ExitBootServices() notify functions behave very differently
> from BindingStop() functions. The latter tear down all the structures
> nicely, in reverse order of construction, freeing memory, uninitializing
> devices, and so on. In comparison, the former *must not* free memory,
> only abort in-flight transfers and de-configure devices surgically,
> "in-place", so that they forget previous system memory references. These
> two are exclusive.
> 
> When people first write UEFI drivers that follow the UEFI driver model,
> they are tempted to call (or imitate) the full BindingStop() logic in
> the ExitBootServices() notify function. That's wrong. Those contexts are
> different with regard to system memory ownership. In BindingStop(), the
> memory is owned by the driver. In the ExitBootServices() callback, the
> memory is already owned by the OS (sort of), it is only on "loan" to the
> driver -- after which a call to BindingStop() is impossible.
> 
> 
> Therefore the answer to your question is, "no, that is not possible".
> 
>> If so, then we will
>> have issue because now we will end up calling Unmap() twice (once from
>> ExitBootServices then device uninit). In my debug statement I saw the
>> call to ExitBootServices but was never able to trigger code path where
>> the device uninit is called.
> 
> If you had been able to trigger such a sequence (exit-boot-services
> callback followed by BindingStop), that would imply a huge problem in edk2.
> 
>> I am wondering if you know any method to
>> trigger the device uninit code flow so that I can verify both the path.
> 
> Testing repeated BindingStart / BindingStop calls is indeed a good idea
> -- sort of necessary -- for any UEFI driver that follows the UEFI driver
> model. It's easiest to do with the CONNECT, DISCONNECT and RECONNECT
> commands in the UEFI shell. (Please see their documentation in the UEFI
> shell spec.)
> 
> In order to find suitable handles for testing (driver and device
> handles), I recommend the DEVICES / DRIVERS / DEVTREE / DH commands.
> Personally I find DH the most useful, in particular with the "-d -v" and
> "-p" options.
> 
> For example, "dh -d -v -p BlockIo" should give you a detailed list of
> handles with BlockIo protocol interfaces on them, and the output should
> help you find the ones installed by VirtioBlkDxe.
> 
> Sorry about the length of this email (I realize a shorter email might
> have been more to the point). I hope it helps a little.
> 


Thanks for detail explanation, I was trying driver unload and reload from
the UEFI shell but that did not trigger the BindStop hence I was not sure
how it all works. But your explanation makes sense. I will try connect and
disconnect to trigger the code path and make sure that all logical code path
have been tested before we commit the patch :)

-Brijesh



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

* Re: [PATCH v2 16/23] OvmfPkg/VirtioRngDxe: map host address to device address
  2017-08-21 14:05   ` Laszlo Ersek
@ 2017-08-22 15:44     ` Brijesh Singh
  2017-08-22 16:28       ` Laszlo Ersek
  0 siblings, 1 reply; 51+ messages in thread
From: Brijesh Singh @ 2017-08-22 15:44 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Tom Lendacky, Ard Biesheuvel



On 08/21/2017 09:05 AM, Laszlo Ersek wrote:

[...]

> 
>>     for (Index = 0; Index < RNGValueLength; Index++) {
>>       RNGValue[Index] = Buffer[Index];
>>     }
>>     Status = EFI_SUCCESS;
>>   
>> +  //
>> +  // Buffer is already Unmaped(), goto free it.
>> +  //
>> +  goto FreeBuffer;
> 
> (6) We restrict "goto" statements to error handling:
> 
> https://edk2-docs.gitbooks.io/edk-ii-c-coding-standards-specification/content/5_source_files/57_c_programming.html
> 
>> 5.7.3.8 Goto Statements should not be used (in general)
>> [...]
>> It is common to use goto for error handling and thus, exiting a
>> routine in an error case is the only legal use of a goto. [...]
> 
> So please open-code the FreePool() call and the "return" statement here.
> 

I was wondering if something like this is acceptable ? Actually since we need to handle
the Unmap due to error from VirtioFlush hence I was trying to minimize the adding
new state variables or additional checks inside the for loop.

@@ -178,17 +194,34 @@ VirtioRngGetRNG (
      if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=
          EFI_SUCCESS) {
        Status = EFI_DEVICE_ERROR;
-      goto FreeBuffer;
+      goto UnmapBuffer;
      }
      ASSERT (Len > 0);
      ASSERT (Len <= BufferSize);
    }
  
+  //
+  // Unmap the device buffer before accessing it.
+  //
+  Status = Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
+  if (EFI_ERROR (Status)) {
+    goto FreeBuffer;
+  }
+
    for (Index = 0; Index < RNGValueLength; Index++) {
      RNGValue[Index] = Buffer[Index];
    }
    Status = EFI_SUCCESS;
  
+UnmapBuffer:
+  //
+  // If we are reached here due to the error then unmap the buffer otherwise
+  // the buffer is already unmapped after VirtioFlush().
+  //
+  if (EFI_ERROR (Status)) {
+    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
+  }
+
  FreeBuffer:
    FreePool ((VOID *)Buffer);
    return Status;



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

* Re: [PATCH v2 17/23] OvmfPkg/VirtioBlkDxe: map host address to device address
  2017-08-22 14:29         ` Brijesh Singh
@ 2017-08-22 15:53           ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-22 15:53 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/22/17 16:29, Brijesh Singh wrote:

> Thanks for detail explanation, I was trying driver unload and reload
> from the UEFI shell but that did not trigger the BindStop hence I was
> not sure how it all works.

*Unload* is a different thing. Clearly a driver can only be unloaded
after all its currently bound devices are unbound, but there is no
dependency in the other direction -- a UEFI_DRIVER module can perfectly
well unbind devices *without* being unloadable.

An edk2 driver module that is unloadable specifies the UNLOAD_IMAGE
define in its INF file. Pretty few drivers do this. (None of the virtio
drivers.)

The "Driver Writer’s Guide for UEFI 2.3.1" writes about unloading in
"7.6 Adding the Unload Feature" (and possibly elsewhere).

> But your explanation makes sense. I will try connect and disconnect
> to trigger the code path and make sure that all logical code path 
> have been tested before we commit the patch :)

Sounds good, thanks!

Laszlo


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

* Re: [PATCH v2 16/23] OvmfPkg/VirtioRngDxe: map host address to device address
  2017-08-22 15:44     ` Brijesh Singh
@ 2017-08-22 16:28       ` Laszlo Ersek
  0 siblings, 0 replies; 51+ messages in thread
From: Laszlo Ersek @ 2017-08-22 16:28 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/22/17 17:44, Brijesh Singh wrote:
>
>
> On 08/21/2017 09:05 AM, Laszlo Ersek wrote:
>
> [...]
>
>>
>>>     for (Index = 0; Index < RNGValueLength; Index++) {
>>>       RNGValue[Index] = Buffer[Index];
>>>     }
>>>     Status = EFI_SUCCESS;
>>>   +  //
>>> +  // Buffer is already Unmaped(), goto free it.
>>> +  //
>>> +  goto FreeBuffer;
>>
>> (6) We restrict "goto" statements to error handling:
>>
>> https://edk2-docs.gitbooks.io/edk-ii-c-coding-standards-specification/content/5_source_files/57_c_programming.html
>>
>>
>>> 5.7.3.8 Goto Statements should not be used (in general)
>>> [...]
>>> It is common to use goto for error handling and thus, exiting a
>>> routine in an error case is the only legal use of a goto. [...]
>>
>> So please open-code the FreePool() call and the "return" statement
>> here.
>>
>
> I was wondering if something like this is acceptable ? Actually since
> we need to handle the Unmap due to error from VirtioFlush hence I was
> trying to minimize the adding new state variables or additional checks
> inside the for loop.
>
> @@ -178,17 +194,34 @@ VirtioRngGetRNG (
>      if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=
>          EFI_SUCCESS) {
>        Status = EFI_DEVICE_ERROR;
> -      goto FreeBuffer;
> +      goto UnmapBuffer;
>      }
>      ASSERT (Len > 0);
>      ASSERT (Len <= BufferSize);
>    }
>
> +  //
> +  // Unmap the device buffer before accessing it.
> +  //
> +  Status = Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
> +  if (EFI_ERROR (Status)) {
> +    goto FreeBuffer;
> +  }
> +
>    for (Index = 0; Index < RNGValueLength; Index++) {
>      RNGValue[Index] = Buffer[Index];
>    }
>    Status = EFI_SUCCESS;
>
> +UnmapBuffer:
> +  //
> +  // If we are reached here due to the error then unmap the buffer
> otherwise
> +  // the buffer is already unmapped after VirtioFlush().
> +  //
> +  if (EFI_ERROR (Status)) {
> +    Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Mapping);
> +  }
> +
>  FreeBuffer:
>    FreePool ((VOID *)Buffer);
>    return Status;
>

This is perfectly fine, as long as it doesn't get overly complex. It
keeps goto's limited to cascading error handling, only part of the error
handling becomes optional if the ownership of Mapping has been
transferred before.

In functions where you have a simple mapping, this doesn't look
difficult, but more care might be required for functions where you have
several mappings (some of which could be optional, dependent on input
parameters or other conditions). IMO, the pattern should work
nonetheless:

>   if (InputCondition1) {
>     Status = Map (&Mapping1);
>     if (EFI_ERROR (Status)) {
>       goto FreeBuffer;
>     }
>   }
>
>   if (InputCondition2) {
>     Status = Map (&Mapping2);
>     if (EFI_ERROR (Status)) {
>       goto Unmap1;
>     }
>   }
>
>   if (InputCondition3) {
>     Status = Map (&Mapping3);
>     if (EFI_ERROR (Status)) {
>       goto Unmap2;
>     }
>   }
>
>   Status = DoSomethingElse ();
>   if (EFI_ERROR (Status)) {
>     goto Unmap3;
>   }
>
>   //
>   // Now unmap stuff for processing results.
>   //
>
>   if (InputCondition3) {
>     Status = Unmap (Mapping3);
>     if (EFI_ERROR (Status)) {
>       goto Unmap2;
>     }
>   }
>
>   if (InputCondition2) {
>     Status = Unmap (Mapping2);
>     if (EFI_ERROR (Status)) {
>       goto Unmap1;
>     }
>   }
>
>   if (InputCondition1) {
>     Status = Unmap (Mapping1);
>     if (EFI_ERROR (Status)) {
>       goto FreeBuffer;
>     }
>   }
>
>   //
>   // Process results.
>   //
>   ...
>
>   Status = EFI_SUCCESS;
>
> Unmap3:
>   if (EFI_ERROR (Status) && InputCondition3) {
>     Unmap (Mapping3);
>   }
>
> Unmap2:
>   if (EFI_ERROR (Status) && InputCondition2) {
>     Unmap (Mapping2);
>   }
>
> Unmap1:
>   if (EFI_ERROR (Status) && InputCondition1) {
>     Unmap (Mapping1);
>   }
>
> FreeBuffer:
>   //
>   // some rollback action that has to be performed unconditionally on
>   // exit
>   //
>   ...
>
>   return Status;

This needs no additional state variables. The depth of the successful
map/unmap sequence is captured with the goto statements and the labels.
And, on the exit path, unmapping of each mapping depends on two
conditions: the exit path being taken due to success or error, and on
the given mapping being relevant in the first place.

Thanks,
Laszlo


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

end of thread, other threads:[~2017-08-22 16:25 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-14 11:36 [PATCH v2 00/21] OvmfPkg/Virtio: introduce IOMMU-like member functions Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 01/23] OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute Brijesh Singh
2017-08-16  0:34   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 02/23] OvmfPkg/Virtio10Dxe: " Brijesh Singh
2017-08-16  0:36   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 03/23] OvmfPkg/VirtioPciDeviceDxe: add missing IN and OUT decoration Brijesh Singh
2017-08-16  0:36   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 04/23] OvmfPkg/VirtioMmioDeviceLib: " Brijesh Singh
2017-08-16  0:37   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 05/23] OvmfPkg/Virtio: fix comment style Brijesh Singh
2017-08-16  0:41   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 06/23] OvmfPkg/Virtio: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL Brijesh Singh
2017-08-16 14:37   ` Laszlo Ersek
2017-08-16 15:58     ` Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 07/23] OvmfPkg/Virtio10Dxe: implement IOMMU-like member functions Brijesh Singh
2017-08-16 14:59   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 08/23] OvmfPkg/VirtioPciDeviceDxe: " Brijesh Singh
2017-08-16 15:32   ` Laszlo Ersek
2017-08-16 15:53     ` Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 09/23] OvmfPkg/VirtioMmioDeviceLib: " Brijesh Singh
2017-08-16 15:58   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 10/23] OvmfPkg/VirtioLib: add VirtioMapAllBytesInSharedBuffer() helper function Brijesh Singh
2017-08-16 16:47   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 11/23] OvmfPkg/VirtioLib: take VirtIo instance in VirtioRingInit/VirtioRingUninit Brijesh Singh
2017-08-16 16:53   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 12/23] OvmfPkg/VirtioLib: add functions to map/unmap VRING Brijesh Singh
2017-08-16 20:56   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 13/23] OvmfPkg/Virtio: take RingBaseShift in VirtioSetQueueAddress() Brijesh Singh
2017-08-16 21:43   ` Laszlo Ersek
2017-08-16 21:51     ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 14/23] OvmfPkg/Virtio10Dxe: add the RingBaseShift offset Brijesh Singh
2017-08-16 21:57   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 15/23] OvmfPkg/VirtioLib: alloc vring buffer with AllocateSharedPages() Brijesh Singh
2017-08-16 22:18   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 16/23] OvmfPkg/VirtioRngDxe: map host address to device address Brijesh Singh
2017-08-21 14:05   ` Laszlo Ersek
2017-08-22 15:44     ` Brijesh Singh
2017-08-22 16:28       ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 17/23] OvmfPkg/VirtioBlkDxe: " Brijesh Singh
2017-08-21 15:24   ` Laszlo Ersek
2017-08-22  1:42     ` Brijesh Singh
     [not found]       ` <1387174d-0040-0072-5e36-c133fd7ec934@redhat.com>
2017-08-22 14:29         ` Brijesh Singh
2017-08-22 15:53           ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 18/23] OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors Brijesh Singh
2017-08-21 19:08   ` Laszlo Ersek
2017-08-14 11:36 ` [PATCH v2 19/23] OvmfPkg/VirtioNetDxe: alloc Tx and Rx rings using AllocateSharedPage() Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 20/23] OvmfPkg/VirtioNetDxe: alloc RxBuf using AllocateSharedPages() Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 21/23] OvmfPkg/VirtioNetDxe: dynamically alloc transmit header Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 22/23] OvmfPkg/VirtioNetDxe: map transmit buffer host address to device address Brijesh Singh
2017-08-14 11:36 ` [PATCH v2 23/23] OvmfPkg/Virtio: define VIRITO_F_IOMMU_PLATFORM feature bit Brijesh Singh
2017-08-21 15:40   ` Laszlo Ersek

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