From: Daniil Egranov <daniil.egranov@arm.com>
To: edk2-devel@lists.01.org
Cc: leif.lindholm@linaro.org, ard.biesheuvel@linaro.org,
Daniil Egranov <daniil.egranov@arm.com>
Subject: [PATCH 4/4] VirtioPciDeviceDxe: Added non-discoverable Virtio support
Date: Tue, 6 Mar 2018 19:36:37 -0600 [thread overview]
Message-ID: <20180307013637.16462-5-daniil.egranov@arm.com> (raw)
In-Reply-To: <20180307013637.16462-1-daniil.egranov@arm.com>
The VirtioPciDeviceDxe was extended to support a non-discoverable
MMIO Virtio case.
The Virtio spec defines both PCI and MMIO device types with the
set of registers that are not the same between these two types
of devices. All PCI registers have corresponding MMIO registers
but the number of registers is less then MMIO. The width of MMIO
registers and PCI registers is not always the same.
Compared to PCI, MMIO Virtio devices required more registers to be
programmed in some cases. Added detection that a PCI device is
based on a non-discoverable device and allows MMIO transactions.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Daniil Egranov <daniil.egranov@arm.com>
---
OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c | 143 +++++++++++++++++++++-
OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h | 21 +++-
OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf | 4 +-
OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c | 117 +++++++++++++++++-
4 files changed, 278 insertions(+), 7 deletions(-)
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
index d4b4ec21c3..df2a4ea116 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c
@@ -4,7 +4,7 @@
Copyright (C) 2012, Red Hat, Inc.
Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>
- Copyright (C) 2013, ARM Ltd.
+ Copyright (C) 2013 - 2018, ARM Ltd.
Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
This program and the accompanying materials are licensed and made available
@@ -215,6 +215,147 @@ VirtioPciIoWrite (
/**
+ Read a word from Region 0 of the device specified by PciMemIo.
+
+ Region 0 must be an iomem region. This is an internal function for the PCI
+ implementation of the protocol.
+
+ @param[in] Dev Virtio PCI device.
+
+ @param[in] FieldOffset Source offset.
+
+ @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.
+
+ @param[in] BufferSize Number of bytes available in the target buffer. Must
+ equal FieldSize.
+
+ @param[out] Buffer Target buffer.
+
+
+ @return Status code returned by PciIo->Io.Read().
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioPciMemIoRead (
+ IN VIRTIO_PCI_DEVICE *Dev,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ UINTN Count;
+ EFI_PCI_IO_PROTOCOL_WIDTH Width;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ ASSERT (FieldSize == BufferSize);
+
+ PciIo = Dev->PciIo;
+ Count = 1;
+
+ switch (FieldSize) {
+ case 1:
+ Width = EfiPciIoWidthUint8;
+ break;
+
+ case 2:
+ Width = EfiPciIoWidthUint16;
+ break;
+
+ case 4:
+ Width = EfiPciIoWidthUint32;
+ break;
+
+ case 8:
+ Width = EfiPciIoWidthUint64;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciIo->Mem.Read (
+ PciIo,
+ Width,
+ PCI_BAR_IDX0,
+ FieldOffset,
+ Count,
+ Buffer
+ );
+}
+
+/**
+
+ Write a word into Region 0 of the device specified by PciMemIo.
+
+ Region 0 must be an iomem region. This is an internal function for the PCI
+ implementation of the protocol.
+
+ @param[in] Dev Virtio PCI device.
+
+ @param[in] FieldOffset Destination offset.
+
+ @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
+
+ @param[in] Value Little endian value to write, converted to UINT64.
+ The least significant FieldSize bytes will be used.
+
+
+ @return Status code returned by PciIo->Io.Write().
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioPciMemIoWrite (
+ IN VIRTIO_PCI_DEVICE *Dev,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ )
+{
+ UINTN Count;
+ EFI_PCI_IO_PROTOCOL_WIDTH Width;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ PciIo = Dev->PciIo;
+ Count = 1;
+
+ switch (FieldSize) {
+ case 1:
+ Width = EfiPciIoWidthUint8;
+ break;
+
+ case 2:
+ Width = EfiPciIoWidthUint16;
+ break;
+
+ case 4:
+ Width = EfiPciIoWidthUint32;
+ break;
+
+ case 8:
+ Width = EfiPciIoWidthUint64;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciIo->Mem.Write (
+ PciIo,
+ Width,
+ PCI_BAR_IDX0,
+ FieldOffset,
+ Count,
+ &Value
+ );
+}
+
+/**
+
Device probe function for this driver.
The DXE core calls this function for any given device in order to see if the
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
index 1f0dc45d50..e91191689c 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.h
@@ -2,7 +2,7 @@
Internal definitions for the VirtIo PCI Device driver
- Copyright (C) 2013, ARM Ltd
+ Copyright (C) 2013-2018, ARM Ltd
Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
This program and the accompanying materials are licensed and made available
@@ -58,6 +58,25 @@ VirtioPciIoWrite (
IN UINT64 Value
);
+EFI_STATUS
+EFIAPI
+VirtioPciMemIoRead (
+ IN VIRTIO_PCI_DEVICE *Dev,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioPciMemIoWrite (
+ IN VIRTIO_PCI_DEVICE *Dev,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ );
+
/********************************************
* PCI Functions for VIRTIO_DEVICE_PROTOCOL
*******************************************/
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
index 4b5d1a493e..675b156c82 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
@@ -2,7 +2,7 @@
# This driver produces the VirtIo Device Protocol instances for VirtIo PCI
# Device
#
-# Copyright (C) 2013, ARM Ltd
+# Copyright (C) 2013-2018, ARM Ltd
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
@@ -28,6 +28,7 @@
[Packages]
MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
OvmfPkg/OvmfPkg.dec
[LibraryClasses]
@@ -41,3 +42,4 @@
[Protocols]
gEfiPciIoProtocolGuid ## TO_START
gVirtioDeviceProtocolGuid ## BY_START
+ gEdkiiNonDiscoverableDeviceProtocolGuid
diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
index b52060d13d..45b49f0915 100644
--- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
+++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciFunctions.c
@@ -4,7 +4,7 @@
Copyright (C) 2012, Red Hat, Inc.
Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
- Copyright (C) 2013, ARM Ltd.
+ Copyright (C) 2013-2018, ARM Ltd.
Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
This program and the accompanying materials are licensed and made available
@@ -21,10 +21,76 @@
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
+
+#include <Protocol/NonDiscoverableDevice.h>
+
#include "VirtioPciDevice.h"
/**
+ Check if virtvo PCI device is a non discoverable virtio MMIO device.
+
+ @param[in] Dev Pointer to the virtio PCI device structure.
+
+ @return TRUE if PCI device is a non discoverable device.
+
+**/
+STATIC
+BOOLEAN
+VirtioIsNonDiscoverableMmioDevice (
+ IN VIRTIO_PCI_DEVICE *Dev
+ )
+{
+ EFI_HANDLE *HandleBuffer;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ NON_DISCOVERABLE_DEVICE *Device;
+ EFI_STATUS Status;
+ UINTN HIndex;
+ UINTN HandleCount;
+ BOOLEAN RetStatus;
+
+ RetStatus = FALSE;
+ Status = gBS->LocateHandleBuffer (ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer);
+
+ if (!EFI_ERROR (Status)) {
+ for (HIndex = 0; HIndex < HandleCount; ++HIndex) {
+ Status = gBS->OpenProtocol (HandleBuffer[HIndex],
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (PciIo == Dev->PciIo) {
+ Status = gBS->OpenProtocol (HandleBuffer[HIndex],
+ &gEdkiiNonDiscoverableDeviceProtocolGuid,
+ (VOID **) &Device,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (!EFI_ERROR (Status)) {
+ RetStatus = TRUE;
+ }
+ break;
+ }
+ }
+ }
+
+ gBS->FreePool (HandleBuffer);
+ return RetStatus;
+}
+
+/**
+
Read a word from Region 0 of the device specified by VirtIo Device protocol.
The function implements the ReadDevice protocol member of
@@ -219,7 +285,21 @@ VirtioPciSetQueueAlignment (
IN UINT32 Alignment
)
{
- return EFI_SUCCESS;
+ VIRTIO_PCI_DEVICE *Dev;
+ EFI_STATUS Status;
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+ Status = EFI_SUCCESS;
+
+ // This register is required to be programmed for MMIO type of devices.
+ // Virtio MMIO device can be registered as a non-discoverable device on
+ // PCI bus, check if it's the case.
+ if (VirtioIsNonDiscoverableMmioDevice (Dev)) {
+ Status = VirtioPciMemIoWrite (Dev, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN,
+ sizeof (UINT32), Alignment);
+ }
+
+ return Status;
}
EFI_STATUS
@@ -229,7 +309,22 @@ VirtioPciSetPageSize (
IN UINT32 PageSize
)
{
- return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
+ VIRTIO_PCI_DEVICE *Dev;
+ EFI_STATUS Status;
+
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+
+ // This register is required to be programmed for MMIO type of devices.
+ // Virtio MMIO device can be registered as a non-discoverable device on
+ // PCI bus, check if it's the case.
+ if (VirtioIsNonDiscoverableMmioDevice (Dev)) {
+ Status = VirtioPciMemIoWrite (Dev, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE,
+ sizeof (UINT32), PageSize);
+ } else {
+ Status = (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
+ }
+
+ return Status;
}
EFI_STATUS
@@ -254,11 +349,25 @@ VirtioPciSetQueueSize (
IN UINT16 Size
)
{
+ VIRTIO_PCI_DEVICE *Dev;
+ EFI_STATUS Status;
+
//
// This function is only applicable in Virtio-MMIO.
// (The QueueSize field is read-only in Virtio proper (PCI))
//
- return EFI_SUCCESS;
+ Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
+ Status = EFI_SUCCESS;
+
+ // This register is required to be programmed for MMIO type of devices.
+ // Virtio MMIO device can be registered as a non-discoverable device on
+ // PCI bus, check if it's the case.
+ if (VirtioIsNonDiscoverableMmioDevice (Dev)) {
+ Status = VirtioPciMemIoWrite (Dev, VIRTIO_MMIO_OFFSET_QUEUE_NUM,
+ sizeof (UINT32), (UINT32) Size);
+ }
+
+ return Status;
}
EFI_STATUS
--
2.11.0
next prev parent reply other threads:[~2018-03-07 1:30 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-07 1:36 [PATCH 0/4] Virtio non-discoverable devices Daniil Egranov
2018-03-07 1:36 ` [PATCH 1/4] MdeModulePkg: Added new Virtio non-discoverable type and GUID Daniil Egranov
2018-03-07 1:36 ` [PATCH 2/4] NonDiscoverableDeviceRegistrationLib: Added Virtio support Daniil Egranov
2018-03-07 1:36 ` [PATCH 3/4] NonDiscoverablePciDeviceDxe: Added MMIO " Daniil Egranov
2018-03-07 1:36 ` Daniil Egranov [this message]
2018-03-07 8:03 ` [PATCH 0/4] Virtio non-discoverable devices Ard Biesheuvel
2018-03-07 20:18 ` Laszlo Ersek
2018-03-08 8:21 ` Daniil Egranov
2018-03-08 8:29 ` Ard Biesheuvel
2018-03-12 6:19 ` Daniil Egranov
2018-03-12 7:31 ` Ard Biesheuvel
2018-03-07 10:56 ` Laszlo Ersek
2018-03-13 2:55 ` Daniil Egranov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180307013637.16462-5-daniil.egranov@arm.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox