public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
@ 2017-08-07 11:58 Brijesh Singh
  2017-08-07 11:58 ` [PATCH v1 01/14] OvmfPkg/Virtio: Introduce new member functions in VIRTIO_DEVICE_PROTOCOL Brijesh Singh
                   ` (15 more replies)
  0 siblings, 16 replies; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 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 - 3:
 Defines and implements new member functions to map a system physical address
 to device address. The patch implements Laszlo's suggestion [1].

Patch 4 - 7:
 Allocates the vring buffer using newly added member functions and provides
 some helper functions.

Patch 8:
 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

Patch 9:
 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 \

Patch 10 - 13:
 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=

Patch 14:
 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

 And succesfully ran RngTest.efi from SecurityPkg/Application

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

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>

Brijesh Singh (14):
  OvmfPkg/Virtio: Introduce new member functions in
    VIRTIO_DEVICE_PROTOCOL
  OvmfPkg/Virtio10Dxe: Implement new member functions
  OvmfPkg/VirtioPciDeviceDxe: Implement new member functions
  OvmfPkg/VirtioLib: Add SharedBuffer helper functions
  OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit()
  OvmfPkg/VirtioLib: Add functions to map/unmap VRING
  OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer
  OvmfPkg/VirtioBlkDxe: Use DeviceAddresses in vring descriptors
  OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors
  OvmfPkg/VirtioNetDxe: Allocate Tx and Rx ring using
    AllocateSharedPage()
  OvmfPkg/VirtioNetDxe: Allocate RxBuf using AllocateSharedPages()
  OvmfPkg/VirtioNetDxe: Dynamically allocate transmit header
  OvmfPkg/VirtioNetDxe: Use DeviceAddress in transmit vring descriptors
  OvmfPkg/VirtioRngDxe: Use DeviceAddresses in vring descriptors

 OvmfPkg/Include/Library/VirtioLib.h             | 198 ++++++++++++-
 OvmfPkg/Include/Protocol/VirtioDevice.h         | 121 ++++++++
 OvmfPkg/VirtioBlkDxe/VirtioBlk.h                |   1 +
 OvmfPkg/VirtioNetDxe/VirtioNet.h                |  25 +-
 OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h    |  34 +++
 OvmfPkg/VirtioRngDxe/VirtioRng.h                |   1 +
 OvmfPkg/VirtioScsiDxe/VirtioScsi.h              |   1 +
 OvmfPkg/Library/VirtioLib/VirtioLib.c           | 296 +++++++++++++++++++-
 OvmfPkg/Virtio10Dxe/Virtio10.c                  | 114 +++++++-
 OvmfPkg/VirtioBlkDxe/VirtioBlk.c                | 104 ++++++-
 OvmfPkg/VirtioGpuDxe/Commands.c                 |   7 +-
 OvmfPkg/VirtioNetDxe/Events.c                   |  24 ++
 OvmfPkg/VirtioNetDxe/SnpGetStatus.c             |  19 +-
 OvmfPkg/VirtioNetDxe/SnpInitialize.c            | 102 +++++--
 OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c         | 119 +++++++-
 OvmfPkg/VirtioNetDxe/SnpShutdown.c              |  16 +-
 OvmfPkg/VirtioNetDxe/SnpTransmit.c              |  22 +-
 OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c    |   7 +-
 OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c |  66 +++++
 OvmfPkg/VirtioRngDxe/VirtioRng.c                |  54 +++-
 OvmfPkg/VirtioScsiDxe/VirtioScsi.c              | 121 +++++++-
 21 files changed, 1378 insertions(+), 74 deletions(-)

-- 
2.7.4



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

* [PATCH v1 01/14] OvmfPkg/Virtio: Introduce new member functions in VIRTIO_DEVICE_PROTOCOL
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-09 14:27   ` Laszlo Ersek
  2017-08-07 11:58 ` [PATCH v1 02/14] OvmfPkg/Virtio10Dxe: Implement new member functions Brijesh Singh
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 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 | 121 ++++++++++++++++++++
 1 file changed, 121 insertions(+)

diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
index 910a4866e7ac..ea5272165389 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,26 @@
 
 typedef struct _VIRTIO_DEVICE_PROTOCOL  VIRTIO_DEVICE_PROTOCOL;
 
+//
+// VIRTIO Operation for Map
+//
+typedef enum {
+  //
+  // A read operation from system memory by a bus master
+  //
+  EfiVirtIoOperationBusMasterRead,
+  //
+  // A write operation from system memory by a bus master
+  //
+  EfiVirtIoOperationBusMasterWrite,
+  //
+  // Provides both read and write access to system memory by both the
+  // processor and a bus master
+  //
+  EfiVirtIoOperationBusMasterCommonBuffer,
+  EfiVirtIoOperationMaximum
+} VIRTIO_MAP_OPERATION;
+
 /**
 
   Read a word from the device-specific I/O region of the Virtio Header.
@@ -319,6 +340,100 @@ EFI_STATUS
   IN UINT8                   DeviceStatus
   );
 
+/**
+
+  Allocates pages that are suitable for sharing between guest and hypervisor.
+
+  @param  This                  The protocol instance pointer.
+  @param  Pages                 The number of pages to allocate.
+  @param  HostAddress           A pointer to store the base system memory
+                                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 SharedAllocateBuffer().
+
+  @param  This           The protocol instance pointer.
+  @param  Pages          The number of pages to free.
+  @param  HostAddress    The base system memory address of the allocated range.
+
+**/
+typedef
+VOID
+(EFIAPI *VIRTIO_FREE_SHARED)(
+  IN  VIRTIO_DEVICE_PROTOCOL                   *This,
+  IN  UINTN                                    Pages,
+  IN  VOID                                     *HostAddress
+  );
+
+/**
+  Provides the shared addresses required to access system memory from a
+  DMA bus master.
+
+  @param  This                    The protocol instance pointer.
+  @param  Operation               Indicates if the bus master is going to
+                                  read or write to system memory.
+  @param  HostAddress             The system memory address to map to shared
+                                  buffer address.
+  @param  NumberOfBytes           On input the number of bytes to map.
+                                  On output the number of bytes that were
+                                  mapped.
+  @param  DeviceAddress           The resulting shared map address for the
+                                  bus master to access the hosts HostAddress.
+  @param  Mapping                 A resulting value to pass to Unmap().
+
+
+  @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 Map() operation and releases any corresponding resources.
+
+  @param  This                   The protocol instance pointer.
+  @param  Mapping                The mapping value returned from Map().
+
+  @retval EFI_SUCCESS            The range was unmapped.
+  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by
+                                 Map().
+  @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
+  );
 
 ///
 ///  This protocol provides an abstraction over the VirtIo transport layer
@@ -353,6 +468,12 @@ struct _VIRTIO_DEVICE_PROTOCOL {
   // Functions to read/write Device Specific headers
   VIRTIO_DEVICE_WRITE         WriteDevice;
   VIRTIO_DEVICE_READ          ReadDevice;
+
+  // Function 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] 42+ messages in thread

* [PATCH v1 02/14] OvmfPkg/Virtio10Dxe: Implement new member functions
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
  2017-08-07 11:58 ` [PATCH v1 01/14] OvmfPkg/Virtio: Introduce new member functions in VIRTIO_DEVICE_PROTOCOL Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-09 16:50   ` Laszlo Ersek
  2017-08-07 11:58 ` [PATCH v1 03/14] OvmfPkg/VirtioPciDeviceDxe: " Brijesh Singh
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

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

- EFI_PCI_IO_PROTOCOL.AllocateBuffer() -- with BootServicesData
- EFI_PCI_IO_PROTOCOL.FreeBuffer()
- EFI_PCI_IO_PROTOCOL.Map()
- 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 | 114 +++++++++++++++++++-
 1 file changed, 113 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
index a8a6a58c3f1d..5bc8f1c7ee27 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
@@ -772,6 +773,113 @@ 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,
+                         0
+                         );
+  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
+  //
+  if (Operation == EfiVirtIoOperationBusMasterRead) {
+    PciIoOperation = EfiPciIoOperationBusMasterRead;
+  } else if (Operation == EfiVirtIoOperationBusMasterWrite) {
+    PciIoOperation = EfiPciIoOperationBusMasterWrite;
+  } else if (Operation == EfiVirtIoOperationBusMasterCommonBuffer) {
+    PciIoOperation = EfiPciIoOperationBusMasterCommonBuffer;
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+
+  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 +896,11 @@ STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = {
   Virtio10GetDeviceStatus,
   Virtio10SetDeviceStatus,
   Virtio10WriteDevice,
-  Virtio10ReadDevice
+  Virtio10ReadDevice,
+  Virtio10AllocateSharedPages,
+  Virtio10FreeSharedPages,
+  Virtio10MapSharedBuffer,
+  Virtio10UnmapSharedBuffer
 };
 
 
-- 
2.7.4



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

* [PATCH v1 03/14] OvmfPkg/VirtioPciDeviceDxe: Implement new member functions
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
  2017-08-07 11:58 ` [PATCH v1 01/14] OvmfPkg/Virtio: Introduce new member functions in VIRTIO_DEVICE_PROTOCOL Brijesh Singh
  2017-08-07 11:58 ` [PATCH v1 02/14] OvmfPkg/Virtio10Dxe: Implement new member functions Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-09 17:09   ` Laszlo Ersek
  2017-08-07 11:58 ` [PATCH v1 04/14] OvmfPkg/VirtioLib: Add SharedBuffer helper functions Brijesh Singh
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

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

- MemoryApplicationLib.AllocatePages () -- with BootServicesData
- MemoryApplicationLib.FreePages ()
- no-op (host address is same as device DMA address)
- 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 | 66 ++++++++++++++++++++
 3 files changed, 106 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
index 8f17a16c88f5..da98de123000 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 (
   UINT8                          DeviceStatus
   );
 
+EFI_STATUS
+EFIAPI
+VirtioPciAllocateSharedPages (
+  VIRTIO_DEVICE_PROTOCOL        *This,
+  UINTN                         NumPages,
+  VOID                          **HostAddress
+  );
+
+VOID
+EFIAPI
+VirtioPciFreeSharedPages (
+  VIRTIO_DEVICE_PROTOCOL        *This,
+  UINTN                         NumPages,
+  VOID                          *HostAddress
+  );
+
+EFI_STATUS
+EFIAPI
+VirtioPciMapSharedBuffer (
+  VIRTIO_DEVICE_PROTOCOL        *This,
+  VIRTIO_MAP_OPERATION          Operation,
+  VOID                          *HostAddress,
+  UINTN                         *NumberOfBytes,
+  EFI_PHYSICAL_ADDRESS          *DeviceAddress,
+  VOID                          **Mapping
+  );
+
+EFI_STATUS
+EFIAPI
+VirtioPciUnmapSharedBuffer (
+  VIRTIO_DEVICE_PROTOCOL        *This,
+  VOID                          *Mapping
+  );
 #endif // _VIRTIO_PCI_DEVICE_DXE_H_
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
index bc4f6fe8bfa3..4e4e21d9a477 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 243aa14c2421..1c587e184311 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,68 @@ VirtioPciSetDeviceStatus (
   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
       sizeof (UINT8), DeviceStatus);
 }
+
+EFI_STATUS
+EFIAPI
+VirtioPciAllocateSharedPages (
+  VIRTIO_DEVICE_PROTOCOL  *This,
+  UINTN                   NumPages,
+  VOID                    **HostAddress
+  )
+{
+  EFI_STATUS              Status;
+  EFI_PHYSICAL_ADDRESS    PhysicalAddress;
+
+  Status = gBS->AllocatePages (
+                  AllocateAnyPages,
+                  EfiBootServicesData,
+                  NumPages,
+                  &PhysicalAddress
+                  );
+  if (!EFI_ERROR (Status)) {
+    *HostAddress = (VOID *) (UINTN) PhysicalAddress;
+  }
+
+  return Status;
+}
+
+VOID
+EFIAPI
+VirtioPciFreeSharedPages (
+  VIRTIO_DEVICE_PROTOCOL  *This,
+  UINTN                   NumPages,
+  VOID                    *HostAddress
+  )
+{
+  gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN)HostAddress, NumPages);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciMapSharedBuffer (
+  VIRTIO_DEVICE_PROTOCOL  *This,
+  VIRTIO_MAP_OPERATION    Operation,
+  VOID                    *HostAddress,
+  UINTN                   *NumberOfBytes,
+  EFI_PHYSICAL_ADDRESS    *DeviceAddress,
+  VOID                    **Mapping
+  )
+{
+  EFI_PHYSICAL_ADDRESS    PhysicalAddress;
+
+  PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
+
+  *DeviceAddress = PhysicalAddress;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioPciUnmapSharedBuffer (
+  VIRTIO_DEVICE_PROTOCOL    *This,
+  VOID                      *Mapping
+  )
+{
+  return EFI_SUCCESS;
+}
-- 
2.7.4



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

* [PATCH v1 04/14] OvmfPkg/VirtioLib: Add SharedBuffer helper functions
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (2 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 03/14] OvmfPkg/VirtioPciDeviceDxe: " Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-09 20:30   ` Laszlo Ersek
  2017-08-07 11:58 ` [PATCH v1 05/14] OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit() Brijesh Singh
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

Patch adds convenience helper functions to call VIRTIO_DEVICE_PROTOCOL
AllocateSharedPages, FreeSharedPages, MapSharedBuffer and UnmapSharedBuffer
member functions.

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   | 143 +++++++++++++
 OvmfPkg/Library/VirtioLib/VirtioLib.c | 220 ++++++++++++++++++++
 2 files changed, 363 insertions(+)

diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
index 5badfb32917f..fa82734f1852 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,146 @@ Virtio10WriteFeatures (
   IN OUT UINT8                  *DeviceStatus
   );
 
+/**
+  Helper function to allocate pages that is suitable for sharing with
+  hypervisor.
+
+  @param[in]  VirtIo  The target virtio device to use. It must be valid.
+
+  @param[in]  Pages   The number of pages to allocate.
+
+  @param[out] Buffer  A pointer to store the base system memory address of
+                      the allocated range.
+
+  return              Returns error code from VirtIo->AllocateSharedPages()
+**/
+EFI_STATUS
+EFIAPI
+VirtioAllocateSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  UINTN                   NumPages,
+  OUT VOID                    **Buffer
+  );
+
+/**
+  Helper function to free pages allocated using VirtioAllocateSharedPages().
+
+  @param[in]  VirtIo  The target virtio device to use. It must be valid.
+
+  @param[in]  Pages   The number of allocated pages.
+
+  @param[in]  Buffer  System memory address allocated from
+                      VirtioAllocateSharedPages ().
+**/
+VOID
+EFIAPI
+VirtioFreeSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  UINTN                   NumPages,
+  IN  VOID                    *Buffer
+  );
+
+/**
+  A helper function to map a system memory to a shared bus master memory for
+  read operation from DMA bus master.
+
+  @param[in]  VirtIo          The target virtio device to use. It must be
+                              valid.
+
+  @param[in]  HostAddress     The system memory address to map to shared bus
+                              master address.
+
+  @param[in]  NumberOfBytes   Number of bytes to be mapped.
+
+  @param[out] DeviceAddress   The resulting shared map address for the bus
+                              master to access the hosts HostAddress.
+
+  @param[out] Mapping         A resulting value to pass to Unmap().
+
+  return                      Returns error code from
+                              VirtIo->MapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioMapSharedBufferRead (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  VOID                    *HostAddress,
+  IN  UINTN                   NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
+  OUT VOID                    **Mapping
+  );
+
+/**
+  A helper function to map a system memory to a shared bus master memory for
+  write operation from DMA bus master.
+
+  @param[in]  VirtIo          The target virtio device to use. It must be
+                              valid.
+
+  @param[in]  HostAddress     The system memory address to map to shared bus
+                              master address.
+
+  @param[in]  NumberOfBytes   Number of bytes to be mapped.
+
+  @param[out] DeviceAddress   The resulting shared map address for the bus
+                              master to access the hosts HostAddress.
+
+  @param[out] Mapping         A resulting value to pass to Unmap().
+
+  return                      Returns error code from
+                              VirtIo->MapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioMapSharedBufferWrite (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  VOID                    *HostAddress,
+  IN  UINTN                   NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
+  OUT VOID                    **Mapping
+  );
+
+/**
+  A helper function to map a system memory to a shared bus master memory for
+  common operation from DMA bus master.
+
+  @param[in]  VirtIo          The target virtio device to use. It must be
+                              valid.
+
+  @param[in]  HostAddress     The system memory address to map to shared bus
+                              master address.
+
+  @param[in]  NumberOfBytes   Number of bytes to be mapped.
+
+  @param[out] Mapping         A resulting value to pass to Unmap().
+
+  return                      Returns error code from
+                              VirtIo->MapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioMapSharedBufferCommon (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  VOID                    *HostAddress,
+  IN  UINTN                   NumberOfBytes,
+  OUT VOID                    **Mapping
+  );
+
+/**
+  A helper function to unmap shared bus master memory mapped using Map().
+
+  @param[in]  VirtIo          The target virtio device to use. It must be
+                              valid.
+
+  @param[in] Mapping          A mapping value return from Map().
+
+  return                      Returns error code from
+                              VirtIo->UnmapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioUnmapSharedBuffer (
+  IN VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN VOID                    *Mapping
+  );
 #endif // _VIRTIO_LIB_H_
diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
index 845f206369a3..f6b464b6cdf8 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,222 @@ Virtio10WriteFeatures (
 
   return Status;
 }
+
+/**
+  Helper function to allocate pages that is suitable for sharing with
+  hypervisor.
+
+  @param[in]  VirtIo  The target virtio device to use. It must be valid.
+
+  @param[in]  Pages   The number of pages to allocate.
+
+  @param[out] Buffer  A pointer to store the base system memory address of
+                      the allocated range.
+
+  return              Returns error code from VirtIo->AllocateSharedPages()
+**/
+EFI_STATUS
+EFIAPI
+VirtioAllocateSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  UINTN                   NumPages,
+  OUT VOID                    **Buffer
+  )
+{
+  return VirtIo->AllocateSharedPages (VirtIo, NumPages, Buffer);
+}
+
+/**
+  Helper function to free pages allocated using VirtioAllocateSharedPages().
+
+  @param[in]  VirtIo  The target virtio device to use. It must be valid.
+
+  @param[in]  Pages   The number of allocated pages.
+
+  @param[in]  Buffer  System memory address allocated from
+                      VirtioAllocateSharedPages ().
+**/
+VOID
+EFIAPI
+VirtioFreeSharedPages (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  UINTN                   NumPages,
+  IN  VOID                    *Buffer
+  )
+{
+  VirtIo->FreeSharedPages (VirtIo, NumPages, Buffer);
+}
+
+STATIC
+EFI_STATUS
+VirtioMapSharedBuffer (
+  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);
+  return EFI_OUT_OF_RESOURCES;
+}
+
+/**
+  A helper function to map a system memory to a shared bus master memory for
+  read operation from DMA bus master.
+
+  @param[in]  VirtIo          The target virtio device to use. It must be
+                              valid.
+
+  @param[in]  HostAddress     The system memory address to map to shared bus
+                              master address.
+
+  @param[in]  NumberOfBytes   Number of bytes to be mapped.
+
+  @param[out] DeviceAddress   The resulting shared map address for the bus
+                              master to access the hosts HostAddress.
+
+  @param[out] Mapping         A resulting value to pass to Unmap().
+
+  return                      Returns error code from
+                              VirtIo->MapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioMapSharedBufferRead (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  VOID                    *HostAddress,
+  IN  UINTN                   NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
+  OUT VOID                    **Mapping
+  )
+{
+  return VirtioMapSharedBuffer (VirtIo, EfiVirtIoOperationBusMasterRead,
+           HostAddress, NumberOfBytes, DeviceAddress, Mapping);
+}
+
+/**
+  A helper function to map a system memory to a shared bus master memory for
+  write operation from DMA bus master.
+
+  @param[in]  VirtIo          The target virtio device to use. It must be
+                              valid.
+
+  @param[in]  HostAddress     The system memory address to map to shared bus
+                              master address.
+
+  @param[in]  NumberOfBytes   Number of bytes to be mapped.
+
+  @param[out] DeviceAddress   The resulting shared map address for the bus
+                              master to access the hosts HostAddress.
+
+  @param[out] Mapping         A resulting value to pass to Unmap().
+
+  return                      Returns error code from
+                              VirtIo->MapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioMapSharedBufferWrite (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  VOID                    *HostAddress,
+  IN  UINTN                   NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
+  OUT VOID                    **Mapping
+  )
+{
+  return VirtioMapSharedBuffer (VirtIo, EfiVirtIoOperationBusMasterWrite,
+           HostAddress, NumberOfBytes, DeviceAddress, Mapping);
+}
+
+/**
+  A helper function to map a system memory to a shared bus master memory for
+  common operation from DMA bus master.
+
+  @param[in]  VirtIo          The target virtio device to use. It must be
+                              valid.
+
+  @param[in]  HostAddress     The system memory address to map to shared bus
+                              master address.
+
+  @param[in]  NumberOfBytes   Number of bytes to be mapped.
+
+  @param[out] Mapping         A resulting value to pass to Unmap().
+
+  return                      Returns error code from
+                              VirtIo->MapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioMapSharedBufferCommon (
+  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN  VOID                    *HostAddress,
+  IN  UINTN                   NumberOfBytes,
+  OUT VOID                    **Mapping
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  DeviceAddress;
+
+  Status = VirtioMapSharedBuffer (VirtIo,
+             EfiVirtIoOperationBusMasterCommonBuffer, HostAddress,
+             NumberOfBytes, &DeviceAddress, Mapping);
+
+  //
+  // On Success, lets verify that DeviceAddress same as HostAddress
+  //
+  if (!EFI_ERROR (Status)) {
+    ASSERT (DeviceAddress == (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress);
+  }
+
+  return Status;
+}
+
+/**
+  A helper function to unmap shared bus master memory mapped using Map().
+
+  @param[in]  VirtIo          The target virtio device to use. It must be
+                              valid.
+
+  @param[in] Mapping          A mapping value return from Map().
+
+  return                      Returns error code from
+                              VirtIo->UnmapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioUnmapSharedBuffer (
+  IN VIRTIO_DEVICE_PROTOCOL  *VirtIo,
+  IN VOID                    *Mapping
+  )
+{
+  return VirtIo->UnmapSharedBuffer (VirtIo, Mapping);
+}
-- 
2.7.4



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

* [PATCH v1 05/14] OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit()
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (3 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 04/14] OvmfPkg/VirtioLib: Add SharedBuffer helper functions Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-09 21:13   ` Laszlo Ersek
  2017-08-07 11:58 ` [PATCH v1 06/14] OvmfPkg/VirtioLib: Add functions to map/unmap VRING Brijesh Singh
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 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 fa82734f1852..610654225de7 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 will 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 f6b464b6cdf8..50e5ec28ea1b 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 will 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] 42+ messages in thread

* [PATCH v1 06/14] OvmfPkg/VirtioLib: Add functions to map/unmap VRING
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (4 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 05/14] OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit() Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-09 23:51   ` Laszlo Ersek
  2017-08-07 11:58 ` [PATCH v1 07/14] OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer Brijesh Singh
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 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.

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   | 41 +++++++++++++++
 OvmfPkg/Library/VirtioLib/VirtioLib.c | 52 ++++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
index 610654225de7..877961af0514 100644
--- a/OvmfPkg/Include/Library/VirtioLib.h
+++ b/OvmfPkg/Include/Library/VirtioLib.h
@@ -62,6 +62,47 @@ 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]     Mapping   A resulting value to pass to Unmap().
+
+  @retval         Value returned from VirtIo->MapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioRingMap (
+  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
+  IN  VRING                  *Ring,
+  OUT VOID                   **Mapping
+  );
+
+/**
+
+  Unmap the ring buffer mapped using VirtioRingMap()
+
+  @param[in]      VirtIo    The virtio device instance.
+
+  @param[in]      Ring      The virtio ring to unmap.
+
+  @param[in]      Mapping   A value obtained through Map().
+
+  @retval         Value returned from VirtIo->UnmapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioRingUnmap (
+  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
+  IN  VRING                  *Ring,
+  IN  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 50e5ec28ea1b..09a3f9b7f2e5 100644
--- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
+++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
@@ -640,3 +640,55 @@ VirtioUnmapSharedBuffer (
 {
   return VirtIo->UnmapSharedBuffer (VirtIo, Mapping);
 }
+
+/**
+
+  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]     Mapping   A resulting value to pass to Unmap().
+
+  @retval         Value returned from VirtIo->MapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioRingMap (
+  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
+  IN  VRING                  *Ring,
+  OUT VOID                   **Mapping
+  )
+{
+  UINTN                 NumberOfBytes;
+
+  NumberOfBytes = Ring->NumPages * EFI_PAGE_SIZE;
+
+  return VirtioMapSharedBufferCommon (VirtIo, Ring->Base,
+           NumberOfBytes, Mapping);
+}
+
+/**
+
+  Unmap the ring buffer mapped using VirtioRingMap()
+
+  @param[in]      VirtIo    The virtio device instance.
+
+  @param[in]      Ring      The virtio ring to unmap.
+
+  @param[in]      Mapping   A value obtained through Map().
+
+  @retval         Value returned from VirtIo->UnmapSharedBuffer()
+**/
+EFI_STATUS
+EFIAPI
+VirtioRingUnmap (
+  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
+  IN  VRING                  *Ring,
+  IN  VOID                   *Mapping
+  )
+{
+  return VirtioUnmapSharedBuffer (VirtIo, Mapping);
+}
-- 
2.7.4



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

* [PATCH v1 07/14] OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (5 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 06/14] OvmfPkg/VirtioLib: Add functions to map/unmap VRING Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-10  0:02   ` Laszlo Ersek
  2017-08-07 11:58 ` [PATCH v1 08/14] OvmfPkg/VirtioBlkDxe: Use DeviceAddresses in vring descriptors Brijesh Singh
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

The vring buffer is communication block between guest and hypervisor,
allocate the vring buffer using AllocateSharedPages() so that it can be
Map() with BusMasterCommonBufer for bi-directional access.

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 | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
index 09a3f9b7f2e5..9ba64204326f 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,12 @@ 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 = VirtioAllocateSharedPages (VirtIo, Ring->NumPages, &Ring->Base);
+  if (EFI_ERROR (Status)) {
     return EFI_OUT_OF_RESOURCES;
   }
   SetMem (Ring->Base, RingSize, 0x00);
@@ -143,7 +147,7 @@ VirtioRingUninit (
   IN OUT VRING                  *Ring
   )
 {
-  FreePages (Ring->Base, Ring->NumPages);
+  VirtioFreeSharedPages (VirtIo, Ring->NumPages, Ring->Base);
   SetMem (Ring, sizeof *Ring, 0x00);
 }
 
-- 
2.7.4



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

* [PATCH v1 08/14] OvmfPkg/VirtioBlkDxe: Use DeviceAddresses in vring descriptors
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (6 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 07/14] OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-07 11:58 ` [PATCH v1 09/14] OvmfPkg/VirtioScsiDxe: " Brijesh Singh
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 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 newly introduced VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer()
function to map system memory 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 | 97 ++++++++++++++++++--
 2 files changed, 91 insertions(+), 7 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 61b9cab4ff02..324403543f24 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,24 @@ SynchronousRequest (
   ASSERT (Dev->Ring.QueueSize >= 3);
 
   //
+  // Map virtio-blk request header
+  //
+  Status = VirtioMapSharedBufferRead (Dev->VirtIo, (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 +324,70 @@ SynchronousRequest (
     ASSERT (BufferSize <= SIZE_1GB);
 
     //
+    // Map data buffer
+    //
+    if (RequestIsWrite) {
+      Status = VirtioMapSharedBufferRead (Dev->VirtIo, (VOID *) Buffer,
+                 BufferSize, &DeviceAddress, &BufferMapping);
+    } else {
+      Status = VirtioMapSharedBufferWrite (Dev->VirtIo, (VOID *) Buffer,
+                 BufferSize, &DeviceAddress, &BufferMapping);
+    }
+
+    if (EFI_ERROR (Status)) {
+      goto Mapping_Failed;
+    }
+
+    //
     // 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 = VirtioMapSharedBufferWrite (Dev->VirtIo, (VOID *) &HostStatus,
+             sizeof HostStatus, &DeviceAddress, &StatusMapping);
+  if (EFI_ERROR (Status)) {
+    goto Mapping_Failed;
+  }
+
+  //
   // 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
+  //
+  VirtioUnmapSharedBuffer (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;
+Mapping_Failed:
+  VirtioUnmapSharedBuffer (Dev->VirtIo, RequestMapping);
+
+  if (BufferMapping != NULL) {
+    VirtioUnmapSharedBuffer (Dev->VirtIo, BufferMapping);
+  }
+
+  return Status;
 }
 
 
@@ -728,6 +784,11 @@ VirtioBlkInit (
     goto Failed;
   }
 
+  Status = VirtioRingMap (Dev->VirtIo, &Dev->Ring, &Dev->RingMapping);
+  if (EFI_ERROR (Status)) {
+    goto Failed;
+  }
+
   //
   // Additional steps for MMIO: align the queue appropriately, and set the
   // size. If anything fails from here on, we must release the ring resources.
@@ -812,6 +873,11 @@ VirtioBlkInit (
   return EFI_SUCCESS;
 
 ReleaseQueue:
+  if (Dev->RingMapping != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMapping);
+    Dev->RingMapping = NULL;
+  }
+
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
 Failed:
@@ -849,6 +915,14 @@ VirtioBlkUninit (
   //
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
 
+  //
+  // If ring buffer is mapped then Umap() it before uninitializing it.
+  //
+  if (Dev->RingMapping != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMapping);
+    Dev->RingMapping = NULL;
+  }
+
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
   SetMem (&Dev->BlockIo,      sizeof Dev->BlockIo,      0x00);
@@ -885,6 +959,15 @@ 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.
+  //
+  if (Dev->RingMapping != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMapping);
+    Dev->RingMapping = NULL;
+  }
 }
 
 /**
-- 
2.7.4



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

* [PATCH v1 09/14] OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (7 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 08/14] OvmfPkg/VirtioBlkDxe: Use DeviceAddresses in vring descriptors Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-07 11:58 ` [PATCH v1 10/14] OvmfPkg/VirtioNetDxe: Allocate Tx and Rx ring using AllocateSharedPage() Brijesh Singh
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 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 | 114 ++++++++++++++++++--
 2 files changed, 107 insertions(+), 8 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 c2f6f412ff40..779104567694 100644
--- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
+++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c
@@ -409,8 +409,14 @@ 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;
+  UINTN                     NumPages;
 
   ZeroMem ((VOID*) &Request, sizeof (Request));
   ZeroMem ((VOID*) &Response, sizeof (Response));
@@ -418,9 +424,33 @@ 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.
+  //
+  NumPages = EFI_SIZE_TO_PAGES (sizeof (*Response));
+  Status = VirtioAllocateSharedPages (Dev->VirtIo, NumPages,
+             (VOID *) &Response);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = VirtioMapSharedBufferCommon (Dev->VirtIo, (VOID *) Response,
+             sizeof (*Response), &ResponseMapping);
+  if (EFI_ERROR (Status)) {
+    goto Failed;
+  }
+
   Status = PopulateRequest (Dev, TargetValue, Lun, Packet, &Request);
   if (EFI_ERROR (Status)) {
-    return Status;
+    goto Failed;
   }
 
   VirtioPrepare (&Dev->Ring, &Indices);
@@ -428,7 +458,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 +467,37 @@ VirtioScsiPassThru (
   ASSERT (Dev->Ring.QueueSize >= 4);
 
   //
+  // Map the scsi-blk request header HostAddress to DeviceAddress
+  //
+  Status = VirtioMapSharedBufferRead (Dev->VirtIo, (VOID *) &Request,
+             sizeof Request, &DeviceAddress, &RequestMapping);
+  if (EFI_ERROR (Status)) {
+    goto Failed;
+  }
+
+  //
   // 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,
+    Status = VirtioMapSharedBufferRead (Dev->VirtIo, Packet->OutDataBuffer,
+               Packet->OutTransferLength, &DeviceAddress, &OutDataMapping);
+    if (EFI_ERROR (Status)) {
+      goto Failed;
+    }
+    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 +506,13 @@ VirtioScsiPassThru (
   // enqueue "datain" if any, to be written by the host
   //
   if (Packet->InTransferLength > 0) {
-    VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->InDataBuffer,
+    Status = VirtioMapSharedBufferWrite (Dev->VirtIo, Packet->InDataBuffer,
+               Packet->InTransferLength, &DeviceAddress, &InDataMapping);
+    if (EFI_ERROR (Status)) {
+      goto Failed;
+    }
+
+    VirtioAppendDesc (&Dev->Ring, (UINTN) DeviceAddress,
       Packet->InTransferLength, VRING_DESC_F_WRITE, &Indices);
   }
 
@@ -480,7 +530,28 @@ VirtioScsiPassThru (
     return EFI_DEVICE_ERROR;
   }
 
-  return ParseResponse (Packet, &Response);
+  Status = ParseResponse (Packet, Response);
+
+Failed:
+  if (RequestMapping) {
+    VirtioUnmapSharedBuffer (Dev->VirtIo, RequestMapping);
+  }
+
+  if (InDataMapping) {
+    VirtioUnmapSharedBuffer (Dev->VirtIo, InDataMapping);
+  }
+
+  if (OutDataMapping) {
+    VirtioUnmapSharedBuffer (Dev->VirtIo, OutDataMapping);
+  }
+
+  if (ResponseMapping) {
+    VirtioUnmapSharedBuffer (Dev->VirtIo, ResponseMapping);
+  }
+
+  VirtioFreeSharedPages (Dev->VirtIo, NumPages, (VOID *) Response);
+
+  return Status;
 }
 
 
@@ -838,6 +909,11 @@ VirtioScsiInit (
     goto Failed;
   }
 
+  Status = VirtioRingMap (Dev->VirtIo, &Dev->Ring, &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.
@@ -927,6 +1003,11 @@ VirtioScsiInit (
   return EFI_SUCCESS;
 
 ReleaseQueue:
+  if (Dev->RingBufMapping != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, &Dev->RingBufMapping);
+    Dev->RingBufMapping = NULL;
+  }
+
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
 Failed:
@@ -965,6 +1046,14 @@ VirtioScsiUninit (
   Dev->MaxLun         = 0;
   Dev->MaxSectors     = 0;
 
+  //
+  // If Ring buffer is mapped then unmap it.
+  //
+  if (Dev->RingBufMapping != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, &Dev->RingBufMapping);
+    Dev->RingBufMapping = NULL;
+  }
+
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
   SetMem (&Dev->PassThru,     sizeof Dev->PassThru,     0x00);
@@ -995,6 +1084,15 @@ 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.
+  //
+  if (Dev->RingBufMapping != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingBufMapping);
+    Dev->RingBufMapping = NULL;
+  }
 }
 
 
-- 
2.7.4



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

* [PATCH v1 10/14] OvmfPkg/VirtioNetDxe: Allocate Tx and Rx ring using AllocateSharedPage()
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (8 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 09/14] OvmfPkg/VirtioScsiDxe: " Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-07 11:58 ` [PATCH v1 11/14] OvmfPkg/VirtioNetDxe: Allocate RxBuf using AllocateSharedPages() Brijesh Singh
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 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        | 14 ++++++++++++++
 OvmfPkg/VirtioNetDxe/SnpInitialize.c | 19 +++++++++++++++++++
 OvmfPkg/VirtioNetDxe/SnpShutdown.c   | 11 +++++++++++
 4 files changed, 46 insertions(+)

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..9eb129ca2006 100644
--- a/OvmfPkg/VirtioNetDxe/Events.c
+++ b/OvmfPkg/VirtioNetDxe/Events.c
@@ -88,4 +88,18 @@ VirtioNetExitBoot (
   if (Dev->Snm.State == EfiSimpleNetworkInitialized) {
     Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
   }
+
+  //
+  // If Rx and Tx Ring exist then unmap it so that hypervisor is not able to
+  // get readable data after device is reset.
+  //
+  if (Dev->TxRingMap != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->TxRing, Dev->TxRingMap);
+    Dev->TxRingMap = NULL;
+  }
+
+  if (Dev->RxRingMap != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->RxRing, Dev->RxRingMap);
+    Dev->RxRingMap = NULL;
+  }
 }
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index 6d9b81a9f939..cbc9c51cb643 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -461,11 +461,21 @@ VirtioNetInitialize (
     goto DeviceFailed;
   }
 
+  Status = VirtioRingMap (Dev->VirtIo, &Dev->RxRing, &Dev->RxRingMap);
+  if (EFI_ERROR (Status)) {
+    goto ReleaseRxRing;
+  }
+
   Status = VirtioNetInitRing (Dev, VIRTIO_NET_Q_TX, &Dev->TxRing);
   if (EFI_ERROR (Status)) {
     goto ReleaseRxRing;
   }
 
+  Status = VirtioRingMap (Dev->VirtIo, &Dev->TxRing, &Dev->TxRingMap);
+  if (EFI_ERROR (Status)) {
+    goto ReleaseTxRing;
+  }
+
   //
   // step 5 -- keep only the features we want
   //
@@ -510,9 +520,18 @@ AbortDevice:
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
 
 ReleaseTxRing:
+  if (Dev->TxRingMap != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->TxRing, Dev->TxRingMap);
+    Dev->TxRingMap = NULL;
+  }
+
   VirtioRingUninit (Dev->VirtIo, &Dev->TxRing);
 
 ReleaseRxRing:
+  if (Dev->RxRingMap != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->TxRing, Dev->RxRingMap);
+    Dev->TxRingMap = NULL;
+  }
   VirtioRingUninit (Dev->VirtIo, &Dev->RxRing);
 
 DeviceFailed:
diff --git a/OvmfPkg/VirtioNetDxe/SnpShutdown.c b/OvmfPkg/VirtioNetDxe/SnpShutdown.c
index 5e84191fbbdd..08524ab94006 100644
--- a/OvmfPkg/VirtioNetDxe/SnpShutdown.c
+++ b/OvmfPkg/VirtioNetDxe/SnpShutdown.c
@@ -65,6 +65,17 @@ VirtioNetShutdown (
   }
 
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
+
+  if (Dev->RxRingMap != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->RxRing, Dev->RxRingMap);
+    Dev->RxRingMap = NULL;
+  }
+
+  if (Dev->TxRingMap != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->TxRing, Dev->TxRingMap);
+    Dev->TxRingMap = NULL;
+  }
+
   VirtioNetShutdownRx (Dev);
   VirtioNetShutdownTx (Dev);
   VirtioRingUninit (Dev->VirtIo, &Dev->TxRing);
-- 
2.7.4



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

* [PATCH v1 11/14] OvmfPkg/VirtioNetDxe: Allocate RxBuf using AllocateSharedPages()
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (9 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 10/14] OvmfPkg/VirtioNetDxe: Allocate Tx and Rx ring using AllocateSharedPage() Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-07 11:58 ` [PATCH v1 12/14] OvmfPkg/VirtioNetDxe: Dynamically allocate transmit header Brijesh Singh
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 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           |  5 +++
 OvmfPkg/VirtioNetDxe/SnpInitialize.c    | 33 +++++++++++++++++---
 OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c | 10 +++++-
 4 files changed, 46 insertions(+), 5 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 9eb129ca2006..171b144518a9 100644
--- a/OvmfPkg/VirtioNetDxe/Events.c
+++ b/OvmfPkg/VirtioNetDxe/Events.c
@@ -102,4 +102,9 @@ VirtioNetExitBoot (
     VirtioRingUnmap (Dev->VirtIo, &Dev->RxRing, Dev->RxRingMap);
     Dev->RxRingMap = NULL;
   }
+
+  if (Dev->RxBufMap != NULL) {
+    VirtioUnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
+    Dev->RxBufMap = NULL;
+  }
 }
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index cbc9c51cb643..59c9f1ed3516 100644
--- a/OvmfPkg/VirtioNetDxe/SnpInitialize.c
+++ b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
@@ -244,6 +244,7 @@ VirtioNetInitRx (
   UINTN      PktIdx;
   UINT16     DescIdx;
   UINT8      *RxPtr;
+  UINTN      NumBytes;
 
   //
   // In VirtIo 1.0, the NumBuffers field is mandatory. In 0.9.5, it depends on
@@ -268,9 +269,24 @@ 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 = VirtioAllocateSharedPages (Dev->VirtIo, Dev->RxBufNoPages,
+             (VOID *) &Dev->RxBuf);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = VirtioMapSharedBufferCommon (Dev->VirtIo, Dev->RxBuf, NumBytes,
+             &Dev->RxBufMap);
+  if (EFI_ERROR (Status)) {
+    goto Failed;
   }
 
   //
@@ -333,10 +349,19 @@ 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 Failed;
   }
 
   return Status;
+
+Failed:
+  if (Dev->RxBufMap != NULL) {
+    VirtioUnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
+    Dev->RxBufMap = NULL;
+  }
+
+  VirtioFreeSharedPages (Dev->VirtIo, Dev->RxBufNoPages, (VOID *) Dev->RxBuf);
+  return Status;
 }
 
 
diff --git a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
index 9fedb72fdbd4..48cd4900911c 100644
--- a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
+++ b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
@@ -39,7 +39,15 @@ VirtioNetShutdownRx (
   IN OUT VNET_DEV *Dev
   )
 {
-  FreePool (Dev->RxBuf);
+  //
+  // If RxBuf mapping exist then unmap it.
+  //
+  if (Dev->RxBufMap != NULL) {
+    VirtioUnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
+    Dev->RxBufMap = NULL;
+  }
+
+  VirtioFreeSharedPages (Dev->VirtIo, Dev->RxBufNoPages, (VOID *) Dev->RxBuf);
 }
 
 
-- 
2.7.4



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

* [PATCH v1 12/14] OvmfPkg/VirtioNetDxe: Dynamically allocate transmit header
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (10 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 11/14] OvmfPkg/VirtioNetDxe: Allocate RxBuf using AllocateSharedPages() Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-07 11:58 ` [PATCH v1 13/14] OvmfPkg/VirtioNetDxe: Use DeviceAddress in transmit vring descriptors Brijesh Singh
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 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           |  5 +++
 OvmfPkg/VirtioNetDxe/SnpInitialize.c    | 41 ++++++++++++++++----
 OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c |  9 +++++
 4 files changed, 49 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 171b144518a9..0004898eab6e 100644
--- a/OvmfPkg/VirtioNetDxe/Events.c
+++ b/OvmfPkg/VirtioNetDxe/Events.c
@@ -107,4 +107,9 @@ VirtioNetExitBoot (
     VirtioUnmapSharedBuffer (Dev->VirtIo, Dev->RxBufMap);
     Dev->RxBufMap = NULL;
   }
+
+  if (Dev->TxSharedReqMap != NULL) {
+    VirtioUnmapSharedBuffer (Dev->VirtIo, Dev->TxSharedReqMap);
+    Dev->TxSharedReqMap = NULL;
+  }
 }
diff --git a/OvmfPkg/VirtioNetDxe/SnpInitialize.c b/OvmfPkg/VirtioNetDxe/SnpInitialize.c
index 59c9f1ed3516..9df9f7af32cc 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>
 
@@ -139,8 +140,10 @@ VirtioNetInitTx (
   IN OUT VNET_DEV *Dev
   )
 {
-  UINTN TxSharedReqSize;
-  UINTN PktIdx;
+  UINTN       TxSharedReqSize;
+  UINTN       PktIdx;
+  UINTN       NumPages;
+  EFI_STATUS  Status;
 
   Dev->TxMaxPending = (UINT16) MIN (Dev->TxRing.QueueSize / 2,
                                  VNET_MAX_PENDING);
@@ -152,12 +155,34 @@ VirtioNetInitTx (
   }
 
   //
+  // Allocate TxSharedReq header and map with BusMasterCommonBuffer so that it
+  // can be accessed equally by both processor and device.
+  //
+  NumPages = EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq));
+  Status = VirtioAllocateSharedPages (Dev->VirtIo, NumPages,
+             (VOID *) &Dev->TxSharedReq);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = VirtioMapSharedBufferCommon (Dev->VirtIo,
+             (VOID *) Dev->TxSharedReq, sizeof *(Dev->TxSharedReq),
+             &Dev->TxSharedReqMap);
+  if (EFI_ERROR (Status)) {
+    VirtioFreeSharedPages (Dev->VirtIo, NumPages,
+      (VOID *) Dev->TxSharedReqMap);
+    return Status;
+  }
+
+  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;
@@ -169,7 +194,7 @@ VirtioNetInitTx (
     // 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) Dev->TxSharedReq;
     Dev->TxRing.Desc[DescIdx].Len   = (UINT32) TxSharedReqSize;
     Dev->TxRing.Desc[DescIdx].Flags = VRING_DESC_F_NEXT;
     Dev->TxRing.Desc[DescIdx].Next  = (UINT16) (DescIdx + 1);
@@ -184,13 +209,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
diff --git a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
index 48cd4900911c..3ed7132be531 100644
--- a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
+++ b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
@@ -57,5 +57,14 @@ VirtioNetShutdownTx (
   IN OUT VNET_DEV *Dev
   )
 {
+  if (Dev->TxSharedReqMap != NULL) {
+    VirtioUnmapSharedBuffer (Dev->VirtIo, Dev->TxSharedReqMap);
+    Dev->TxSharedReqMap = NULL;
+  }
+
+  VirtioFreeSharedPages (Dev->VirtIo,
+    EFI_SIZE_TO_PAGES (sizeof *(Dev->TxSharedReq)),
+    (VOID *) Dev->TxSharedReq);
+
   FreePool (Dev->TxFreeStack);
 }
-- 
2.7.4



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

* [PATCH v1 13/14] OvmfPkg/VirtioNetDxe: Use DeviceAddress in transmit vring descriptors
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (11 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 12/14] OvmfPkg/VirtioNetDxe: Dynamically allocate transmit header Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-07 11:58 ` [PATCH v1 14/14] OvmfPkg/VirtioRngDxe: Use DeviceAddresses in " Brijesh Singh
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 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
DMA address and use the DeviceAddress in vring descriptors.

Since the transmit buffers are returned back to caller in
VirtioNetGetStatus() hence we maintain a list to map DeviceAddress to
HostAddress. The list is consulted to find the correct HostAddress upon
transmit completion interruption.

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 | 100 ++++++++++++++++++++
 OvmfPkg/VirtioNetDxe/SnpTransmit.c      |  22 +++--
 4 files changed, 149 insertions(+), 9 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 3ed7132be531..6a6866e65b5f 100644
--- a/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
+++ b/OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c
@@ -14,10 +14,25 @@
 
 **/
 
+#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)
+
+STATIC LIST_ENTRY mTxBufMapList = INITIALIZE_LIST_HEAD_VARIABLE (mTxBufMapList);
+
+
 /**
   Release RX and TX resources on the boundary of the
   EfiSimpleNetworkInitialized state.
@@ -68,3 +83,88 @@ 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 = VirtioMapSharedBufferRead (Dev->VirtIo,
+             (VOID *) (UINTN) Private->HostAddress, NumberOfBytes,
+             &Private->DeviceAddress, &Private->Mapping);
+  if (EFI_ERROR (Status)) {
+    FreePool (Private);
+    return Status;
+  }
+
+  *DeviceAddress = Private->DeviceAddress;
+
+  //
+  // Add the mapping information into internal list so that we can retrieve
+  // the HostAddress upon Unmap().
+  //
+  InsertTailList (&mTxBufMapList, &Private->Link);
+
+  return EFI_SUCCESS;
+}
+
+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 = VirtioUnmapSharedBuffer (Dev->VirtIo, Private->Mapping);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *HostAddress = Private->HostAddress;
+
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/VirtioNetDxe/SnpTransmit.c b/OvmfPkg/VirtioNetDxe/SnpTransmit.c
index 7ca40d5d0650..20c56c12df04 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,19 @@ 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;
 
   //
-- 
2.7.4



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

* [PATCH v1 14/14] OvmfPkg/VirtioRngDxe: Use DeviceAddresses in vring descriptors
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (12 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 13/14] OvmfPkg/VirtioNetDxe: Use DeviceAddress in transmit vring descriptors Brijesh Singh
@ 2017-08-07 11:58 ` Brijesh Singh
  2017-08-10  0:25   ` Laszlo Ersek
  2017-08-09 14:39 ` [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Laszlo Ersek
  2017-08-09 22:38 ` Laszlo Ersek
  15 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-07 11:58 UTC (permalink / raw)
  To: edk2-devel
  Cc: Brijesh Singh, Ard Biesheuvel, Jordan Justen, Tom Lendacky,
	Laszlo Ersek

The patch uses newly introduced VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer()
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/VirtioRngDxe/VirtioRng.h |  1 +
 OvmfPkg/VirtioRngDxe/VirtioRng.c | 47 +++++++++++++++++---
 2 files changed, 43 insertions(+), 5 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 e20602ac7225..5ff54867616a 100644
--- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
+++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
@@ -140,11 +140,15 @@ VirtioRngGetRNG (
   UINT32                    Len;
   UINT32                    BufferSize;
   EFI_STATUS                Status;
+  UINTN                     NumPages;
+  EFI_PHYSICAL_ADDRESS      DeviceAddress;
+  VOID                      *Mapping;
 
   if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {
     return EFI_INVALID_PARAMETER;
   }
 
+  Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
   //
   // We only support the raw algorithm, so reject requests for anything else
   //
@@ -153,12 +157,18 @@ VirtioRngGetRNG (
     return EFI_UNSUPPORTED;
   }
 
-  Buffer = (volatile UINT8 *)AllocatePool (RNGValueLength);
-  if (Buffer == NULL) {
+  NumPages = EFI_SIZE_TO_PAGES (RNGValueLength);
+  Status = VirtioAllocateSharedPages (Dev->VirtIo, NumPages, (VOID *)&Buffer);
+  if (EFI_ERROR (Status)) {
     return EFI_DEVICE_ERROR;
   }
 
-  Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
+  Status = VirtioMapSharedBufferWrite (Dev->VirtIo, (VOID *)Buffer,
+             RNGValueLength, &DeviceAddress, &Mapping);
+  if (EFI_ERROR (Status)) {
+    VirtioFreeSharedPages (Dev->VirtIo, NumPages, (VOID *)Buffer);
+    return EFI_DEVICE_ERROR;
+  }
 
   //
   // The Virtio RNG device may return less data than we asked it to, and can
@@ -170,7 +180,7 @@ VirtioRngGetRNG (
 
     VirtioPrepare (&Dev->Ring, &Indices);
     VirtioAppendDesc (&Dev->Ring,
-      (UINTN)Buffer + Index,
+      (UINTN)DeviceAddress + Index,
       BufferSize,
       VRING_DESC_F_WRITE,
       &Indices);
@@ -178,19 +188,22 @@ VirtioRngGetRNG (
     if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=
         EFI_SUCCESS) {
       Status = EFI_DEVICE_ERROR;
+      VirtioUnmapSharedBuffer (Dev->VirtIo, Mapping);
       goto FreeBuffer;
     }
     ASSERT (Len > 0);
     ASSERT (Len <= BufferSize);
   }
 
+  VirtioUnmapSharedBuffer (Dev->VirtIo, Mapping);
+
   for (Index = 0; Index < RNGValueLength; Index++) {
     RNGValue[Index] = Buffer[Index];
   }
   Status = EFI_SUCCESS;
 
 FreeBuffer:
-  FreePool ((VOID *)Buffer);
+  VirtioFreeSharedPages (Dev->VirtIo, NumPages, (VOID *)Buffer);
   return Status;
 }
 
@@ -281,6 +294,11 @@ VirtioRngInit (
     goto Failed;
   }
 
+  Status = VirtioRingMap (Dev->VirtIo, &Dev->Ring, &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.
@@ -332,6 +350,11 @@ VirtioRngInit (
   return EFI_SUCCESS;
 
 ReleaseQueue:
+  if (Dev->RingMap != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap);
+    Dev->RingMap = NULL;
+  }
+
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 
 Failed:
@@ -359,6 +382,11 @@ VirtioRngUninit (
   // the old comms area.
   //
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
+
+  if (Dev->RingMap != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap);
+  }
+
   VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
 }
 
@@ -385,6 +413,15 @@ VirtioRngExitBoot (
   //
   Dev = Context;
   Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
+
+  //
+  // If Ring mapping exist then umap it so that hypervisor will not able to
+  // get readable data after device reset.
+  //
+  if (Dev->RingMap != NULL) {
+    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap);
+    Dev->RingMap = NULL;
+  }
 }
 
 
-- 
2.7.4



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

* Re: [PATCH v1 01/14] OvmfPkg/Virtio: Introduce new member functions in VIRTIO_DEVICE_PROTOCOL
  2017-08-07 11:58 ` [PATCH v1 01/14] OvmfPkg/Virtio: Introduce new member functions in VIRTIO_DEVICE_PROTOCOL Brijesh Singh
@ 2017-08-09 14:27   ` Laszlo Ersek
  2017-08-09 18:23     ` Brijesh Singh
  0 siblings, 1 reply; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-09 14:27 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/07/17 13:58, 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().
> 
> 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 | 121 ++++++++++++++++++++
>  1 file changed, 121 insertions(+)

(1) I suggest the following subject:

OvmfPkg: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL

The current wording "new member functions" is a bit too generic IMO.

> 
> diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
> index 910a4866e7ac..ea5272165389 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,26 @@
>  
>  typedef struct _VIRTIO_DEVICE_PROTOCOL  VIRTIO_DEVICE_PROTOCOL;
>  
> +//
> +// VIRTIO Operation for Map
> +//

(2) "Map" can be made a bit more precise; please say either
"VIRTIO_MAP_SHARED" or MapSharedBuffer().

> +typedef enum {
> +  //
> +  // A read operation from system memory by a bus master
> +  //
> +  EfiVirtIoOperationBusMasterRead,
> +  //
> +  // A write operation from system memory by a bus master
> +  //
> +  EfiVirtIoOperationBusMasterWrite,

(3) s/from/to/

> +  //
> +  // Provides both read and write access to system memory by both the
> +  // processor and a bus master
> +  //
> +  EfiVirtIoOperationBusMasterCommonBuffer,
> +  EfiVirtIoOperationMaximum
> +} VIRTIO_MAP_OPERATION;
> +

(4) Please drop the "Efi" prefix.

(5) Please replace the remaining "VirtIo" prefix with "Virtio". Although
you can find both spellings in the source code, they are used in
different contexts. In function names and enumeration constants, we've
used Virtio* thus far, as far as I can see.

I hope this won't cause too much churn for the series!

>  /**
>  
>    Read a word from the device-specific I/O region of the Virtio Header.
> @@ -319,6 +340,100 @@ EFI_STATUS
>    IN UINT8                   DeviceStatus
>    );
>  
> +/**
> +
> +  Allocates pages that are suitable for sharing between guest and hypervisor.
> +
> +  @param  This                  The protocol instance pointer.
> +  @param  Pages                 The number of pages to allocate.
> +  @param  HostAddress           A pointer to store the base system memory
> +                                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
> +  );

The typedef / function prototype looks good. Some comments for the
comment block:

(6) s/base system memory address/system memory base address/, I'd think;
but I could be convinced otherwise

(7) Please annotate each @param with: [in], [out], or [in,out], as
appropriate (see other examples in the same header file).

(This affects the rest of the members added in this patch.

It also likely affects all three implementations of this set of members
(via copy-pasted comment blocks).)

> +
> +/**
> +  Frees memory that was allocated with SharedAllocateBuffer().

(8) s/SharedAllocateBuffer()/VIRTIO_ALLOCATE_SHARED/

> +
> +  @param  This           The protocol instance pointer.
> +  @param  Pages          The number of pages to free.
> +  @param  HostAddress    The base system memory address of the allocated range.

(9) Whatever you do for comment (6), please apply it here as well.

> +
> +**/
> +typedef
> +VOID
> +(EFIAPI *VIRTIO_FREE_SHARED)(
> +  IN  VIRTIO_DEVICE_PROTOCOL                   *This,
> +  IN  UINTN                                    Pages,
> +  IN  VOID                                     *HostAddress
> +  );
> +
> +/**
> +  Provides the shared addresses required to access system memory from a
> +  DMA bus master.

(10) what do you think of s/shared addresses/device address/, singular?
(Also, replace "shared" with "virtio device" or just "device" below?)
Just an idea.

> +
> +  @param  This                    The protocol instance pointer.
> +  @param  Operation               Indicates if the bus master is going to
> +                                  read or write to system memory.
> +  @param  HostAddress             The system memory address to map to shared
> +                                  buffer address.

(11) Please point out the connection between
VirtioOperationBusMasterCommonBuffer, VIRTIO_ALLOCATE_SHARED, and
HostAddress.

It doesn't have to be extremely verbose (feel free to steal and adapt
the woring of the PciIo chapter in the UEFI spec), but since this is a
protocol header file, we should say something about that connection.

It's also fine if you just add a pointer to the UEFI spec (spec version,
chapter/section, interface), and say "this interface follows the same
usage pattern".

> +  @param  NumberOfBytes           On input the number of bytes to map.
> +                                  On output the number of bytes that were
> +                                  mapped.
> +  @param  DeviceAddress           The resulting shared map address for the
> +                                  bus master to access the hosts HostAddress.
> +  @param  Mapping                 A resulting value to pass to Unmap().

(12) What do you think of: "a resulting token 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
> +  );
> +

Looks OK.

> +/**
> +  Completes the Map() operation and releases any corresponding resources.

(13) What do you think of s/Map()/VIRTIO_MAP_SHARED/?

> +
> +  @param  This                   The protocol instance pointer.
> +  @param  Mapping                The mapping value returned from Map().

(14) I suggest "the Mapping token output by VIRTIO_MAP_SHARED".

> +
> +  @retval EFI_SUCCESS            The range was unmapped.
> +  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by
> +                                 Map().

(15) s/value/token/

(16) Please remind the reader that the implementation is not required to
recognize and report all such cases. Invalid Mapping tokens 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
> +  );

OK.

(In general I'm not sure if I like EFI_STATUS as return type here. I
would prefer VOID, I think -- my guess is that the rest of the patch set
will ignore the return value anywayy:
- EFI_SUCCESS fits VOID obviously.
- EFI_INVALID_PARAMETER is fully preventable if the caller sticks with
  the valid use pattern (and if they don't they can get undefined
  behavior anyway).

The only reason I think we should still keep the EFI_STATUS return type
on the interface level is that Unmap() might do actual data movement
after BusMasterWrite. Before client code consumes such data, the client
code should really check whether Unmap() succeeded (i.e., see the
EFI_DEVICE_ERROR case).

So, I guess let's keep the EFI_STATUS return type. (And check the
returns status everywhere in this series, wherever appropriate.)

>  
>  ///
>  ///  This protocol provides an abstraction over the VirtIo transport layer
> @@ -353,6 +468,12 @@ struct _VIRTIO_DEVICE_PROTOCOL {
>    // Functions to read/write Device Specific headers
>    VIRTIO_DEVICE_WRITE         WriteDevice;
>    VIRTIO_DEVICE_READ          ReadDevice;
> +
> +  // Function to allocate, free, map and unmap shared buffer

(17) s/Function/Functions/, plural

(18) I realize the current comments in this structure don't conform to
the coding style. Can you perhaps prepend a patch that fixes the comment
style for the following:

// VirtIo Specification Revision: ...

  /// VirtIo Specification Revision encoded with VIRTIO_SPEC_REVISION()

  /// From the Virtio Spec

  // Functions to read/write Device Specific headers

They should all be spelled

//
// comment
//

(There is no general need to prefix or suffix such comments with
additional empty lines -- use your judgement. In actual code, the empty
lines are helpful; between fields of a structure, not necessarily.)

(19) and then please adapt the new comment in this patch.

(20) This is actually for the commit message, but I'm too lazy to
renumber my points :) In the commit message, please state that:

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".

Thanks!
Laszlo

> +  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] 42+ messages in thread

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (13 preceding siblings ...)
  2017-08-07 11:58 ` [PATCH v1 14/14] OvmfPkg/VirtioRngDxe: Use DeviceAddresses in " Brijesh Singh
@ 2017-08-09 14:39 ` Laszlo Ersek
  2017-08-09 17:35   ` Brijesh Singh
  2017-08-09 22:38 ` Laszlo Ersek
  15 siblings, 1 reply; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-09 14:39 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/07/17 13:58, Brijesh Singh wrote:
> 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 - 3:
>  Defines and implements new member functions to map a system physical address
>  to device address. The patch implements Laszlo's suggestion [1].

(1) I guess under [1] you meant the following message:

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

If you want, you can add that link to the commit message of patch #1.

(2) But, that's not my main point here. Before I forget, I'd like to
point out that you missed one of the three virtio protocol
implementations -- see my point (5.4) in the above-referenced message
--, namely:

> - "ArmVirtPkg/VirtioFdtDxe" (via
>   "OvmfPkg/Library/VirtioMmioDeviceLib") binds virtio-mmio devices,
>    and offers virtio 0.9.5 semantics.

So please replicate patch v1 03/14 to
"OvmfPkg/Library/VirtioMmioDeviceLib". Otherwise, the modified virtio
device drivers will crash when they are built for ArmVirtPkg and used
over virtio-mmio transports.

(3) Starting with your v2, please add a reminder to your blurb -- for
Ard and myself -- that before merging this, we should regression-test it
on aarch64.

Thanks!
Laszlo

> 
> Patch 4 - 7:
>  Allocates the vring buffer using newly added member functions and provides
>  some helper functions.
> 
> Patch 8:
>  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
> 
> Patch 9:
>  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 \
> 
> Patch 10 - 13:
>  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=
> 
> Patch 14:
>  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
> 
>  And succesfully ran RngTest.efi from SecurityPkg/Application
> 
> Repo: https://github.com/codomania/edk2
> Branch: virtio-support
> 
> 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>
> 
> Brijesh Singh (14):
>   OvmfPkg/Virtio: Introduce new member functions in
>     VIRTIO_DEVICE_PROTOCOL
>   OvmfPkg/Virtio10Dxe: Implement new member functions
>   OvmfPkg/VirtioPciDeviceDxe: Implement new member functions
>   OvmfPkg/VirtioLib: Add SharedBuffer helper functions
>   OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit()
>   OvmfPkg/VirtioLib: Add functions to map/unmap VRING
>   OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer
>   OvmfPkg/VirtioBlkDxe: Use DeviceAddresses in vring descriptors
>   OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors
>   OvmfPkg/VirtioNetDxe: Allocate Tx and Rx ring using
>     AllocateSharedPage()
>   OvmfPkg/VirtioNetDxe: Allocate RxBuf using AllocateSharedPages()
>   OvmfPkg/VirtioNetDxe: Dynamically allocate transmit header
>   OvmfPkg/VirtioNetDxe: Use DeviceAddress in transmit vring descriptors
>   OvmfPkg/VirtioRngDxe: Use DeviceAddresses in vring descriptors
> 
>  OvmfPkg/Include/Library/VirtioLib.h             | 198 ++++++++++++-
>  OvmfPkg/Include/Protocol/VirtioDevice.h         | 121 ++++++++
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.h                |   1 +
>  OvmfPkg/VirtioNetDxe/VirtioNet.h                |  25 +-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h    |  34 +++
>  OvmfPkg/VirtioRngDxe/VirtioRng.h                |   1 +
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.h              |   1 +
>  OvmfPkg/Library/VirtioLib/VirtioLib.c           | 296 +++++++++++++++++++-
>  OvmfPkg/Virtio10Dxe/Virtio10.c                  | 114 +++++++-
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.c                | 104 ++++++-
>  OvmfPkg/VirtioGpuDxe/Commands.c                 |   7 +-
>  OvmfPkg/VirtioNetDxe/Events.c                   |  24 ++
>  OvmfPkg/VirtioNetDxe/SnpGetStatus.c             |  19 +-
>  OvmfPkg/VirtioNetDxe/SnpInitialize.c            | 102 +++++--
>  OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c         | 119 +++++++-
>  OvmfPkg/VirtioNetDxe/SnpShutdown.c              |  16 +-
>  OvmfPkg/VirtioNetDxe/SnpTransmit.c              |  22 +-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c    |   7 +-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c |  66 +++++
>  OvmfPkg/VirtioRngDxe/VirtioRng.c                |  54 +++-
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.c              | 121 +++++++-
>  21 files changed, 1378 insertions(+), 74 deletions(-)
> 



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

* Re: [PATCH v1 02/14] OvmfPkg/Virtio10Dxe: Implement new member functions
  2017-08-07 11:58 ` [PATCH v1 02/14] OvmfPkg/Virtio10Dxe: Implement new member functions Brijesh Singh
@ 2017-08-09 16:50   ` Laszlo Ersek
  0 siblings, 0 replies; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-09 16:50 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

(1) For the subject, I suggest again

    OvmfPkg/Virtio10Dxe: Implement IOMMU-like member functions

On 08/07/17 13:58, Brijesh Singh wrote:
> The patch implements the newly added member functions by respectively
> delegating the job to:
>
> - EFI_PCI_IO_PROTOCOL.AllocateBuffer() -- with BootServicesData
> - EFI_PCI_IO_PROTOCOL.FreeBuffer()
> - EFI_PCI_IO_PROTOCOL.Map()
> - EFI_PCI_IO_PROTOCOL.Unmap()

(2) looks good, but please spell out the new virtio protocol member
    names as well. (This will become more important in the commit
    message of the next patch, where the reader has to guess what member
    functions exactly get the "no-op" implementation.)

    And then we should be consistent in the commit messages.

>
> 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 | 114 +++++++++++++++++++-
>  1 file changed, 113 insertions(+), 1 deletion(-)
>
> diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c
> index a8a6a58c3f1d..5bc8f1c7ee27 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
> @@ -772,6 +773,113 @@ 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,
> +                         0

(3) We should pass Attributes=EFI_PCI_ATTRIBUTE_MEMORY_CACHED, even if
    only for cosmetic purposes (at the moment).

(4) Independently, this makes me think about
    EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE.

    * PciIoAllocateBuffer() [MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c]
      sets the EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE attribute
      internally, before calling out to the PCI Root Bridge IO Protocol,
      *if* "PciIoDevice->Attributes" has
      EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE set.

      In turn:

      - If there is an IOMMU protocol in the system, then
        RootBridgeIoAllocateBuffer()
        [MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c] passes
        EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE through to the IOMMU
        protocol's AllocateBuffer() member *if* "RootBridge->DmaAbove4G"
        is set. Otherwise the DUAL_ADDRESS_CYCLE hint is cleared.

        (EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE has the same numeric
        value, 0x8000, as EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE.)

      - If there is no IOMMU protocol in the system, then
        RootBridgeIoAllocateBuffer() itself allocates memory, again
        obeying  EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE and
        "RootBridge->DmaAbove4G".

      So regardless of whether there is an IOMMU protocol in the system
      or not, on the PCI Root Bridge IO level, 64-bit AllocateBuffer()
      is be permitted according to device-level DUAL_ADDRESS_CYCLE *AND*
      root-bridge-level DmaAbove4G.

    * Let's consider what's going to happen if we convert the virtio
      drivers to the new virtio proto member functions, and (in
      addition) Virtio10Dxe is converted to explicit
      PciIo.AllocateBuffer():

      - In OvmfPkg, allocations that used to be plain AllocatePool() or
        AllocatePages(), will be restricted to 32-bit, due to two
        reasons (either of which is sufficient in this regard):

        - In "OvmfPkg/Library/PciHostBridgeLib", we clear DmaAbove4G,
          for hysterical raisins.

        - In Virtio10Dxe, we don't set
          EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE.

      - In ArmVirtPkg, allocations that used to be plain AllocatePool()
        or AllocatePages(), will also be restricted to 32-bit. While
        "ArmVirtPkg/Library/FdtPciHostBridgeLib" *sets* DmaAbove4G, lack
        of EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE in Virtio10Dxe alone
        is suffices to trigger the restriction.

    * Therefore, please extend this patch with the following: in the
      Virtio10BindingStart() function [OvmfPkg/Virtio10Dxe/Virtio10.c],
      please replace

        SetAttributes = 0;

      with

        SetAttributes = EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;

      It will not help OvmfPkg, but it will keep the 4GB restriction out
      of ArmVirtPkg. (I'm unsure if we can simply flip "DmaAbove4G" to
      TRUE in OvmfPkg.)

    * (In the past, Ard wrote a number of similar patches for physical
      device drivers:

        167c3fb45674 MdeModulePkg/EhciDxe: enable 64-bit PCI DMA
        4e28ea2c29e0 MdeModulePkg/NvmExpressDxe: enable 64-bit PCI DMA
        df0a0e4b6fae MdeModulePkg/SdMmcPciHcDxe: enable 64-bit PCI DMA
        5c1b371a8839 MdeModulePkg/XhciDxe: enable 64-bit PCI DMA
        e58a71d9c50b MdeModulePkg/PciHostBridgeDxe: restrict 64-bit DMA
                     to devices that support it
        4c0b2d25c61c ArmVirtPkg/FdtPciHostBridgeLib: enable 64-bit PCI
                     DMA

      and that's what we should do here, in separate patches, for the
      virtio-pci transport drivers.)

(5) Looking more at the PciIo attribute setting in both virtio-PCI
    transport drivers, it seems that I failed to set
    EFI_PCI_IO_ATTRIBUTE_BUS_MASTER in both. Virtio devices read and
    write guest RAM (they don't just decode their IO and/or MMIO BARs),
    which translates to "bus master".

    So, please clean up my mess :) , and prepend two separate patches to
    the series:

    - "OvmfPkg/VirtioPciDeviceDxe: supply missing BUS_MASTER attribute"

      Please change

        EFI_PCI_IO_ATTRIBUTE_IO

      to

        EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER

      in VirtioPciDeviceBindingStart()
      [OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c].

    - "OvmfPkg/Virtio10Dxe: supply missing BUS_MASTER attribute"

      Please change

        SetAttributes = 0;

      to

        SetAttributes = EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;

      in Virtio10BindingStart() [OvmfPkg/Virtio10Dxe/Virtio10.c].

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

Okay, summary of points (3), (4) and (5):

- please prepend *two* patches, setting EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
  in each virtio-pci transport driver -- point (5)

- please set EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE in the modern-only
  driver, in this patch -- point (4)

- please pass Attributes=EFI_PCI_ATTRIBUTE_MEMORY_CACHED to
  Dev->PciIo->AllocateBuffer(), in this patch -- point (3).

Phew, this is complex. :)

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

Looks OK.

> +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
> +  //
> +  if (Operation == EfiVirtIoOperationBusMasterRead) {
> +    PciIoOperation = EfiPciIoOperationBusMasterRead;
> +  } else if (Operation == EfiVirtIoOperationBusMasterWrite) {
> +    PciIoOperation = EfiPciIoOperationBusMasterWrite;
> +  } else if (Operation == EfiVirtIoOperationBusMasterCommonBuffer) {
> +    PciIoOperation = EfiPciIoOperationBusMasterCommonBuffer;
> +  } else {
> +    return EFI_UNSUPPORTED;
> +  }

(6) This mapping lends itself to simplification by virtue of a switch
    statement. (Please remember that the "case" labels are indented
    *zero* positions relative to the "switch" keyword.)

(7) Rather than EFI_UNSUPPORTED, EFI_INVALID_PARAMETER should be
    returned ("One or more parameters are invalid.")

(8) You don't seem to be using "VirtioOperationMaximum" for range
    checking (that's fine, with the switch we can check each value
    individually, and then add a "default" case) -- please consider
    removing VirtioOperationMaximum from the protocol interface then.


Regarding 64-bit transparency: this code is good, as long as we cover
point (4) above:

- EFI_PCI_IO_PROTOCOL_OPERATION has no separate 32-bit and 64-bit
  constants,

- EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION does make such a
  distinction,

- PciIoMap() in "MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c" shifts the
  former op constants up to the 64-bit latter op constants, if
  EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE is enabled for the device
  (hence my reference to (4)).

The rest also looks good.

Thanks,
Laszlo

> +
> +  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 +896,11 @@ STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = {
>    Virtio10GetDeviceStatus,
>    Virtio10SetDeviceStatus,
>    Virtio10WriteDevice,
> -  Virtio10ReadDevice
> +  Virtio10ReadDevice,
> +  Virtio10AllocateSharedPages,
> +  Virtio10FreeSharedPages,
> +  Virtio10MapSharedBuffer,
> +  Virtio10UnmapSharedBuffer
>  };
>
>
>



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

* Re: [PATCH v1 03/14] OvmfPkg/VirtioPciDeviceDxe: Implement new member functions
  2017-08-07 11:58 ` [PATCH v1 03/14] OvmfPkg/VirtioPciDeviceDxe: " Brijesh Singh
@ 2017-08-09 17:09   ` Laszlo Ersek
  2017-08-10 18:41     ` Brijesh Singh
  0 siblings, 1 reply; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-09 17:09 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/07/17 13:58, Brijesh Singh wrote:
> The patch implements the newly added member functions by respectively
> delegating the job to:
> 
> - MemoryApplicationLib.AllocatePages () -- with BootServicesData
> - MemoryApplicationLib.FreePages ()
> - no-op (host address is same as device DMA address)
> - no-op

(1) (2) Please see points (1) and (2) in my "PATCH v1 02/14" feedback.

(3) s/Application/Allocation/

(4) the "with BootServicesData" remark is not needed after the
MemoryAllocationLib.AllocatePages() reference. MemoryAllocationLib
encodes the memory type in the API names. So you have AllocatePool /
AllocatePages, AllocateReservedPool / AllocateReservedPages,
AllocateRuntimePool / AllocateRuntimePages, etc.

Please see the lib class header

MdePkg/Include/Library/MemoryAllocationLib.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/VirtioPciDeviceDxe/VirtioPciDevice.h    | 34 ++++++++++
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c    |  7 ++-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c | 66 ++++++++++++++++++++
>  3 files changed, 106 insertions(+), 1 deletion(-)
> 
> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
> index 8f17a16c88f5..da98de123000 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 (
>    UINT8                          DeviceStatus
>    );
>  
> +EFI_STATUS
> +EFIAPI
> +VirtioPciAllocateSharedPages (
> +  VIRTIO_DEVICE_PROTOCOL        *This,
> +  UINTN                         NumPages,
> +  VOID                          **HostAddress
> +  );
> +
> +VOID
> +EFIAPI
> +VirtioPciFreeSharedPages (
> +  VIRTIO_DEVICE_PROTOCOL        *This,
> +  UINTN                         NumPages,
> +  VOID                          *HostAddress
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioPciMapSharedBuffer (
> +  VIRTIO_DEVICE_PROTOCOL        *This,
> +  VIRTIO_MAP_OPERATION          Operation,
> +  VOID                          *HostAddress,
> +  UINTN                         *NumberOfBytes,
> +  EFI_PHYSICAL_ADDRESS          *DeviceAddress,
> +  VOID                          **Mapping
> +  );
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioPciUnmapSharedBuffer (
> +  VIRTIO_DEVICE_PROTOCOL        *This,
> +  VOID                          *Mapping
> +  );
>  #endif // _VIRTIO_PCI_DEVICE_DXE_H_
> diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
> index bc4f6fe8bfa3..4e4e21d9a477 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 243aa14c2421..1c587e184311 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,68 @@ VirtioPciSetDeviceStatus (
>    return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
>        sizeof (UINT8), DeviceStatus);
>  }
> +
> +EFI_STATUS
> +EFIAPI
> +VirtioPciAllocateSharedPages (
> +  VIRTIO_DEVICE_PROTOCOL  *This,
> +  UINTN                   NumPages,
> +  VOID                    **HostAddress
> +  )
> +{
> +  EFI_STATUS              Status;
> +  EFI_PHYSICAL_ADDRESS    PhysicalAddress;
> +
> +  Status = gBS->AllocatePages (
> +                  AllocateAnyPages,
> +                  EfiBootServicesData,
> +                  NumPages,
> +                  &PhysicalAddress
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    *HostAddress = (VOID *) (UINTN) PhysicalAddress;
> +  }
> +
> +  return Status;
> +}

(5) We might want do what we promise in the commit message :) Namely,
use MemoryAllocationLib APIs (for simplicity), rather than boot
services. Such as:

  VOID *Buffer;

  Buffer = AllocatePages (NumPages);
  if (Buffer == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  *HostAddress = Buffer;
  return EFI_SUCCESS;

> +
> +VOID
> +EFIAPI
> +VirtioPciFreeSharedPages (
> +  VIRTIO_DEVICE_PROTOCOL  *This,
> +  UINTN                   NumPages,
> +  VOID                    *HostAddress
> +  )
> +{
> +  gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN)HostAddress, NumPages);
> +}

(6) Similarly:

  FreePages (HostAddress, NumPages);

> +
> +EFI_STATUS
> +EFIAPI
> +VirtioPciMapSharedBuffer (
> +  VIRTIO_DEVICE_PROTOCOL  *This,
> +  VIRTIO_MAP_OPERATION    Operation,
> +  VOID                    *HostAddress,
> +  UINTN                   *NumberOfBytes,
> +  EFI_PHYSICAL_ADDRESS    *DeviceAddress,
> +  VOID                    **Mapping
> +  )
> +{
> +  EFI_PHYSICAL_ADDRESS    PhysicalAddress;
> +
> +  PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
> +
> +  *DeviceAddress = PhysicalAddress;
> +
> +  return EFI_SUCCESS;
> +}

(7) We could condense it to a single assignment to *DeviceAddress. Up to
you.

(8) Please set *Mapping to NULL -- let's not cause the future caller of
Unmap() to evaluate (for argument passing) a pointer with garbage
contents at that point; that's undefined behavior in itself, at least in
theory.

> +
> +EFI_STATUS
> +EFIAPI
> +VirtioPciUnmapSharedBuffer (
> +  VIRTIO_DEVICE_PROTOCOL    *This,
> +  VOID                      *Mapping
> +  )
> +{
> +  return EFI_SUCCESS;
> +}
> 

(9) Please refresh the function signatures in both "VirtioPciDevice.h"
and "VirtioPciFunctions.c", from the protocol definition in
"OvmfPkg/Include/Protocol/VirtioDevice.h".

In particular, all the IN and OUT decoration is missing here.

To be continued.

Thanks,
Laszlo


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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-09 14:39 ` [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Laszlo Ersek
@ 2017-08-09 17:35   ` Brijesh Singh
  2017-08-09 17:56     ` Laszlo Ersek
  0 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-09 17:35 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Tom Lendacky, Ard Biesheuvel



On 08/09/2017 09:39 AM, Laszlo Ersek wrote:
> On 08/07/17 13:58, Brijesh Singh wrote:
>> 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 - 3:
>>   Defines and implements new member functions to map a system physical address
>>   to device address. The patch implements Laszlo's suggestion [1].
> 
> (1) I guess under [1] you meant the following message:
> 
> http://mid.mail-archive.com/841bec5f-6f6e-8b1f-25ba-0fd37a915b72@redhat.com
> 

Yes, thank you :) I did not realized that I forgot adding the link.


> If you want, you can add that link to the commit message of patch #1.
> 
> (2) But, that's not my main point here. Before I forget, I'd like to
> point out that you missed one of the three virtio protocol
> implementations -- see my point (5.4) in the above-referenced message
> --, namely:
> 
>> - "ArmVirtPkg/VirtioFdtDxe" (via
>>    "OvmfPkg/Library/VirtioMmioDeviceLib") binds virtio-mmio devices,
>>     and offers virtio 0.9.5 semantics.
> 
> So please replicate patch v1 03/14 to
> "OvmfPkg/Library/VirtioMmioDeviceLib". Otherwise, the modified virtio
> device drivers will crash when they are built for ArmVirtPkg and used
> over virtio-mmio transports.
> 

Sure, I will make the necessary changes in VirtioMmioDeviceLib and try
do the build test but I don't have aarch64 platform to verify at the
runtime.

> (3) Starting with your v2, please add a reminder to your blurb -- for
> Ard and myself -- that before merging this, we should regression-test it
> on aarch64.
> 

Will do


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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-09 17:35   ` Brijesh Singh
@ 2017-08-09 17:56     ` Laszlo Ersek
  2017-08-09 19:29       ` Laszlo Ersek
  2017-08-11 22:22       ` Brijesh Singh
  0 siblings, 2 replies; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-09 17:56 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/09/17 19:35, Brijesh Singh wrote:
> 
> 
> On 08/09/2017 09:39 AM, Laszlo Ersek wrote:
>> On 08/07/17 13:58, Brijesh Singh wrote:
>>> 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 - 3:
>>>   Defines and implements new member functions to map a system
>>> physical address
>>>   to device address. The patch implements Laszlo's suggestion [1].
>>
>> (1) I guess under [1] you meant the following message:
>>
>> http://mid.mail-archive.com/841bec5f-6f6e-8b1f-25ba-0fd37a915b72@redhat.com
>>
>>
> 
> Yes, thank you :) I did not realized that I forgot adding the link.
> 
> 
>> If you want, you can add that link to the commit message of patch #1.
>>
>> (2) But, that's not my main point here. Before I forget, I'd like to
>> point out that you missed one of the three virtio protocol
>> implementations -- see my point (5.4) in the above-referenced message
>> --, namely:
>>
>>> - "ArmVirtPkg/VirtioFdtDxe" (via
>>>    "OvmfPkg/Library/VirtioMmioDeviceLib") binds virtio-mmio devices,
>>>     and offers virtio 0.9.5 semantics.
>>
>> So please replicate patch v1 03/14 to
>> "OvmfPkg/Library/VirtioMmioDeviceLib". Otherwise, the modified virtio
>> device drivers will crash when they are built for ArmVirtPkg and used
>> over virtio-mmio transports.
>>
> 
> Sure, I will make the necessary changes in VirtioMmioDeviceLib and try
> do the build test but I don't have aarch64 platform to verify at the
> runtime.

Actually, dependent on your GNU/Linux distribution, it is pretty easy to
do on x86_64 too. It comes together from two parts:

(1) installing an aarch64 cross compiler
(2) installing qemu-system-aarch64 (from source or distro package),
    and then either using it directly (from the cmdline) or with the
    libvirt toolstack

The only "real" difference is that it's going to use TCG and not KVM
(software emulation rather than hardware virtualization), so it will be
slower, but that's not really a problem if you only care about your VM
until the firmware boots the OS :)

On Fedora, the cross-compiler (and cross-binutils) packages are built
from the following SRPMs:

  https://koji.fedoraproject.org/koji/buildinfo?buildID=921790
  https://koji.fedoraproject.org/koji/buildinfo?buildID=912429

("cross-gcc", "cross-binutils")

Linaro distributes distro-independent cross compilers:

  http://www.linaro.org/downloads/

Build instructions for ArmVirtQemu, and usage hints for the QEMU command
line, can be found in the Linaro Wiki:

  https://wiki.linaro.org/LEG/UEFIforQEMU

Thanks
Laszlo

>> (3) Starting with your v2, please add a reminder to your blurb -- for
>> Ard and myself -- that before merging this, we should regression-test it
>> on aarch64.
>>
> 
> Will do



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

* Re: [PATCH v1 01/14] OvmfPkg/Virtio: Introduce new member functions in VIRTIO_DEVICE_PROTOCOL
  2017-08-09 14:27   ` Laszlo Ersek
@ 2017-08-09 18:23     ` Brijesh Singh
  0 siblings, 0 replies; 42+ messages in thread
From: Brijesh Singh @ 2017-08-09 18:23 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Tom Lendacky, Ard Biesheuvel



On 08/09/2017 09:27 AM, Laszlo Ersek wrote:
> On 08/07/17 13:58, 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().
>>
>> 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 | 121 ++++++++++++++++++++
>>   1 file changed, 121 insertions(+)
> 
> (1) I suggest the following subject:
> 
> OvmfPkg: introduce IOMMU-like member functions to VIRTIO_DEVICE_PROTOCOL
> 
> The current wording "new member functions" is a bit too generic IMO.
> 


Will do.

>>
>> diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h
>> index 910a4866e7ac..ea5272165389 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,26 @@
>>   
>>   typedef struct _VIRTIO_DEVICE_PROTOCOL  VIRTIO_DEVICE_PROTOCOL;
>>   
>> +//
>> +// VIRTIO Operation for Map
>> +//
> 
> (2) "Map" can be made a bit more precise; please say either
> "VIRTIO_MAP_SHARED" or MapSharedBuffer().
> 

Will do

>> +typedef enum {
>> +  //
>> +  // A read operation from system memory by a bus master
>> +  //
>> +  EfiVirtIoOperationBusMasterRead,
>> +  //
>> +  // A write operation from system memory by a bus master
>> +  //
>> +  EfiVirtIoOperationBusMasterWrite,
> 
> (3) s/from/to/
> 

Will update it. thanks

>> +  //
>> +  // Provides both read and write access to system memory by both the
>> +  // processor and a bus master
>> +  //
>> +  EfiVirtIoOperationBusMasterCommonBuffer,
>> +  EfiVirtIoOperationMaximum
>> +} VIRTIO_MAP_OPERATION;
>> +
> 
> (4) Please drop the "Efi" prefix.
> 
> (5) Please replace the remaining "VirtIo" prefix with "Virtio". Although
> you can find both spellings in the source code, they are used in
> different contexts. In function names and enumeration constants, we've
> used Virtio* thus far, as far as I can see.
> 
> I hope this won't cause too much churn for the series!
> 

I was actually trying to follow the IOMMU protocol header file, but I will
drop the Efi Prefix and also fix the "Virtio" prefix.

Drivers don't use these macro's directly, I have a helper function in Patch 4
to map the shared buffers. Depending on your feedback on Patch #4, it may not
be bad change at all. If we don't want those helper functions from patch 4 then
I will anyway have to update the drivers. In summary, I will make the suggested
changes in v2.



>>   /**
>>   
>>     Read a word from the device-specific I/O region of the Virtio Header.
>> @@ -319,6 +340,100 @@ EFI_STATUS
>>     IN UINT8                   DeviceStatus
>>     );
>>   
>> +/**
>> +
>> +  Allocates pages that are suitable for sharing between guest and hypervisor.
>> +
>> +  @param  This                  The protocol instance pointer.
>> +  @param  Pages                 The number of pages to allocate.
>> +  @param  HostAddress           A pointer to store the base system memory
>> +                                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
>> +  );
> 
> The typedef / function prototype looks good. Some comments for the
> comment block:
> 
> (6) s/base system memory address/system memory base address/, I'd think;
> but I could be convinced otherwise
> 
> (7) Please annotate each @param with: [in], [out], or [in,out], as
> appropriate (see other examples in the same header file).
> 
> (This affects the rest of the members added in this patch.
> 
> It also likely affects all three implementations of this set of members
> (via copy-pasted comment blocks).)
> 

I will fix those, I was doing copy/paste of these functions from
MdeModules/Include/Protocol/IoMmu.h hence missed updating the annotate of
each param.

>> +
>> +/**
>> +  Frees memory that was allocated with SharedAllocateBuffer().
> 
> (8) s/SharedAllocateBuffer()/VIRTIO_ALLOCATE_SHARED/
> 

Will do thanks

>> +
>> +  @param  This           The protocol instance pointer.
>> +  @param  Pages          The number of pages to free.
>> +  @param  HostAddress    The base system memory address of the allocated range.
> 
> (9) Whatever you do for comment (6), please apply it here as well.
> 

Will do

>> +
>> +**/
>> +typedef
>> +VOID
>> +(EFIAPI *VIRTIO_FREE_SHARED)(
>> +  IN  VIRTIO_DEVICE_PROTOCOL                   *This,
>> +  IN  UINTN                                    Pages,
>> +  IN  VOID                                     *HostAddress
>> +  );
>> +
>> +/**
>> +  Provides the shared addresses required to access system memory from a
>> +  DMA bus master.
> 
> (10) what do you think of s/shared addresses/device address/, singular?
> (Also, replace "shared" with "virtio device" or just "device" below?)
> Just an idea.
> 

device address works for me, I will update it.

>> +
>> +  @param  This                    The protocol instance pointer.
>> +  @param  Operation               Indicates if the bus master is going to
>> +                                  read or write to system memory.
>> +  @param  HostAddress             The system memory address to map to shared
>> +                                  buffer address.
> 
> (11) Please point out the connection between
> VirtioOperationBusMasterCommonBuffer, VIRTIO_ALLOCATE_SHARED, and
> HostAddress.
> 
> It doesn't have to be extremely verbose (feel free to steal and adapt
> the woring of the PciIo chapter in the UEFI spec), but since this is a
> protocol header file, we should say something about that connection.
> 
> It's also fine if you just add a pointer to the UEFI spec (spec version,
> chapter/section, interface), and say "this interface follows the same
> usage pattern".
> 

Again this was basically copy/paste from IoMmu.h hence I did not put anything
regarding the VirtioOperationBusMasterCommonBuffer, I will mention the UEFI
spec version and section.

>> +  @param  NumberOfBytes           On input the number of bytes to map.
>> +                                  On output the number of bytes that were
>> +                                  mapped.
>> +  @param  DeviceAddress           The resulting shared map address for the
>> +                                  bus master to access the hosts HostAddress.
>> +  @param  Mapping                 A resulting value to pass to Unmap().
> 
> (12) What do you think of: "a resulting token to pass to
> VIRTIO_UNMAP_SHARED"?
> 

Works for me. thanks

>> +
>> +
>> +  @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
>> +  );
>> +
> 
> Looks OK.
> 
>> +/**
>> +  Completes the Map() operation and releases any corresponding resources.
> 
> (13) What do you think of s/Map()/VIRTIO_MAP_SHARED/?
> 

Works for me

>> +
>> +  @param  This                   The protocol instance pointer.
>> +  @param  Mapping                The mapping value returned from Map().
> 
> (14) I suggest "the Mapping token output by VIRTIO_MAP_SHARED".
> 

Will do

>> +
>> +  @retval EFI_SUCCESS            The range was unmapped.
>> +  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by
>> +                                 Map().
> 
> (15) s/value/token/
> 

Will do

> (16) Please remind the reader that the implementation is not required to
> recognize and report all such cases. Invalid Mapping tokens can cause
> undefined behavior.
> 

Will do

>> +  @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
>> +  );
> 
> OK.
> 
> (In general I'm not sure if I like EFI_STATUS as return type here. I
> would prefer VOID, I think -- my guess is that the rest of the patch set
> will ignore the return value anywayy:
> - EFI_SUCCESS fits VOID obviously.
> - EFI_INVALID_PARAMETER is fully preventable if the caller sticks with
>    the valid use pattern (and if they don't they can get undefined
>    behavior anyway).
> 
> The only reason I think we should still keep the EFI_STATUS return type
> on the interface level is that Unmap() might do actual data movement
> after BusMasterWrite. Before client code consumes such data, the client
> code should really check whether Unmap() succeeded (i.e., see the
> EFI_DEVICE_ERROR case).
> 
> So, I guess let's keep the EFI_STATUS return type. (And check the
> returns status everywhere in this series, wherever appropriate.)
> 

Okay lets make sure we check the status when required


>>   
>>   ///
>>   ///  This protocol provides an abstraction over the VirtIo transport layer
>> @@ -353,6 +468,12 @@ struct _VIRTIO_DEVICE_PROTOCOL {
>>     // Functions to read/write Device Specific headers
>>     VIRTIO_DEVICE_WRITE         WriteDevice;
>>     VIRTIO_DEVICE_READ          ReadDevice;
>> +
>> +  // Function to allocate, free, map and unmap shared buffer
> 
> (17) s/Function/Functions/, plural
> 

Will fix it

> (18) I realize the current comments in this structure don't conform to
> the coding style. Can you perhaps prepend a patch that fixes the comment
> style for the following:
> 

Sure will do

> // VirtIo Specification Revision: ...
> 
>    /// VirtIo Specification Revision encoded with VIRTIO_SPEC_REVISION()
> 
>    /// From the Virtio Spec
> 
>    // Functions to read/write Device Specific headers
> 
> They should all be spelled
> 
> //
> // comment
> //
> 
> (There is no general need to prefix or suffix such comments with
> additional empty lines -- use your judgement. In actual code, the empty
> lines are helpful; between fields of a structure, not necessarily.)
> 
> (19) and then please adapt the new comment in this patch.
> 
> (20) This is actually for the commit message, but I'm too lazy to
> renumber my points :) In the commit message, please state that:
> 
> 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".
> 

Sure, I will use the message in commit.

Thanks
Brijesh


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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-09 17:56     ` Laszlo Ersek
@ 2017-08-09 19:29       ` Laszlo Ersek
  2017-08-11 22:22       ` Brijesh Singh
  1 sibling, 0 replies; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-09 19:29 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Ard Biesheuvel, Tom Lendacky

On 08/09/17 19:56, Laszlo Ersek wrote:

> Build instructions for ArmVirtQemu, and usage hints for the QEMU command
> line, can be found in the Linaro Wiki:
> 
>   https://wiki.linaro.org/LEG/UEFIforQEMU

It's visible in the Wiki article, but I'd like to point it out
nevertheless, that you can select the virtio-mmio transport for a given
virtio device model by typing

  -device virtio-whatever-device

rather than

  -device virtio-whatever-pci

Thanks
Laszlo


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

* Re: [PATCH v1 04/14] OvmfPkg/VirtioLib: Add SharedBuffer helper functions
  2017-08-07 11:58 ` [PATCH v1 04/14] OvmfPkg/VirtioLib: Add SharedBuffer helper functions Brijesh Singh
@ 2017-08-09 20:30   ` Laszlo Ersek
  0 siblings, 0 replies; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-09 20:30 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/07/17 13:58, Brijesh Singh wrote:
> Patch adds convenience helper functions to call VIRTIO_DEVICE_PROTOCOL
> AllocateSharedPages, FreeSharedPages, MapSharedBuffer and UnmapSharedBuffer
> member functions.
> 
> 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   | 143 +++++++++++++
>  OvmfPkg/Library/VirtioLib/VirtioLib.c | 220 ++++++++++++++++++++
>  2 files changed, 363 insertions(+)

I prefer to add functions to VirtioLib that actually buy us something.
So let me evaluate that for each function:

> diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
> index 5badfb32917f..fa82734f1852 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,146 @@ Virtio10WriteFeatures (
>    IN OUT UINT8                  *DeviceStatus
>    );
>  
> +/**
> +  Helper function to allocate pages that is suitable for sharing with
> +  hypervisor.
> +
> +  @param[in]  VirtIo  The target virtio device to use. It must be valid.
> +
> +  @param[in]  Pages   The number of pages to allocate.
> +
> +  @param[out] Buffer  A pointer to store the base system memory address of
> +                      the allocated range.
> +
> +  return              Returns error code from VirtIo->AllocateSharedPages()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioAllocateSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  UINTN                   NumPages,
> +  OUT VOID                    **Buffer
> +  );
> +
> +/**
> +  Helper function to free pages allocated using VirtioAllocateSharedPages().
> +
> +  @param[in]  VirtIo  The target virtio device to use. It must be valid.
> +
> +  @param[in]  Pages   The number of allocated pages.
> +
> +  @param[in]  Buffer  System memory address allocated from
> +                      VirtioAllocateSharedPages ().
> +**/
> +VOID
> +EFIAPI
> +VirtioFreeSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  UINTN                   NumPages,
> +  IN  VOID                    *Buffer
> +  );
> +
> +/**
> +  A helper function to map a system memory to a shared bus master memory for
> +  read operation from DMA bus master.
> +
> +  @param[in]  VirtIo          The target virtio device to use. It must be
> +                              valid.
> +
> +  @param[in]  HostAddress     The system memory address to map to shared bus
> +                              master address.
> +
> +  @param[in]  NumberOfBytes   Number of bytes to be mapped.
> +
> +  @param[out] DeviceAddress   The resulting shared map address for the bus
> +                              master to access the hosts HostAddress.
> +
> +  @param[out] Mapping         A resulting value to pass to Unmap().
> +
> +  return                      Returns error code from
> +                              VirtIo->MapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioMapSharedBufferRead (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  VOID                    *HostAddress,
> +  IN  UINTN                   NumberOfBytes,
> +  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
> +  OUT VOID                    **Mapping
> +  );
> +
> +/**
> +  A helper function to map a system memory to a shared bus master memory for
> +  write operation from DMA bus master.
> +
> +  @param[in]  VirtIo          The target virtio device to use. It must be
> +                              valid.
> +
> +  @param[in]  HostAddress     The system memory address to map to shared bus
> +                              master address.
> +
> +  @param[in]  NumberOfBytes   Number of bytes to be mapped.
> +
> +  @param[out] DeviceAddress   The resulting shared map address for the bus
> +                              master to access the hosts HostAddress.
> +
> +  @param[out] Mapping         A resulting value to pass to Unmap().
> +
> +  return                      Returns error code from
> +                              VirtIo->MapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioMapSharedBufferWrite (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  VOID                    *HostAddress,
> +  IN  UINTN                   NumberOfBytes,
> +  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
> +  OUT VOID                    **Mapping
> +  );
> +
> +/**
> +  A helper function to map a system memory to a shared bus master memory for
> +  common operation from DMA bus master.
> +
> +  @param[in]  VirtIo          The target virtio device to use. It must be
> +                              valid.
> +
> +  @param[in]  HostAddress     The system memory address to map to shared bus
> +                              master address.
> +
> +  @param[in]  NumberOfBytes   Number of bytes to be mapped.
> +
> +  @param[out] Mapping         A resulting value to pass to Unmap().
> +
> +  return                      Returns error code from
> +                              VirtIo->MapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioMapSharedBufferCommon (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  VOID                    *HostAddress,
> +  IN  UINTN                   NumberOfBytes,
> +  OUT VOID                    **Mapping
> +  );
> +
> +/**
> +  A helper function to unmap shared bus master memory mapped using Map().
> +
> +  @param[in]  VirtIo          The target virtio device to use. It must be
> +                              valid.
> +
> +  @param[in] Mapping          A mapping value return from Map().
> +
> +  return                      Returns error code from
> +                              VirtIo->UnmapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioUnmapSharedBuffer (
> +  IN VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN VOID                    *Mapping
> +  );
>  #endif // _VIRTIO_LIB_H_
> diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
> index 845f206369a3..f6b464b6cdf8 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,222 @@ Virtio10WriteFeatures (
>  
>    return Status;
>  }
> +
> +/**
> +  Helper function to allocate pages that is suitable for sharing with
> +  hypervisor.
> +
> +  @param[in]  VirtIo  The target virtio device to use. It must be valid.
> +
> +  @param[in]  Pages   The number of pages to allocate.
> +
> +  @param[out] Buffer  A pointer to store the base system memory address of
> +                      the allocated range.
> +
> +  return              Returns error code from VirtIo->AllocateSharedPages()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioAllocateSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  UINTN                   NumPages,
> +  OUT VOID                    **Buffer
> +  )
> +{
> +  return VirtIo->AllocateSharedPages (VirtIo, NumPages, Buffer);
> +}

(1) I think this function buys us nothing. I suggest to drop it.

> +
> +/**
> +  Helper function to free pages allocated using VirtioAllocateSharedPages().
> +
> +  @param[in]  VirtIo  The target virtio device to use. It must be valid.
> +
> +  @param[in]  Pages   The number of allocated pages.
> +
> +  @param[in]  Buffer  System memory address allocated from
> +                      VirtioAllocateSharedPages ().
> +**/
> +VOID
> +EFIAPI
> +VirtioFreeSharedPages (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  UINTN                   NumPages,
> +  IN  VOID                    *Buffer
> +  )
> +{
> +  VirtIo->FreeSharedPages (VirtIo, NumPages, Buffer);
> +}

(2) Same here.

> +
> +STATIC
> +EFI_STATUS
> +VirtioMapSharedBuffer (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  VIRTIO_MAP_OPERATION    Operation,
> +  IN  VOID                    *HostAddress,
> +  IN  UINTN                   NumberOfBytes,
> +  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
> +  OUT VOID                    **Mapping
> +  )

(3) Please add a comment block above the function. Basically you can
copy the MapSharedBuffer() documentation, just point out the extra logic
for NumberOfBytes.

In fact, please rename this function to:

  VirtioMapAllBytesInSharedBuffer

> +{
> +  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);
> +  return EFI_OUT_OF_RESOURCES;
> +}

Now, I think this helper function does actually buy us convenience -- it
helps us centralize error handling, and it allows callers to pass in
constants or other evaluated expressions for NumberOfBytes.

I've given quite a bit of thought to our "hardliner" handling of the
case when NumberOfBytes is decreased on output. The PciIo spec says that
in such cases the transfer should be broken up into smaller chunks:

> In all mapping requests the resulting NumberOfBytes actually mapped
> may be less than the requested amount. In this case, the DMA operation
> will have to be broken up into smaller chunks. The Map() function will
> map as much of the DMA operation as it can at one time. The caller may
> have to loop on Map() and Unmap() in order to complete a large DMA
> transfer.

While generally speaking that could be a valid idea, I think it doesn't
apply well to virtio, for the following reasons:

- I don't think that CommonBuffer areas are possible to split up in any
sensible way (e.g., rings),

- Even for unidirectional transfers, the request framing is usually
dictated on the virtio request level (i.e., request framing is usually
matched closely by the individual virtio descriptors that constitute the
descriptor chain that *is* the virtio request). If PciIo (ultimately:
the IOMMU) "suggests" that we split the request into smaller chunks,
that could affect the descriptors / descriptor chaining too, and I
simply don't want to go there.

- Turning a single "outer request" (like EFI_BLOCK_IO_PROTOCOL read or
write request) into a series of "inner virtio requests" is a mess as
well -- what if you get a failure from the hypervisor mid-loop?

IMO, we should forward the outer (higher level) request as transparently
over virtio as possible. If the IOMMU limits that for whatever reason,
then we should fail the request immediately, and propagate the error to
the client of the higher level protocol.

So, IMO, the handling of NumberOfBytes is valid here, and this function
is useful.

(4) Please make this function extern (add it to the header file too).

> +
> +/**
> +  A helper function to map a system memory to a shared bus master memory for
> +  read operation from DMA bus master.
> +
> +  @param[in]  VirtIo          The target virtio device to use. It must be
> +                              valid.
> +
> +  @param[in]  HostAddress     The system memory address to map to shared bus
> +                              master address.
> +
> +  @param[in]  NumberOfBytes   Number of bytes to be mapped.
> +
> +  @param[out] DeviceAddress   The resulting shared map address for the bus
> +                              master to access the hosts HostAddress.
> +
> +  @param[out] Mapping         A resulting value to pass to Unmap().
> +
> +  return                      Returns error code from
> +                              VirtIo->MapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioMapSharedBufferRead (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  VOID                    *HostAddress,
> +  IN  UINTN                   NumberOfBytes,
> +  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
> +  OUT VOID                    **Mapping
> +  )
> +{
> +  return VirtioMapSharedBuffer (VirtIo, EfiVirtIoOperationBusMasterRead,
> +           HostAddress, NumberOfBytes, DeviceAddress, Mapping);
> +}

(5) I don't think this function buys us much. The only parameter you can
save at the call site is Operation, but the rest (together with the
saving of the return code) will require so many characters still that
you'll have to break it to multiple lines anyway. So I suggest to drop
this function.

> +
> +/**
> +  A helper function to map a system memory to a shared bus master memory for
> +  write operation from DMA bus master.
> +
> +  @param[in]  VirtIo          The target virtio device to use. It must be
> +                              valid.
> +
> +  @param[in]  HostAddress     The system memory address to map to shared bus
> +                              master address.
> +
> +  @param[in]  NumberOfBytes   Number of bytes to be mapped.
> +
> +  @param[out] DeviceAddress   The resulting shared map address for the bus
> +                              master to access the hosts HostAddress.
> +
> +  @param[out] Mapping         A resulting value to pass to Unmap().
> +
> +  return                      Returns error code from
> +                              VirtIo->MapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioMapSharedBufferWrite (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  VOID                    *HostAddress,
> +  IN  UINTN                   NumberOfBytes,
> +  OUT EFI_PHYSICAL_ADDRESS    *DeviceAddress,
> +  OUT VOID                    **Mapping
> +  )
> +{
> +  return VirtioMapSharedBuffer (VirtIo, EfiVirtIoOperationBusMasterWrite,
> +           HostAddress, NumberOfBytes, DeviceAddress, Mapping);
> +}

(6) Same as (5) here.

> +
> +/**
> +  A helper function to map a system memory to a shared bus master memory for
> +  common operation from DMA bus master.
> +
> +  @param[in]  VirtIo          The target virtio device to use. It must be
> +                              valid.
> +
> +  @param[in]  HostAddress     The system memory address to map to shared bus
> +                              master address.
> +
> +  @param[in]  NumberOfBytes   Number of bytes to be mapped.
> +
> +  @param[out] Mapping         A resulting value to pass to Unmap().
> +
> +  return                      Returns error code from
> +                              VirtIo->MapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioMapSharedBufferCommon (
> +  IN  VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN  VOID                    *HostAddress,
> +  IN  UINTN                   NumberOfBytes,
> +  OUT VOID                    **Mapping
> +  )
> +{
> +  EFI_STATUS            Status;
> +  EFI_PHYSICAL_ADDRESS  DeviceAddress;
> +
> +  Status = VirtioMapSharedBuffer (VirtIo,
> +             EfiVirtIoOperationBusMasterCommonBuffer, HostAddress,
> +             NumberOfBytes, &DeviceAddress, Mapping);
> +
> +  //
> +  // On Success, lets verify that DeviceAddress same as HostAddress
> +  //
> +  if (!EFI_ERROR (Status)) {
> +    ASSERT (DeviceAddress == (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress);
> +  }
> +
> +  return Status;
> +}

So this function seems to save us two parameters:

(7) Operation -- I commented on that under (5).

(8) DeviceAddress -- I actually disagree with hiding that. In my
opinion, this is different from the NumberOfBytes question.

We can be inflexible with NumberOfBytes because the in-out NumberOfBytes
parameter of PciIo.Map() reflects an *accidental* trait of some IOMMUs
(namely that their map sizes may be limited). I think that in the virtio
scope we can safely say that we simply don't support IOMMU protocol
instances that can't accommodate our desired request framing.

(Case in point: versions of the virtio spec have presented limits on
virtio request sizes, and thus the virtio drivers already enforce
suitable (stricter) limits on the outer protocol interfaces. Search
"VirtioBlk.c" and "VirtioScsi.c" for SIZE_1GB, for example. Therefore
refusing oversized requests is nothing new, except the definition of
"oversized" might vary, dependent on IOMMU.)

However, DeviceAddress being (potentially) different from HostAddress is
the core idea (an *inherent* trait) of the IOMMU protocol. If we ever
implement a different IOMMU protocol -- e.g. for QEMU's vIOMMU --, I
wouldn't like this assert -- or function prototype -- to cause issues.

So, please drop this helper function, and update all call sites to pass
DeviceAddress to the virtio device.

(I'm aware that this might cause major churn, and more review work for
me, but after all, this is the entire point of the IOMMU abstraction.)

> +
> +/**
> +  A helper function to unmap shared bus master memory mapped using Map().
> +
> +  @param[in]  VirtIo          The target virtio device to use. It must be
> +                              valid.
> +
> +  @param[in] Mapping          A mapping value return from Map().
> +
> +  return                      Returns error code from
> +                              VirtIo->UnmapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioUnmapSharedBuffer (
> +  IN VIRTIO_DEVICE_PROTOCOL  *VirtIo,
> +  IN VOID                    *Mapping
> +  )
> +{
> +  return VirtIo->UnmapSharedBuffer (VirtIo, Mapping);
> +}
> 

(9) I think this function also doesn't buy us much, please drop it.

Thanks,
Laszlo


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

* Re: [PATCH v1 05/14] OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit()
  2017-08-07 11:58 ` [PATCH v1 05/14] OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit() Brijesh Singh
@ 2017-08-09 21:13   ` Laszlo Ersek
  0 siblings, 0 replies; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-09 21:13 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

(1) the subject has a typo ("Uinit()") so I suggest:

OvmfPkg/VirtioLib: take VirtIo instance in VirtioRingInit/VirtioRingUninit

(74 characters).

On 08/07/17 13:58, 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(-)
>
> diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
> index fa82734f1852..610654225de7 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 will was using the ring.

(2) s/will was/was/

> +
> +  @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 f6b464b6cdf8..50e5ec28ea1b 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 will was using the ring.

(3) Same as (2).

With these fixed:

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

Thanks
Laszlo

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



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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
                   ` (14 preceding siblings ...)
  2017-08-09 14:39 ` [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Laszlo Ersek
@ 2017-08-09 22:38 ` Laszlo Ersek
  2017-08-09 22:44   ` Brijesh Singh
  15 siblings, 1 reply; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-09 22:38 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/07/17 13:58, Brijesh Singh wrote:
> 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 - 3:
>  Defines and implements new member functions to map a system physical address
>  to device address. The patch implements Laszlo's suggestion [1].
> 
> Patch 4 - 7:
>  Allocates the vring buffer using newly added member functions and provides
>  some helper functions.
> 
> Patch 8:
>  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
> 
> Patch 9:
>  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 \
> 
> Patch 10 - 13:
>  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=
> 
> Patch 14:
>  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
> 
>  And succesfully ran RngTest.efi from SecurityPkg/Application
> 
> Repo: https://github.com/codomania/edk2
> Branch: virtio-support
> 
> 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>
> 
> Brijesh Singh (14):
>   OvmfPkg/Virtio: Introduce new member functions in
>     VIRTIO_DEVICE_PROTOCOL
>   OvmfPkg/Virtio10Dxe: Implement new member functions
>   OvmfPkg/VirtioPciDeviceDxe: Implement new member functions
>   OvmfPkg/VirtioLib: Add SharedBuffer helper functions
>   OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit()
>   OvmfPkg/VirtioLib: Add functions to map/unmap VRING
>   OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer
>   OvmfPkg/VirtioBlkDxe: Use DeviceAddresses in vring descriptors
>   OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors
>   OvmfPkg/VirtioNetDxe: Allocate Tx and Rx ring using
>     AllocateSharedPage()
>   OvmfPkg/VirtioNetDxe: Allocate RxBuf using AllocateSharedPages()
>   OvmfPkg/VirtioNetDxe: Dynamically allocate transmit header
>   OvmfPkg/VirtioNetDxe: Use DeviceAddress in transmit vring descriptors
>   OvmfPkg/VirtioRngDxe: Use DeviceAddresses in vring descriptors
> 
>  OvmfPkg/Include/Library/VirtioLib.h             | 198 ++++++++++++-
>  OvmfPkg/Include/Protocol/VirtioDevice.h         | 121 ++++++++
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.h                |   1 +
>  OvmfPkg/VirtioNetDxe/VirtioNet.h                |  25 +-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h    |  34 +++
>  OvmfPkg/VirtioRngDxe/VirtioRng.h                |   1 +
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.h              |   1 +
>  OvmfPkg/Library/VirtioLib/VirtioLib.c           | 296 +++++++++++++++++++-
>  OvmfPkg/Virtio10Dxe/Virtio10.c                  | 114 +++++++-
>  OvmfPkg/VirtioBlkDxe/VirtioBlk.c                | 104 ++++++-
>  OvmfPkg/VirtioGpuDxe/Commands.c                 |   7 +-
>  OvmfPkg/VirtioNetDxe/Events.c                   |  24 ++
>  OvmfPkg/VirtioNetDxe/SnpGetStatus.c             |  19 +-
>  OvmfPkg/VirtioNetDxe/SnpInitialize.c            | 102 +++++--
>  OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c         | 119 +++++++-
>  OvmfPkg/VirtioNetDxe/SnpShutdown.c              |  16 +-
>  OvmfPkg/VirtioNetDxe/SnpTransmit.c              |  22 +-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c    |   7 +-
>  OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c |  66 +++++
>  OvmfPkg/VirtioRngDxe/VirtioRng.c                |  54 +++-
>  OvmfPkg/VirtioScsiDxe/VirtioScsi.c              | 121 +++++++-
>  21 files changed, 1378 insertions(+), 74 deletions(-)
> 

The conversion for VirtioGpuDxe seems to be missing; is it on your todo
list? (Not that it's urgent at all; in fact I'll suggest delaying the
more complex drivers in a minute.)

Thanks,
Laszlo


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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-09 22:38 ` Laszlo Ersek
@ 2017-08-09 22:44   ` Brijesh Singh
  2017-08-10  9:53     ` Laszlo Ersek
  0 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-09 22:44 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Tom Lendacky, Ard Biesheuvel



On 08/09/2017 05:38 PM, Laszlo Ersek wrote:
> On 08/07/17 13:58, Brijesh Singh wrote:
>> 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 - 3:
>>   Defines and implements new member functions to map a system physical address
>>   to device address. The patch implements Laszlo's suggestion [1].
>>
>> Patch 4 - 7:
>>   Allocates the vring buffer using newly added member functions and provides
>>   some helper functions.
>>
>> Patch 8:
>>   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
>>
>> Patch 9:
>>   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 \
>>
>> Patch 10 - 13:
>>   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=
>>
>> Patch 14:
>>   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
>>
>>   And succesfully ran RngTest.efi from SecurityPkg/Application
>>
>> Repo: https://github.com/codomania/edk2
>> Branch: virtio-support
>>
>> 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>
>>
>> Brijesh Singh (14):
>>    OvmfPkg/Virtio: Introduce new member functions in
>>      VIRTIO_DEVICE_PROTOCOL
>>    OvmfPkg/Virtio10Dxe: Implement new member functions
>>    OvmfPkg/VirtioPciDeviceDxe: Implement new member functions
>>    OvmfPkg/VirtioLib: Add SharedBuffer helper functions
>>    OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit()
>>    OvmfPkg/VirtioLib: Add functions to map/unmap VRING
>>    OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer
>>    OvmfPkg/VirtioBlkDxe: Use DeviceAddresses in vring descriptors
>>    OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors
>>    OvmfPkg/VirtioNetDxe: Allocate Tx and Rx ring using
>>      AllocateSharedPage()
>>    OvmfPkg/VirtioNetDxe: Allocate RxBuf using AllocateSharedPages()
>>    OvmfPkg/VirtioNetDxe: Dynamically allocate transmit header
>>    OvmfPkg/VirtioNetDxe: Use DeviceAddress in transmit vring descriptors
>>    OvmfPkg/VirtioRngDxe: Use DeviceAddresses in vring descriptors
>>
>>   OvmfPkg/Include/Library/VirtioLib.h             | 198 ++++++++++++-
>>   OvmfPkg/Include/Protocol/VirtioDevice.h         | 121 ++++++++
>>   OvmfPkg/VirtioBlkDxe/VirtioBlk.h                |   1 +
>>   OvmfPkg/VirtioNetDxe/VirtioNet.h                |  25 +-
>>   OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h    |  34 +++
>>   OvmfPkg/VirtioRngDxe/VirtioRng.h                |   1 +
>>   OvmfPkg/VirtioScsiDxe/VirtioScsi.h              |   1 +
>>   OvmfPkg/Library/VirtioLib/VirtioLib.c           | 296 +++++++++++++++++++-
>>   OvmfPkg/Virtio10Dxe/Virtio10.c                  | 114 +++++++-
>>   OvmfPkg/VirtioBlkDxe/VirtioBlk.c                | 104 ++++++-
>>   OvmfPkg/VirtioGpuDxe/Commands.c                 |   7 +-
>>   OvmfPkg/VirtioNetDxe/Events.c                   |  24 ++
>>   OvmfPkg/VirtioNetDxe/SnpGetStatus.c             |  19 +-
>>   OvmfPkg/VirtioNetDxe/SnpInitialize.c            | 102 +++++--
>>   OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c         | 119 +++++++-
>>   OvmfPkg/VirtioNetDxe/SnpShutdown.c              |  16 +-
>>   OvmfPkg/VirtioNetDxe/SnpTransmit.c              |  22 +-
>>   OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c    |   7 +-
>>   OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c |  66 +++++
>>   OvmfPkg/VirtioRngDxe/VirtioRng.c                |  54 +++-
>>   OvmfPkg/VirtioScsiDxe/VirtioScsi.c              | 121 +++++++-
>>   21 files changed, 1378 insertions(+), 74 deletions(-)
>>
> 
> The conversion for VirtioGpuDxe seems to be missing; is it on your todo
> list? (Not that it's urgent at all; in fact I'll suggest delaying the
> more complex drivers in a minute.)
> 

Actually I was thinking to delay it for now, once we get a basic support
enabled then we can revisit the VirtioGpuDxe, I still need to figure out
qemu cli and Uefi app to test it. I will add in TODO list so that.


> Thanks,
> Laszlo
> 


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

* Re: [PATCH v1 06/14] OvmfPkg/VirtioLib: Add functions to map/unmap VRING
  2017-08-07 11:58 ` [PATCH v1 06/14] OvmfPkg/VirtioLib: Add functions to map/unmap VRING Brijesh Singh
@ 2017-08-09 23:51   ` Laszlo Ersek
  0 siblings, 0 replies; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-09 23:51 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

First some superficial comments, then some more serious ones.

On 08/07/17 13:58, Brijesh Singh wrote:
> Add functions to map and unmap the ring buffer with BusMasterCommonBuffer.
> 
> 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   | 41 +++++++++++++++
>  OvmfPkg/Library/VirtioLib/VirtioLib.c | 52 ++++++++++++++++++++
>  2 files changed, 93 insertions(+)
> 
> diff --git a/OvmfPkg/Include/Library/VirtioLib.h b/OvmfPkg/Include/Library/VirtioLib.h
> index 610654225de7..877961af0514 100644
> --- a/OvmfPkg/Include/Library/VirtioLib.h
> +++ b/OvmfPkg/Include/Library/VirtioLib.h
> @@ -62,6 +62,47 @@ 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]     Mapping   A resulting value to pass to Unmap().

(1) Please say "token" here (to be consistent with my earlier request).

(2) Please replace Unmap() with VirtIo->UnmapSharedBuffer().

> +
> +  @retval         Value returned from VirtIo->MapSharedBuffer()

(3) This should be @return, not @retval. @retval is for concrete
constants. Also I would suggest "Status code" rather than "Value".

(4) Please sync the comment block in the C file.

> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioRingMap (
> +  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
> +  IN  VRING                  *Ring,
> +  OUT VOID                   **Mapping
> +  );
> +
> +/**
> +
> +  Unmap the ring buffer mapped using VirtioRingMap()
> +
> +  @param[in]      VirtIo    The virtio device instance.
> +
> +  @param[in]      Ring      The virtio ring to unmap.
> +
> +  @param[in]      Mapping   A value obtained through Map().
> +
> +  @retval         Value returned from VirtIo->UnmapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioRingUnmap (
> +  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
> +  IN  VRING                  *Ring,
> +  IN  VOID                   *Mapping
> +  );

(5) Please drop this function. It doesn't save us anything. (The Ring
parameter isn't even used in the implementation.)

> +
> +/**
> +
>    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 50e5ec28ea1b..09a3f9b7f2e5 100644
> --- a/OvmfPkg/Library/VirtioLib/VirtioLib.c
> +++ b/OvmfPkg/Library/VirtioLib/VirtioLib.c
> @@ -640,3 +640,55 @@ VirtioUnmapSharedBuffer (
>  {
>    return VirtIo->UnmapSharedBuffer (VirtIo, Mapping);
>  }
> +
> +/**
> +
> +  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]     Mapping   A resulting value to pass to Unmap().
> +
> +  @retval         Value returned from VirtIo->MapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioRingMap (
> +  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
> +  IN  VRING                  *Ring,
> +  OUT VOID                   **Mapping
> +  )
> +{
> +  UINTN                 NumberOfBytes;
> +
> +  NumberOfBytes = Ring->NumPages * EFI_PAGE_SIZE;

(6) "EFI_PAGES_TO_SIZE (Ring->NumPages)" is more idiomatic.

> +
> +  return VirtioMapSharedBufferCommon (VirtIo, Ring->Base,
> +           NumberOfBytes, Mapping);

(7) So, based on my earlier request, this should become a call to
VirtioMapAllBytesInSharedBuffer(). Please break every argument to a
separate line.

Now, my important comments for this patch. :)

VirtioMapAllBytesInSharedBuffer() will give you a DeviceAddress. Here's
what we should do with it:


(8) Please introduce a new patch that modifies the
VIRTIO_SET_QUEUE_ADDRESS typedef, in
"OvmfPkg/Include/Protocol/VirtioDevice.h". Namely, please add a third
parameter:

  IN UINT64 RingBaseShift

In this initial patch, simply update all call sites to pass in 0.

In parallel (in the same initial patch), update all three implementations:
- VirtioMmioSetQueueAddress()
[OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c]
- VirtioPciSetQueueAddress()
[OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c]
- Virtio10SetQueueAddress() [OvmfPkg/Virtio10Dxe/Virtio10.c]

as follows:
- accept the new parameter (obviously),
- simply assert that it is zero, at the top of the function.


(9) Modify Virtio10SetQueueAddress() as follows, in another separate patch:

- every time after the local variable "Address" is assigned, please insert:

  Address += RingBaseShift;

This is automatically going to happen in UINT64 arithmetic, which has
well-defined wrap-around semantics. Three such insertions will be necessary.

- remove the ASSERT added in (8)


(10) Then please include the present patch, with the following update
(beyond the changes requested above):

- Add the following output parameter to VirtioRingMap():

  OUT UINT64 *RingBaseShift

- In the implementation, assign it like this, if
VirtioMapAllBytesInSharedBuffer() succeeds:

  *RingBaseShift = DeviceAddress - (UINT64)(UINTN)Ring->Base;

(DeviceAddress has type EFI_PHYSICAL_ADDRESS, which is equivalent to
UINT64, on the spec level.)


(11) Please make sure that no output parameter is modified before we can
guarantee returning EFI_SUCCESS.


(12) In the individual virtio device drivers, whenever you insert the
VirtioRingMap() function call, carry "RingBaseShift" from
VirtioRingMap() to VirtIo->SetQueueAddress() in a new local UINT64 variable.

End result:
- the MMIO and legacy PCI transport implementations will always set
DeviceAddress to HostAddress in their no-op MapSharedBuffer() member
functions,
- therefore VirtioRingMap() will set RingBaseShift to zero,
- the ASSERT()s in the SetQueueAddress() members of those same transport
implementations will be satisfied,
- with the modern-only (1.0) transport, RingBaseShift will also be zero
(because of the SEV IOMMU that we have), and "Address += 0" will have no
effect,
- if we ever add an IOMMU driver that translates addresses, the
translation will happen automatically in the modern-only transport.

Thanks,
Laszlo


> +}
> +
> +/**
> +
> +  Unmap the ring buffer mapped using VirtioRingMap()
> +
> +  @param[in]      VirtIo    The virtio device instance.
> +
> +  @param[in]      Ring      The virtio ring to unmap.
> +
> +  @param[in]      Mapping   A value obtained through Map().
> +
> +  @retval         Value returned from VirtIo->UnmapSharedBuffer()
> +**/
> +EFI_STATUS
> +EFIAPI
> +VirtioRingUnmap (
> +  IN  VIRTIO_DEVICE_PROTOCOL *VirtIo,
> +  IN  VRING                  *Ring,
> +  IN  VOID                   *Mapping
> +  )
> +{
> +  return VirtioUnmapSharedBuffer (VirtIo, Mapping);
> +}
> 



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

* Re: [PATCH v1 07/14] OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer
  2017-08-07 11:58 ` [PATCH v1 07/14] OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer Brijesh Singh
@ 2017-08-10  0:02   ` Laszlo Ersek
  0 siblings, 0 replies; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-10  0:02 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/07/17 13:58, Brijesh Singh wrote:
> The vring buffer is communication block between guest and hypervisor,
> allocate the vring buffer using AllocateSharedPages() so that it can be
> Map() with BusMasterCommonBufer for bi-directional access.
> 
> 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 | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/OvmfPkg/Library/VirtioLib/VirtioLib.c b/OvmfPkg/Library/VirtioLib/VirtioLib.c
> index 09a3f9b7f2e5..9ba64204326f 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,12 @@ 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 = VirtioAllocateSharedPages (VirtIo, Ring->NumPages, &Ring->Base);
> +  if (EFI_ERROR (Status)) {
>      return EFI_OUT_OF_RESOURCES;
>    }
>    SetMem (Ring->Base, RingSize, 0x00);
> @@ -143,7 +147,7 @@ VirtioRingUninit (
>    IN OUT VRING                  *Ring
>    )
>  {
> -  FreePages (Ring->Base, Ring->NumPages);
> +  VirtioFreeSharedPages (VirtIo, Ring->NumPages, Ring->Base);
>    SetMem (Ring, sizeof *Ring, 0x00);
>  }
>  
> 

The logic looks good, I have some superficial comments:

(1) Please update the subject, the commit message, and the code to refer
to VirtIo->AllocateSharedPages() (or even VIRTIO_ALLOCATE_SHARED, as you
see fit -- just not the helper function, because we won't have that).

(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].

Thanks,
Laszlo


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

* Re: [PATCH v1 14/14] OvmfPkg/VirtioRngDxe: Use DeviceAddresses in vring descriptors
  2017-08-07 11:58 ` [PATCH v1 14/14] OvmfPkg/VirtioRngDxe: Use DeviceAddresses in " Brijesh Singh
@ 2017-08-10  0:25   ` Laszlo Ersek
  2017-08-10  0:46     ` Laszlo Ersek
  0 siblings, 1 reply; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-10  0:25 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/07/17 13:58, Brijesh Singh wrote:
> The patch uses newly introduced VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer()
> 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/VirtioRngDxe/VirtioRng.h |  1 +
>  OvmfPkg/VirtioRngDxe/VirtioRng.c | 47 +++++++++++++++++---
>  2 files changed, 43 insertions(+), 5 deletions(-)

I'm skipping all the other device driver conversion patches for now (v1
8-13), because I think that this is the simplest driver, and we already
have enough changes queued from this review.

I suggest that for v2, you please update and test all of the drivers (so
that we can be sure that my requests are feasible), but move this driver
patch in front of the others.

I'll say a number of generalities:

* Please never roll-back earlier actions directly within an
  error-catching "if" -- instead, insert a new error handling label at
  the appropriate place, and jump to it with "goto". Sooner or later
  we'll grow yet more actions, and then we'll have to convert those "if"
  bodies to goto's anyway.

* NULL for RingMap is a valid value () -- see also point (8) in my v1
  03/14 feedback -- and device driver logic should not depend on it.
  Instead, use additional (precise) labels -- such as "UnmapQueue" and
  "UnmapBuffer" -- and matching goto statements.

  If a VirtIo->MapSharedBuffer() implementation gives you RingMap=NULL
  (on success), then VirtIo->UnmapSharedBuffer() will also take
  RingMap=NULL -- you simply don't have to be aware of the value.

* In most cases, the fact that you have a live exit-boot-services
  callback implies that your device is "live" as well. So no need for
  additional checks before unmapping the queue. (There are exceptions of
  course, such as virtio-net -- IIRC the SimpleNetworkProtocol has an
  internal state flag that affects this question.)

  For example, in the virtio-rng case, the exit-boot-services
  notification function is installed in VirtioRngDriverBindingStart()
  *after* the call to VirtioRngInit(). In addition, it is uninstalled --
  its associated event is closed -- in VirtioRngDriverBindingStop(),
  *before* the call to VirtioRngUninit(). So whenever the notification
  function can run, the device is guaranteed to be live.

Thanks,
Laszlo

> 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 e20602ac7225..5ff54867616a 100644
> --- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
> +++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
> @@ -140,11 +140,15 @@ VirtioRngGetRNG (
>    UINT32                    Len;
>    UINT32                    BufferSize;
>    EFI_STATUS                Status;
> +  UINTN                     NumPages;
> +  EFI_PHYSICAL_ADDRESS      DeviceAddress;
> +  VOID                      *Mapping;
>  
>    if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {
>      return EFI_INVALID_PARAMETER;
>    }
>  
> +  Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
>    //
>    // We only support the raw algorithm, so reject requests for anything else
>    //
> @@ -153,12 +157,18 @@ VirtioRngGetRNG (
>      return EFI_UNSUPPORTED;
>    }
>  
> -  Buffer = (volatile UINT8 *)AllocatePool (RNGValueLength);
> -  if (Buffer == NULL) {
> +  NumPages = EFI_SIZE_TO_PAGES (RNGValueLength);
> +  Status = VirtioAllocateSharedPages (Dev->VirtIo, NumPages, (VOID *)&Buffer);
> +  if (EFI_ERROR (Status)) {
>      return EFI_DEVICE_ERROR;
>    }
>  
> -  Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
> +  Status = VirtioMapSharedBufferWrite (Dev->VirtIo, (VOID *)Buffer,
> +             RNGValueLength, &DeviceAddress, &Mapping);
> +  if (EFI_ERROR (Status)) {
> +    VirtioFreeSharedPages (Dev->VirtIo, NumPages, (VOID *)Buffer);
> +    return EFI_DEVICE_ERROR;
> +  }
>  
>    //
>    // The Virtio RNG device may return less data than we asked it to, and can
> @@ -170,7 +180,7 @@ VirtioRngGetRNG (
>  
>      VirtioPrepare (&Dev->Ring, &Indices);
>      VirtioAppendDesc (&Dev->Ring,
> -      (UINTN)Buffer + Index,
> +      (UINTN)DeviceAddress + Index,
>        BufferSize,
>        VRING_DESC_F_WRITE,
>        &Indices);
> @@ -178,19 +188,22 @@ VirtioRngGetRNG (
>      if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=
>          EFI_SUCCESS) {
>        Status = EFI_DEVICE_ERROR;
> +      VirtioUnmapSharedBuffer (Dev->VirtIo, Mapping);
>        goto FreeBuffer;
>      }
>      ASSERT (Len > 0);
>      ASSERT (Len <= BufferSize);
>    }
>  
> +  VirtioUnmapSharedBuffer (Dev->VirtIo, Mapping);
> +
>    for (Index = 0; Index < RNGValueLength; Index++) {
>      RNGValue[Index] = Buffer[Index];
>    }
>    Status = EFI_SUCCESS;
>  
>  FreeBuffer:
> -  FreePool ((VOID *)Buffer);
> +  VirtioFreeSharedPages (Dev->VirtIo, NumPages, (VOID *)Buffer);
>    return Status;
>  }
>  
> @@ -281,6 +294,11 @@ VirtioRngInit (
>      goto Failed;
>    }
>  
> +  Status = VirtioRingMap (Dev->VirtIo, &Dev->Ring, &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.
> @@ -332,6 +350,11 @@ VirtioRngInit (
>    return EFI_SUCCESS;
>  
>  ReleaseQueue:
> +  if (Dev->RingMap != NULL) {
> +    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap);
> +    Dev->RingMap = NULL;
> +  }
> +
>    VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
>  
>  Failed:
> @@ -359,6 +382,11 @@ VirtioRngUninit (
>    // the old comms area.
>    //
>    Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
> +
> +  if (Dev->RingMap != NULL) {
> +    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap);
> +  }
> +
>    VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
>  }
>  
> @@ -385,6 +413,15 @@ VirtioRngExitBoot (
>    //
>    Dev = Context;
>    Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
> +
> +  //
> +  // If Ring mapping exist then umap it so that hypervisor will not able to
> +  // get readable data after device reset.
> +  //
> +  if (Dev->RingMap != NULL) {
> +    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap);
> +    Dev->RingMap = NULL;
> +  }
>  }
>  
>  
> 



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

* Re: [PATCH v1 14/14] OvmfPkg/VirtioRngDxe: Use DeviceAddresses in vring descriptors
  2017-08-10  0:25   ` Laszlo Ersek
@ 2017-08-10  0:46     ` Laszlo Ersek
  0 siblings, 0 replies; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-10  0:46 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/10/17 02:25, Laszlo Ersek wrote:
> On 08/07/17 13:58, Brijesh Singh wrote:
>> The patch uses newly introduced VIRTIO_DEVICE_PROTOCOL.MapSharedBuffer()
>> 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/VirtioRngDxe/VirtioRng.h |  1 +
>>  OvmfPkg/VirtioRngDxe/VirtioRng.c | 47 +++++++++++++++++---
>>  2 files changed, 43 insertions(+), 5 deletions(-)
> 
> I'm skipping all the other device driver conversion patches for now (v1
> 8-13), because I think that this is the simplest driver, and we already
> have enough changes queued from this review.
> 
> I suggest that for v2, you please update and test all of the drivers (so
> that we can be sure that my requests are feasible), but move this driver
> patch in front of the others.
> 
> I'll say a number of generalities:
> 
> * Please never roll-back earlier actions directly within an
>   error-catching "if" -- instead, insert a new error handling label at
>   the appropriate place, and jump to it with "goto". Sooner or later
>   we'll grow yet more actions, and then we'll have to convert those "if"
>   bodies to goto's anyway.
> 
> * NULL for RingMap is a valid value () -- see also point (8) in my v1
>   03/14 feedback -- and device driver logic should not depend on it.
>   Instead, use additional (precise) labels -- such as "UnmapQueue" and
>   "UnmapBuffer" -- and matching goto statements.
> 
>   If a VirtIo->MapSharedBuffer() implementation gives you RingMap=NULL
>   (on success), then VirtIo->UnmapSharedBuffer() will also take
>   RingMap=NULL -- you simply don't have to be aware of the value.
> 
> * In most cases, the fact that you have a live exit-boot-services
>   callback implies that your device is "live" as well. So no need for
>   additional checks before unmapping the queue. (There are exceptions of
>   course, such as virtio-net -- IIRC the SimpleNetworkProtocol has an
>   internal state flag that affects this question.)
> 
>   For example, in the virtio-rng case, the exit-boot-services
>   notification function is installed in VirtioRngDriverBindingStart()
>   *after* the call to VirtioRngInit(). In addition, it is uninstalled --
>   its associated event is closed -- in VirtioRngDriverBindingStop(),
>   *before* the call to VirtioRngUninit(). So whenever the notification
>   function can run, the device is guaranteed to be live.

Something else: please don't forget about the VIRTIO_F_IOMMU_PLATFORM
flag -- pls see point (5.3) in
<http://mid.mail-archive.com/841bec5f-6f6e-8b1f-25ba-0fd37a915b72@redhat.com>.

After this conversion is complete, we can claim that our virtio device
drivers are "IOMMU aware", whenever we negotiate VIRTIO_F_VERSION_1.
(It's a different question what IOMMU drivers we have.)

Thanks,
Laszlo


>> 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 e20602ac7225..5ff54867616a 100644
>> --- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
>> +++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
>> @@ -140,11 +140,15 @@ VirtioRngGetRNG (
>>    UINT32                    Len;
>>    UINT32                    BufferSize;
>>    EFI_STATUS                Status;
>> +  UINTN                     NumPages;
>> +  EFI_PHYSICAL_ADDRESS      DeviceAddress;
>> +  VOID                      *Mapping;
>>  
>>    if (This == NULL || RNGValueLength == 0 || RNGValue == NULL) {
>>      return EFI_INVALID_PARAMETER;
>>    }
>>  
>> +  Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
>>    //
>>    // We only support the raw algorithm, so reject requests for anything else
>>    //
>> @@ -153,12 +157,18 @@ VirtioRngGetRNG (
>>      return EFI_UNSUPPORTED;
>>    }
>>  
>> -  Buffer = (volatile UINT8 *)AllocatePool (RNGValueLength);
>> -  if (Buffer == NULL) {
>> +  NumPages = EFI_SIZE_TO_PAGES (RNGValueLength);
>> +  Status = VirtioAllocateSharedPages (Dev->VirtIo, NumPages, (VOID *)&Buffer);
>> +  if (EFI_ERROR (Status)) {
>>      return EFI_DEVICE_ERROR;
>>    }
>>  
>> -  Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
>> +  Status = VirtioMapSharedBufferWrite (Dev->VirtIo, (VOID *)Buffer,
>> +             RNGValueLength, &DeviceAddress, &Mapping);
>> +  if (EFI_ERROR (Status)) {
>> +    VirtioFreeSharedPages (Dev->VirtIo, NumPages, (VOID *)Buffer);
>> +    return EFI_DEVICE_ERROR;
>> +  }
>>  
>>    //
>>    // The Virtio RNG device may return less data than we asked it to, and can
>> @@ -170,7 +180,7 @@ VirtioRngGetRNG (
>>  
>>      VirtioPrepare (&Dev->Ring, &Indices);
>>      VirtioAppendDesc (&Dev->Ring,
>> -      (UINTN)Buffer + Index,
>> +      (UINTN)DeviceAddress + Index,
>>        BufferSize,
>>        VRING_DESC_F_WRITE,
>>        &Indices);
>> @@ -178,19 +188,22 @@ VirtioRngGetRNG (
>>      if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices, &Len) !=
>>          EFI_SUCCESS) {
>>        Status = EFI_DEVICE_ERROR;
>> +      VirtioUnmapSharedBuffer (Dev->VirtIo, Mapping);
>>        goto FreeBuffer;
>>      }
>>      ASSERT (Len > 0);
>>      ASSERT (Len <= BufferSize);
>>    }
>>  
>> +  VirtioUnmapSharedBuffer (Dev->VirtIo, Mapping);
>> +
>>    for (Index = 0; Index < RNGValueLength; Index++) {
>>      RNGValue[Index] = Buffer[Index];
>>    }
>>    Status = EFI_SUCCESS;
>>  
>>  FreeBuffer:
>> -  FreePool ((VOID *)Buffer);
>> +  VirtioFreeSharedPages (Dev->VirtIo, NumPages, (VOID *)Buffer);
>>    return Status;
>>  }
>>  
>> @@ -281,6 +294,11 @@ VirtioRngInit (
>>      goto Failed;
>>    }
>>  
>> +  Status = VirtioRingMap (Dev->VirtIo, &Dev->Ring, &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.
>> @@ -332,6 +350,11 @@ VirtioRngInit (
>>    return EFI_SUCCESS;
>>  
>>  ReleaseQueue:
>> +  if (Dev->RingMap != NULL) {
>> +    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap);
>> +    Dev->RingMap = NULL;
>> +  }
>> +
>>    VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
>>  
>>  Failed:
>> @@ -359,6 +382,11 @@ VirtioRngUninit (
>>    // the old comms area.
>>    //
>>    Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
>> +
>> +  if (Dev->RingMap != NULL) {
>> +    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap);
>> +  }
>> +
>>    VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
>>  }
>>  
>> @@ -385,6 +413,15 @@ VirtioRngExitBoot (
>>    //
>>    Dev = Context;
>>    Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
>> +
>> +  //
>> +  // If Ring mapping exist then umap it so that hypervisor will not able to
>> +  // get readable data after device reset.
>> +  //
>> +  if (Dev->RingMap != NULL) {
>> +    VirtioRingUnmap (Dev->VirtIo, &Dev->Ring, Dev->RingMap);
>> +    Dev->RingMap = NULL;
>> +  }
>>  }
>>  
>>  
>>
> 



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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-09 22:44   ` Brijesh Singh
@ 2017-08-10  9:53     ` Laszlo Ersek
  0 siblings, 0 replies; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-10  9:53 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/10/17 00:44, Brijesh Singh wrote:
> 
> 
> On 08/09/2017 05:38 PM, Laszlo Ersek wrote:
>> On 08/07/17 13:58, Brijesh Singh wrote:
>>> 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 - 3:
>>>   Defines and implements new member functions to map a system
>>> physical address
>>>   to device address. The patch implements Laszlo's suggestion [1].
>>>
>>> Patch 4 - 7:
>>>   Allocates the vring buffer using newly added member functions and
>>> provides
>>>   some helper functions.
>>>
>>> Patch 8:
>>>   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
>>>
>>> Patch 9:
>>>   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 \
>>>
>>> Patch 10 - 13:
>>>   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=
>>>
>>> Patch 14:
>>>   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
>>>
>>>   And succesfully ran RngTest.efi from SecurityPkg/Application
>>>
>>> Repo: https://github.com/codomania/edk2
>>> Branch: virtio-support
>>>
>>> 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>
>>>
>>> Brijesh Singh (14):
>>>    OvmfPkg/Virtio: Introduce new member functions in
>>>      VIRTIO_DEVICE_PROTOCOL
>>>    OvmfPkg/Virtio10Dxe: Implement new member functions
>>>    OvmfPkg/VirtioPciDeviceDxe: Implement new member functions
>>>    OvmfPkg/VirtioLib: Add SharedBuffer helper functions
>>>    OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit()
>>>    OvmfPkg/VirtioLib: Add functions to map/unmap VRING
>>>    OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer
>>>    OvmfPkg/VirtioBlkDxe: Use DeviceAddresses in vring descriptors
>>>    OvmfPkg/VirtioScsiDxe: Use DeviceAddresses in vring descriptors
>>>    OvmfPkg/VirtioNetDxe: Allocate Tx and Rx ring using
>>>      AllocateSharedPage()
>>>    OvmfPkg/VirtioNetDxe: Allocate RxBuf using AllocateSharedPages()
>>>    OvmfPkg/VirtioNetDxe: Dynamically allocate transmit header
>>>    OvmfPkg/VirtioNetDxe: Use DeviceAddress in transmit vring descriptors
>>>    OvmfPkg/VirtioRngDxe: Use DeviceAddresses in vring descriptors
>>>
>>>   OvmfPkg/Include/Library/VirtioLib.h             | 198 ++++++++++++-
>>>   OvmfPkg/Include/Protocol/VirtioDevice.h         | 121 ++++++++
>>>   OvmfPkg/VirtioBlkDxe/VirtioBlk.h                |   1 +
>>>   OvmfPkg/VirtioNetDxe/VirtioNet.h                |  25 +-
>>>   OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h    |  34 +++
>>>   OvmfPkg/VirtioRngDxe/VirtioRng.h                |   1 +
>>>   OvmfPkg/VirtioScsiDxe/VirtioScsi.h              |   1 +
>>>   OvmfPkg/Library/VirtioLib/VirtioLib.c           | 296
>>> +++++++++++++++++++-
>>>   OvmfPkg/Virtio10Dxe/Virtio10.c                  | 114 +++++++-
>>>   OvmfPkg/VirtioBlkDxe/VirtioBlk.c                | 104 ++++++-
>>>   OvmfPkg/VirtioGpuDxe/Commands.c                 |   7 +-
>>>   OvmfPkg/VirtioNetDxe/Events.c                   |  24 ++
>>>   OvmfPkg/VirtioNetDxe/SnpGetStatus.c             |  19 +-
>>>   OvmfPkg/VirtioNetDxe/SnpInitialize.c            | 102 +++++--
>>>   OvmfPkg/VirtioNetDxe/SnpSharedHelpers.c         | 119 +++++++-
>>>   OvmfPkg/VirtioNetDxe/SnpShutdown.c              |  16 +-
>>>   OvmfPkg/VirtioNetDxe/SnpTransmit.c              |  22 +-
>>>   OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c    |   7 +-
>>>   OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c |  66 +++++
>>>   OvmfPkg/VirtioRngDxe/VirtioRng.c                |  54 +++-
>>>   OvmfPkg/VirtioScsiDxe/VirtioScsi.c              | 121 +++++++-
>>>   21 files changed, 1378 insertions(+), 74 deletions(-)
>>>
>>
>> The conversion for VirtioGpuDxe seems to be missing; is it on your todo
>> list? (Not that it's urgent at all; in fact I'll suggest delaying the
>> more complex drivers in a minute.)
>>
> 
> Actually I was thinking to delay it for now,

OK, that makes sense even from the complexity standpoint.

> once we get a basic support
> enabled then we can revisit the VirtioGpuDxe, I still need to figure out
> qemu cli and Uefi app to test it.

You can read about my original test cases and test instructions in the
following message:

[2] http://mid.mail-archive.com/20160819124932.29711-1-lersek@redhat.com

(

Some background:

The virtio-vga device combines the Virtio GPU and the traditional VGA
framebuffer that is also seen on QXL and stdvga ("Bochs"). If you use
"-device virtio-vga", then QemuVideoDxe will bind the device (this is
intended). So, the right option for specifically using the virtio GPU is
"-device virtio-gpu-pci".

You can read more about this distinction in the following libvirt commit:

[3] http://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=706b5b627719

)

Regarding a UEFI app for testing, the UEFI shell and grub suffice:
- do you see the TianoCore boot logo?
- does the UEFI shell work?
- does the shell scroll fine when you press Enter at the bottom of the
  screen?
- does the MODE command work in the shell?
- typing on the serial port, can you disconnect / reconnect the display?
- does grub work?

See again my message [2].

> I will add in TODO list so that.

Sounds good. Once we lay down the foundation (and I can find some time),
I might be able to take on the conversion of VirtioGpuDxe. (If you're OK
with that.)

Thanks!
Laszlo


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

* Re: [PATCH v1 03/14] OvmfPkg/VirtioPciDeviceDxe: Implement new member functions
  2017-08-09 17:09   ` Laszlo Ersek
@ 2017-08-10 18:41     ` Brijesh Singh
  2017-08-10 19:47       ` Laszlo Ersek
  0 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-10 18:41 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Tom Lendacky, Ard Biesheuvel

Hi Laszlo,

On 08/09/2017 12:09 PM, Laszlo Ersek wrote:
[Snip]

> 
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +VirtioPciUnmapSharedBuffer (
>> +  VIRTIO_DEVICE_PROTOCOL    *This,
>> +  VOID                      *Mapping
>> +  )
>> +{
>> +  return EFI_SUCCESS;
>> +}
>>
> 
> (9) Please refresh the function signatures in both "VirtioPciDevice.h"
> and "VirtioPciFunctions.c", from the protocol definition in
> "OvmfPkg/Include/Protocol/VirtioDevice.h".
> 
> In particular, all the IN and OUT decoration is missing here.

I see that several functions defined in VirtioPciDevice.h is missing IN and OUT,
do you want me to send a separate patch to fix that too ?

-Brijesh


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

* Re: [PATCH v1 03/14] OvmfPkg/VirtioPciDeviceDxe: Implement new member functions
  2017-08-10 18:41     ` Brijesh Singh
@ 2017-08-10 19:47       ` Laszlo Ersek
  0 siblings, 0 replies; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-10 19:47 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/10/17 20:41, Brijesh Singh wrote:
> Hi Laszlo,
> 
> On 08/09/2017 12:09 PM, Laszlo Ersek wrote:
> [Snip]
> 
>>
>>> +
>>> +EFI_STATUS
>>> +EFIAPI
>>> +VirtioPciUnmapSharedBuffer (
>>> +  VIRTIO_DEVICE_PROTOCOL    *This,
>>> +  VOID                      *Mapping
>>> +  )
>>> +{
>>> +  return EFI_SUCCESS;
>>> +}
>>>
>>
>> (9) Please refresh the function signatures in both "VirtioPciDevice.h"
>> and "VirtioPciFunctions.c", from the protocol definition in
>> "OvmfPkg/Include/Protocol/VirtioDevice.h".
>>
>> In particular, all the IN and OUT decoration is missing here.
> 
> I see that several functions defined in VirtioPciDevice.h is missing IN
> and OUT,

Ouch, you are right!

> do you want me to send a separate patch to fix that too ?

That would be very kind of you.

Thanks!
Laszlo


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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-09 17:56     ` Laszlo Ersek
  2017-08-09 19:29       ` Laszlo Ersek
@ 2017-08-11 22:22       ` Brijesh Singh
  2017-08-15 10:42         ` Laszlo Ersek
  1 sibling, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-11 22:22 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Tom Lendacky, Ard Biesheuvel



On 08/09/2017 12:56 PM, Laszlo Ersek wrote:

>>
>> Sure, I will make the necessary changes in VirtioMmioDeviceLib and try
>> do the build test but I don't have aarch64 platform to verify at the
>> runtime.
> 
> Actually, dependent on your GNU/Linux distribution, it is pretty easy to
> do on x86_64 too. It comes together from two parts:
> 
> (1) installing an aarch64 cross compiler
> (2) installing qemu-system-aarch64 (from source or distro package),
>      and then either using it directly (from the cmdline) or with the
>      libvirt toolstack
> 
> The only "real" difference is that it's going to use TCG and not KVM
> (software emulation rather than hardware virtualization), so it will be
> slower, but that's not really a problem if you only care about your VM
> until the firmware boots the OS :)
> 
> On Fedora, the cross-compiler (and cross-binutils) packages are built
> from the following SRPMs:
> 
>    https://koji.fedoraproject.org/koji/buildinfo?buildID=921790
>    https://koji.fedoraproject.org/koji/buildinfo?buildID=912429
> 
> ("cross-gcc", "cross-binutils")
> 
> Linaro distributes distro-independent cross compilers:
> 
>    http://www.linaro.org/downloads/
> 
> Build instructions for ArmVirtQemu, and usage hints for the QEMU command
> line, can be found in the Linaro Wiki:
> 
>    https://wiki.linaro.org/LEG/UEFIforQEMU

v2 is almost ready for review, I have made all the necessary changes in
VirtioMmioDeviceLib and it builds fine for aarch64 but I am having trouble
booting the qemu-aarch64 in general. On serial console I see the UEFI debug
messages but it never reaches to UEFI shell.

I have been following the steps from  https://wiki.linaro.org/LEG/UEFIforQEMU

qemu-system-aarch64 \
  -m 1024 \
  -cpu cortex-a57 \
  -M virt  \
  -bios QEMU_EFI.fd \
  -serial stdio

I tried this steps with and without my patches and it resulted in the same.
It seems like I am missing something in the qemu cli, do I need to pass
special dtb file or something similar ?

P.S: the wiki talks about a prebuilt qcow2 image but the link is dead, instead
I downloaded a qcow2 file from Ubuntu repo.

-Brijesh


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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-11 22:22       ` Brijesh Singh
@ 2017-08-15 10:42         ` Laszlo Ersek
  2017-08-15 19:32           ` Brijesh Singh
  0 siblings, 1 reply; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-15 10:42 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/12/17 00:22, Brijesh Singh wrote:
> 
> 
> On 08/09/2017 12:56 PM, Laszlo Ersek wrote:
> 
>>>
>>> Sure, I will make the necessary changes in VirtioMmioDeviceLib and try
>>> do the build test but I don't have aarch64 platform to verify at the
>>> runtime.
>>
>> Actually, dependent on your GNU/Linux distribution, it is pretty easy to
>> do on x86_64 too. It comes together from two parts:
>>
>> (1) installing an aarch64 cross compiler
>> (2) installing qemu-system-aarch64 (from source or distro package),
>>      and then either using it directly (from the cmdline) or with the
>>      libvirt toolstack
>>
>> The only "real" difference is that it's going to use TCG and not KVM
>> (software emulation rather than hardware virtualization), so it will be
>> slower, but that's not really a problem if you only care about your VM
>> until the firmware boots the OS :)
>>
>> On Fedora, the cross-compiler (and cross-binutils) packages are built
>> from the following SRPMs:
>>
>>    https://koji.fedoraproject.org/koji/buildinfo?buildID=921790
>>    https://koji.fedoraproject.org/koji/buildinfo?buildID=912429
>>
>> ("cross-gcc", "cross-binutils")
>>
>> Linaro distributes distro-independent cross compilers:
>>
>>    http://www.linaro.org/downloads/
>>
>> Build instructions for ArmVirtQemu, and usage hints for the QEMU command
>> line, can be found in the Linaro Wiki:
>>
>>    https://wiki.linaro.org/LEG/UEFIforQEMU
> 
> v2 is almost ready for review, I have made all the necessary changes in
> VirtioMmioDeviceLib and it builds fine for aarch64 but I am having trouble
> booting the qemu-aarch64 in general. On serial console I see the UEFI debug
> messages but it never reaches to UEFI shell.
> 
> I have been following the steps from 
> https://wiki.linaro.org/LEG/UEFIforQEMU
> 
> qemu-system-aarch64 \
>  -m 1024 \
>  -cpu cortex-a57 \
>  -M virt  \
>  -bios QEMU_EFI.fd \
>  -serial stdio
> 
> I tried this steps with and without my patches and it resulted in the same.
> It seems like I am missing something in the qemu cli, do I need to pass
> special dtb file or something similar ?

The above command line is not right ("-bios"). Please scroll down the
wiki page, to the section heading saying "Using persistent UEFI
variables". There it explains how to pad the images and how to use two
-pflash options. ... Perhaps even that part of the article is a bit
out-of-date now.

Basically, today ArmVirtQemu should be used the same way as OVMF, except
for the padding. The build produces two files:
- QEMU_EFI.fd (fw binary)
- QEMU_VARS.fd (varstore template)

Each should be padded to 64MiB with zeros at the end (write a small
script for that), then use them with two pflash drives similarly to OVMF.

Thanks!
Laszlo

> P.S: the wiki talks about a prebuilt qcow2 image but the link is dead,
> instead
> I downloaded a qcow2 file from Ubuntu repo.
> 
> -Brijesh



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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-15 10:42         ` Laszlo Ersek
@ 2017-08-15 19:32           ` Brijesh Singh
  2017-08-15 19:48             ` Laszlo Ersek
  0 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-15 19:32 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Tom Lendacky, Ard Biesheuvel

Hi Laszlo,

On 08/15/2017 05:42 AM, Laszlo Ersek wrote:
[snip]

>>
>> I have been following the steps from
>> https://wiki.linaro.org/LEG/UEFIforQEMU
>>
>> qemu-system-aarch64 \
>>   -m 1024 \
>>   -cpu cortex-a57 \
>>   -M virt  \
>>   -bios QEMU_EFI.fd \
>>   -serial stdio
>>
>> I tried this steps with and without my patches and it resulted in the same.
>> It seems like I am missing something in the qemu cli, do I need to pass
>> special dtb file or something similar ?
> 
> The above command line is not right ("-bios"). Please scroll down the
> wiki page, to the section heading saying "Using persistent UEFI
> variables". There it explains how to pad the images and how to use two
> -pflash options. ... Perhaps even that part of the article is a bit
> out-of-date now.
> 
> Basically, today ArmVirtQemu should be used the same way as OVMF, except
> for the padding. The build produces two files:
> - QEMU_EFI.fd (fw binary)
> - QEMU_VARS.fd (varstore template)
> 
> Each should be padded to 64MiB with zeros at the end (write a small
> script for that), then use them with two pflash drives similarly to OVMF.
> 

Still no luck, you can see my log error [1]. I never get to UEFI shell, I have
tried with and without virtio disk.

https://gist.github.com/codomania/0aed024702b817761ee55fd30929200a

I will continuing googling ...



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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-15 19:32           ` Brijesh Singh
@ 2017-08-15 19:48             ` Laszlo Ersek
  2017-08-15 20:26               ` Brijesh Singh
  0 siblings, 1 reply; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-15 19:48 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Ard Biesheuvel, Tom Lendacky

On 08/15/17 21:32, Brijesh Singh wrote:
> Hi Laszlo,
> 
> On 08/15/2017 05:42 AM, Laszlo Ersek wrote:
> [snip]
> 
>>>
>>> I have been following the steps from
>>> https://wiki.linaro.org/LEG/UEFIforQEMU
>>>
>>> qemu-system-aarch64 \
>>>   -m 1024 \
>>>   -cpu cortex-a57 \
>>>   -M virt  \
>>>   -bios QEMU_EFI.fd \
>>>   -serial stdio
>>>
>>> I tried this steps with and without my patches and it resulted in the
>>> same.
>>> It seems like I am missing something in the qemu cli, do I need to pass
>>> special dtb file or something similar ?
>>
>> The above command line is not right ("-bios"). Please scroll down the
>> wiki page, to the section heading saying "Using persistent UEFI
>> variables". There it explains how to pad the images and how to use two
>> -pflash options. ... Perhaps even that part of the article is a bit
>> out-of-date now.
>>
>> Basically, today ArmVirtQemu should be used the same way as OVMF, except
>> for the padding. The build produces two files:
>> - QEMU_EFI.fd (fw binary)
>> - QEMU_VARS.fd (varstore template)
>>
>> Each should be padded to 64MiB with zeros at the end (write a small
>> script for that), then use them with two pflash drives similarly to OVMF.
>>
> 
> Still no luck, you can see my log error [1]. I never get to UEFI shell,
> I have
> tried with and without virtio disk.
> 
> https://gist.github.com/codomania/0aed024702b817761ee55fd30929200a
> 
> I will continuing googling ...

In order to get as detailed as possible logs, I suggest adding the
following option to the ArmVirtQemu build command line:

  -D DEBUG_PRINT_ERROR_LEVEL=0x8040004F

The current log looks quite strange to me in places, but I'm not sure if
that's because there are problems in those parts, or because the log
does not contain DEBUG_VERBOSE entries.

Thanks
Laszlo


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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-15 19:48             ` Laszlo Ersek
@ 2017-08-15 20:26               ` Brijesh Singh
  2017-08-15 20:39                 ` Laszlo Ersek
  0 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-15 20:26 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Ard Biesheuvel, Tom Lendacky



On 08/15/2017 02:48 PM, Laszlo Ersek wrote:
> On 08/15/17 21:32, Brijesh Singh wrote:
>> Hi Laszlo,
>>
>> On 08/15/2017 05:42 AM, Laszlo Ersek wrote:
>> [snip]
>>
>>>>
>>>> I have been following the steps from
>>>> https://wiki.linaro.org/LEG/UEFIforQEMU
>>>>
>>>> qemu-system-aarch64 \
>>>>    -m 1024 \
>>>>    -cpu cortex-a57 \
>>>>    -M virt  \
>>>>    -bios QEMU_EFI.fd \
>>>>    -serial stdio
>>>>
>>>> I tried this steps with and without my patches and it resulted in the
>>>> same.
>>>> It seems like I am missing something in the qemu cli, do I need to pass
>>>> special dtb file or something similar ?
>>>
>>> The above command line is not right ("-bios"). Please scroll down the
>>> wiki page, to the section heading saying "Using persistent UEFI
>>> variables". There it explains how to pad the images and how to use two
>>> -pflash options. ... Perhaps even that part of the article is a bit
>>> out-of-date now.
>>>
>>> Basically, today ArmVirtQemu should be used the same way as OVMF, except
>>> for the padding. The build produces two files:
>>> - QEMU_EFI.fd (fw binary)
>>> - QEMU_VARS.fd (varstore template)
>>>
>>> Each should be padded to 64MiB with zeros at the end (write a small
>>> script for that), then use them with two pflash drives similarly to OVMF.
>>>
>>
>> Still no luck, you can see my log error [1]. I never get to UEFI shell,
>> I have
>> tried with and without virtio disk.
>>
>> https://gist.github.com/codomania/0aed024702b817761ee55fd30929200a
>>
>> I will continuing googling ...
> 
> In order to get as detailed as possible logs, I suggest adding the
> following option to the ArmVirtQemu build command line:
> 
>    -D DEBUG_PRINT_ERROR_LEVEL=0x8040004F
> 
> The current log looks quite strange to me in places, but I'm not sure if
> that's because there are problems in those parts, or because the log
> does not contain DEBUG_VERBOSE entries.
> 


https://gist.github.com/codomania/8b2fc5424fda259236405c5e257d8f47

I am using Ubuntu 16.04 for builds and runs

$ qemu-system-aarch64 --version
QEMU emulator version 2.5.0 (Debian 1:2.5+dfsg-5ubuntu10.14), Copyright (c) 2003-2008 Fabrice Bellard

-Brijesh


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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-15 20:26               ` Brijesh Singh
@ 2017-08-15 20:39                 ` Laszlo Ersek
  2017-08-15 20:44                   ` Brijesh Singh
  0 siblings, 1 reply; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-15 20:39 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Ard Biesheuvel, Tom Lendacky

On 08/15/17 22:26, Brijesh Singh wrote:
> 
> 
> On 08/15/2017 02:48 PM, Laszlo Ersek wrote:
>> On 08/15/17 21:32, Brijesh Singh wrote:
>>> Hi Laszlo,
>>>
>>> On 08/15/2017 05:42 AM, Laszlo Ersek wrote:
>>> [snip]
>>>
>>>>>
>>>>> I have been following the steps from
>>>>> https://wiki.linaro.org/LEG/UEFIforQEMU
>>>>>
>>>>> qemu-system-aarch64 \
>>>>>    -m 1024 \
>>>>>    -cpu cortex-a57 \
>>>>>    -M virt  \
>>>>>    -bios QEMU_EFI.fd \
>>>>>    -serial stdio
>>>>>
>>>>> I tried this steps with and without my patches and it resulted in the
>>>>> same.
>>>>> It seems like I am missing something in the qemu cli, do I need to
>>>>> pass
>>>>> special dtb file or something similar ?
>>>>
>>>> The above command line is not right ("-bios"). Please scroll down the
>>>> wiki page, to the section heading saying "Using persistent UEFI
>>>> variables". There it explains how to pad the images and how to use two
>>>> -pflash options. ... Perhaps even that part of the article is a bit
>>>> out-of-date now.
>>>>
>>>> Basically, today ArmVirtQemu should be used the same way as OVMF,
>>>> except
>>>> for the padding. The build produces two files:
>>>> - QEMU_EFI.fd (fw binary)
>>>> - QEMU_VARS.fd (varstore template)
>>>>
>>>> Each should be padded to 64MiB with zeros at the end (write a small
>>>> script for that), then use them with two pflash drives similarly to
>>>> OVMF.
>>>>
>>>
>>> Still no luck, you can see my log error [1]. I never get to UEFI shell,
>>> I have
>>> tried with and without virtio disk.
>>>
>>> https://gist.github.com/codomania/0aed024702b817761ee55fd30929200a
>>>
>>> I will continuing googling ...
>>
>> In order to get as detailed as possible logs, I suggest adding the
>> following option to the ArmVirtQemu build command line:
>>
>>    -D DEBUG_PRINT_ERROR_LEVEL=0x8040004F
>>
>> The current log looks quite strange to me in places, but I'm not sure if
>> that's because there are problems in those parts, or because the log
>> does not contain DEBUG_VERBOSE entries.
>>
> 
> 
> https://gist.github.com/codomania/8b2fc5424fda259236405c5e257d8f47
> 
> I am using Ubuntu 16.04 for builds and runs
> 
> $ qemu-system-aarch64 --version
> QEMU emulator version 2.5.0 (Debian 1:2.5+dfsg-5ubuntu10.14), Copyright
> (c) 2003-2008 Fabrice Bellard

What is your complete QEMU command line?

Thanks
Laszlo


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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-15 20:39                 ` Laszlo Ersek
@ 2017-08-15 20:44                   ` Brijesh Singh
  2017-08-15 21:57                     ` Laszlo Ersek
  0 siblings, 1 reply; 42+ messages in thread
From: Brijesh Singh @ 2017-08-15 20:44 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Jordan Justen, Ard Biesheuvel, Tom Lendacky



On 08/15/2017 03:39 PM, Laszlo Ersek wrote:
> On 08/15/17 22:26, Brijesh Singh wrote:
>>
>>
>> On 08/15/2017 02:48 PM, Laszlo Ersek wrote:
>>> On 08/15/17 21:32, Brijesh Singh wrote:
>>>> Hi Laszlo,
>>>>
>>>> On 08/15/2017 05:42 AM, Laszlo Ersek wrote:
>>>> [snip]
>>>>
>>>>>>
>>>>>> I have been following the steps from
>>>>>> https://wiki.linaro.org/LEG/UEFIforQEMU
>>>>>>
>>>>>> qemu-system-aarch64 \
>>>>>>     -m 1024 \
>>>>>>     -cpu cortex-a57 \
>>>>>>     -M virt  \
>>>>>>     -bios QEMU_EFI.fd \
>>>>>>     -serial stdio
>>>>>>
>>>>>> I tried this steps with and without my patches and it resulted in the
>>>>>> same.
>>>>>> It seems like I am missing something in the qemu cli, do I need to
>>>>>> pass
>>>>>> special dtb file or something similar ?
>>>>>
>>>>> The above command line is not right ("-bios"). Please scroll down the
>>>>> wiki page, to the section heading saying "Using persistent UEFI
>>>>> variables". There it explains how to pad the images and how to use two
>>>>> -pflash options. ... Perhaps even that part of the article is a bit
>>>>> out-of-date now.
>>>>>
>>>>> Basically, today ArmVirtQemu should be used the same way as OVMF,
>>>>> except
>>>>> for the padding. The build produces two files:
>>>>> - QEMU_EFI.fd (fw binary)
>>>>> - QEMU_VARS.fd (varstore template)
>>>>>
>>>>> Each should be padded to 64MiB with zeros at the end (write a small
>>>>> script for that), then use them with two pflash drives similarly to
>>>>> OVMF.
>>>>>
>>>>
>>>> Still no luck, you can see my log error [1]. I never get to UEFI shell,
>>>> I have
>>>> tried with and without virtio disk.
>>>>
>>>> https://gist.github.com/codomania/0aed024702b817761ee55fd30929200a
>>>>
>>>> I will continuing googling ...
>>>
>>> In order to get as detailed as possible logs, I suggest adding the
>>> following option to the ArmVirtQemu build command line:
>>>
>>>     -D DEBUG_PRINT_ERROR_LEVEL=0x8040004F
>>>
>>> The current log looks quite strange to me in places, but I'm not sure if
>>> that's because there are problems in those parts, or because the log
>>> does not contain DEBUG_VERBOSE entries.
>>>
>>
>>
>> https://gist.github.com/codomania/8b2fc5424fda259236405c5e257d8f47
>>
>> I am using Ubuntu 16.04 for builds and runs
>>
>> $ qemu-system-aarch64 --version
>> QEMU emulator version 2.5.0 (Debian 1:2.5+dfsg-5ubuntu10.14), Copyright
>> (c) 2003-2008 Fabrice Bellard
> 
> What is your complete QEMU command line?
> 

I have been using the following two qemu cli

# qemu-system-aarch64 -m 2048 -cpu cortex-a57 -M virt \
      -pflash flash0.img -pflash flash1.img \
      -nographic

# qemu-system-aarch64 -m 2048 -cpu cortex-a57 -M virt \
       -pflash flash0.img -pflash flash1.img \
      -drive if=none,file=/home/brijesh/xenial-server-cloudimg-arm64.img,id=hd0,format=raw -device virtio-blk-device,drive=hd0 \
      -nographic
   




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

* Re: [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address
  2017-08-15 20:44                   ` Brijesh Singh
@ 2017-08-15 21:57                     ` Laszlo Ersek
  0 siblings, 0 replies; 42+ messages in thread
From: Laszlo Ersek @ 2017-08-15 21:57 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Jordan Justen, Tom Lendacky, Ard Biesheuvel

On 08/15/17 22:44, Brijesh Singh wrote:
> 
> 
> On 08/15/2017 03:39 PM, Laszlo Ersek wrote:
>> On 08/15/17 22:26, Brijesh Singh wrote:
>>>
>>>
>>> On 08/15/2017 02:48 PM, Laszlo Ersek wrote:
>>>> On 08/15/17 21:32, Brijesh Singh wrote:
>>>>> Hi Laszlo,
>>>>>
>>>>> On 08/15/2017 05:42 AM, Laszlo Ersek wrote:
>>>>> [snip]
>>>>>
>>>>>>>
>>>>>>> I have been following the steps from
>>>>>>> https://wiki.linaro.org/LEG/UEFIforQEMU
>>>>>>>
>>>>>>> qemu-system-aarch64 \
>>>>>>>     -m 1024 \
>>>>>>>     -cpu cortex-a57 \
>>>>>>>     -M virt  \
>>>>>>>     -bios QEMU_EFI.fd \
>>>>>>>     -serial stdio
>>>>>>>
>>>>>>> I tried this steps with and without my patches and it resulted in
>>>>>>> the
>>>>>>> same.
>>>>>>> It seems like I am missing something in the qemu cli, do I need to
>>>>>>> pass
>>>>>>> special dtb file or something similar ?
>>>>>>
>>>>>> The above command line is not right ("-bios"). Please scroll down the
>>>>>> wiki page, to the section heading saying "Using persistent UEFI
>>>>>> variables". There it explains how to pad the images and how to use
>>>>>> two
>>>>>> -pflash options. ... Perhaps even that part of the article is a bit
>>>>>> out-of-date now.
>>>>>>
>>>>>> Basically, today ArmVirtQemu should be used the same way as OVMF,
>>>>>> except
>>>>>> for the padding. The build produces two files:
>>>>>> - QEMU_EFI.fd (fw binary)
>>>>>> - QEMU_VARS.fd (varstore template)
>>>>>>
>>>>>> Each should be padded to 64MiB with zeros at the end (write a small
>>>>>> script for that), then use them with two pflash drives similarly to
>>>>>> OVMF.
>>>>>>
>>>>>
>>>>> Still no luck, you can see my log error [1]. I never get to UEFI
>>>>> shell,
>>>>> I have
>>>>> tried with and without virtio disk.
>>>>>
>>>>> https://gist.github.com/codomania/0aed024702b817761ee55fd30929200a
>>>>>
>>>>> I will continuing googling ...
>>>>
>>>> In order to get as detailed as possible logs, I suggest adding the
>>>> following option to the ArmVirtQemu build command line:
>>>>
>>>>     -D DEBUG_PRINT_ERROR_LEVEL=0x8040004F
>>>>
>>>> The current log looks quite strange to me in places, but I'm not
>>>> sure if
>>>> that's because there are problems in those parts, or because the log
>>>> does not contain DEBUG_VERBOSE entries.
>>>>
>>>
>>>
>>> https://gist.github.com/codomania/8b2fc5424fda259236405c5e257d8f47
>>>
>>> I am using Ubuntu 16.04 for builds and runs
>>>
>>> $ qemu-system-aarch64 --version
>>> QEMU emulator version 2.5.0 (Debian 1:2.5+dfsg-5ubuntu10.14), Copyright
>>> (c) 2003-2008 Fabrice Bellard
>>
>> What is your complete QEMU command line?
>>
> 
> I have been using the following two qemu cli
> 
> # qemu-system-aarch64 -m 2048 -cpu cortex-a57 -M virt \
>      -pflash flash0.img -pflash flash1.img \
>      -nographic
> 
> # qemu-system-aarch64 -m 2048 -cpu cortex-a57 -M virt \
>       -pflash flash0.img -pflash flash1.img \
>      -drive
> if=none,file=/home/brijesh/xenial-server-cloudimg-arm64.img,id=hd0,format=raw
> -device virtio-blk-device,drive=hd0 \
>      -nographic

I can reproduce the boot hang. It looks like an edk2 regression. I'm
currently bisecting the issue.

Thanks
Laszlo


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

end of thread, other threads:[~2017-08-15 21:54 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-07 11:58 [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 01/14] OvmfPkg/Virtio: Introduce new member functions in VIRTIO_DEVICE_PROTOCOL Brijesh Singh
2017-08-09 14:27   ` Laszlo Ersek
2017-08-09 18:23     ` Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 02/14] OvmfPkg/Virtio10Dxe: Implement new member functions Brijesh Singh
2017-08-09 16:50   ` Laszlo Ersek
2017-08-07 11:58 ` [PATCH v1 03/14] OvmfPkg/VirtioPciDeviceDxe: " Brijesh Singh
2017-08-09 17:09   ` Laszlo Ersek
2017-08-10 18:41     ` Brijesh Singh
2017-08-10 19:47       ` Laszlo Ersek
2017-08-07 11:58 ` [PATCH v1 04/14] OvmfPkg/VirtioLib: Add SharedBuffer helper functions Brijesh Singh
2017-08-09 20:30   ` Laszlo Ersek
2017-08-07 11:58 ` [PATCH v1 05/14] OvmfPkg/VirtioLib: Pass VirtIo instance in VringInit/Uinit() Brijesh Singh
2017-08-09 21:13   ` Laszlo Ersek
2017-08-07 11:58 ` [PATCH v1 06/14] OvmfPkg/VirtioLib: Add functions to map/unmap VRING Brijesh Singh
2017-08-09 23:51   ` Laszlo Ersek
2017-08-07 11:58 ` [PATCH v1 07/14] OvmfPkg/VirtioLib: Use AllocateShared() to allocate vring buffer Brijesh Singh
2017-08-10  0:02   ` Laszlo Ersek
2017-08-07 11:58 ` [PATCH v1 08/14] OvmfPkg/VirtioBlkDxe: Use DeviceAddresses in vring descriptors Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 09/14] OvmfPkg/VirtioScsiDxe: " Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 10/14] OvmfPkg/VirtioNetDxe: Allocate Tx and Rx ring using AllocateSharedPage() Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 11/14] OvmfPkg/VirtioNetDxe: Allocate RxBuf using AllocateSharedPages() Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 12/14] OvmfPkg/VirtioNetDxe: Dynamically allocate transmit header Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 13/14] OvmfPkg/VirtioNetDxe: Use DeviceAddress in transmit vring descriptors Brijesh Singh
2017-08-07 11:58 ` [PATCH v1 14/14] OvmfPkg/VirtioRngDxe: Use DeviceAddresses in " Brijesh Singh
2017-08-10  0:25   ` Laszlo Ersek
2017-08-10  0:46     ` Laszlo Ersek
2017-08-09 14:39 ` [PATCH v1 00/14] OvmfPkg/Virtio: Add APIs to map system physical to device address Laszlo Ersek
2017-08-09 17:35   ` Brijesh Singh
2017-08-09 17:56     ` Laszlo Ersek
2017-08-09 19:29       ` Laszlo Ersek
2017-08-11 22:22       ` Brijesh Singh
2017-08-15 10:42         ` Laszlo Ersek
2017-08-15 19:32           ` Brijesh Singh
2017-08-15 19:48             ` Laszlo Ersek
2017-08-15 20:26               ` Brijesh Singh
2017-08-15 20:39                 ` Laszlo Ersek
2017-08-15 20:44                   ` Brijesh Singh
2017-08-15 21:57                     ` Laszlo Ersek
2017-08-09 22:38 ` Laszlo Ersek
2017-08-09 22:44   ` Brijesh Singh
2017-08-10  9:53     ` Laszlo Ersek

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