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 3/4] NonDiscoverablePciDeviceDxe: Added MMIO Virtio support
Date: Tue, 6 Mar 2018 19:36:36 -0600 [thread overview]
Message-ID: <20180307013637.16462-4-daniil.egranov@arm.com> (raw)
In-Reply-To: <20180307013637.16462-1-daniil.egranov@arm.com>
Added PCI IO to MMIO translation for Virtio case into the PCI IO
protocol functions.
Added Virtio device type into the PCI IO protocol initialization
procedure.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Daniil Egranov <daniil.egranov@arm.com>
---
.../NonDiscoverablePciDeviceDxe.c | 3 +-
.../NonDiscoverablePciDeviceDxe.inf | 5 +-
.../NonDiscoverablePciDeviceIo.c | 240 ++++++++++++++++++++-
3 files changed, 241 insertions(+), 7 deletions(-)
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
index 3e9ff6620d..2c3eeca914 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.c
@@ -1,6 +1,6 @@
/** @file
- Copyright (C) 2016, Linaro Ltd. All rights reserved.<BR>
+ Copyright (C) 2016-2018, Linaro Ltd. 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
@@ -32,6 +32,7 @@ SupportedNonDiscoverableDevices[] = {
&gEdkiiNonDiscoverableUfsDeviceGuid,
&gEdkiiNonDiscoverableUhciDeviceGuid,
&gEdkiiNonDiscoverableXhciDeviceGuid,
+ &gEdkiiNonDiscoverableVirtioDeviceGuid
};
//
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
index ac551a82ab..a7bf5a5fc1 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
@@ -1,7 +1,7 @@
## @file
# PCI I/O driver for non-discoverable devices.
#
-# Copyright (C) 2016, Linaro Ltd.
+# Copyright (C) 2016-2018, Linaro Ltd.
#
# This program and the accompanying materials are licensed and made available
# under the terms and conditions of the BSD License which accompanies this
@@ -30,6 +30,7 @@
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
+ OvmfPkg/OvmfPkg.dec
[LibraryClasses]
BaseMemoryLib
@@ -54,3 +55,5 @@
gEdkiiNonDiscoverableUfsDeviceGuid ## CONSUMES ## GUID
gEdkiiNonDiscoverableUhciDeviceGuid ## CONSUMES ## GUID
gEdkiiNonDiscoverableXhciDeviceGuid ## CONSUMES ## GUID
+ gEdkiiNonDiscoverableVirtioDeviceGuid ## CONSUMES ## GUID
+
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
index 0e42ae4bf6..cb99bf0ba6 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
@@ -1,7 +1,7 @@
/** @file
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
- Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>
+ Copyright (c) 2016-2018, Linaro, Ltd. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -17,8 +17,12 @@
#include <Library/DxeServicesTableLib.h>
+#include <Library/IoLib.h>
+
#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/Virtio.h>
+
#include <Protocol/PciRootBridgeIo.h>
typedef struct {
@@ -374,6 +378,82 @@ PciIoMemWrite (
}
/**
+ Translate PCI IO to MMIO for VirtIo Non-Discoverable devices.
+
+ @param BaseAddress A base MMIO memory address of a VirtIo device.
+ @param PciIoOffset PCI IO offset.
+ @param DevConfigAddress The address is a device specific config space.
+
+ @retval EFI_SUCCESS The address translated successfully.
+ @retval EFI_UNSUPPORTED The PCI IO address can not be translated.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+VirtioPciIoToMemIoTranslation (
+ IN UINTN BaseAddress,
+ IN UINTN PciIoOffset,
+ IN OUT UINTN *Address,
+ IN OUT BOOLEAN *DevConfigAddress
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ INTN DevConfigSpaceOffset;
+
+ Status = EFI_SUCCESS;
+ Offset = PciIoOffset;
+ *DevConfigAddress = FALSE;
+ DevConfigSpaceOffset = 0;
+
+ //
+ //Check if it's device specific config space
+ //
+ if (PciIoOffset >= VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI ) {
+ Offset = VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI;
+ DevConfigSpaceOffset = PciIoOffset - VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI;
+ *DevConfigAddress = TRUE;
+ }
+
+ switch (Offset) {
+ case VIRTIO_PCI_OFFSET_DEVICE_FEATURES:
+ *Address = BaseAddress + VIRTIO_MMIO_OFFSET_HOST_FEATURES;
+ break;
+ case VIRTIO_PCI_OFFSET_GUEST_FEATURES:
+ *Address = BaseAddress + VIRTIO_MMIO_OFFSET_GUEST_FEATURES;
+ break;
+ case VIRTIO_PCI_OFFSET_QUEUE_ADDRESS:
+ *Address = BaseAddress + VIRTIO_MMIO_OFFSET_QUEUE_PFN;
+ break;
+ case VIRTIO_PCI_OFFSET_QUEUE_SIZE:
+ *Address = BaseAddress + VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX;
+ break;
+ case VIRTIO_PCI_OFFSET_QUEUE_SELECT:
+ *Address = BaseAddress + VIRTIO_MMIO_OFFSET_QUEUE_SEL;
+ break;
+ case VIRTIO_PCI_OFFSET_QUEUE_NOTIFY:
+ *Address = BaseAddress + VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY;
+ break;
+ case VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS:
+ *Address = BaseAddress + VIRTIO_MMIO_OFFSET_STATUS;
+ break;
+ case VIRTIO_PCI_OFFSET_QUEUE_DEVICE_ISR:
+ Status = EFI_UNSUPPORTED;
+ break;
+ case VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI:
+ case VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI_WITH_MSI_X:
+ *Address = BaseAddress + VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + DevConfigSpaceOffset;
+ break;
+ default:
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ return Status;
+}
+
+/**
Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space.
@param This A pointer to the EFI_PCI_IO_PROTOCOL instance.
@@ -398,8 +478,72 @@ PciIoIoRead (
IN OUT VOID *Buffer
)
{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+ UINTN Length;
+ UINTN Address;
+ UINT32 ReadData;
+ BOOLEAN IsDevConfigSpace;
+ EFI_STATUS Status;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This);
+
+ //
+ // Only allow accesses to the BARs we emulate
+ //
+ Status = GetBarResource (Dev, BarIndex, &Desc);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Length = Count << ((UINTN)Width & 0x3);
+ if (Offset + Length > Desc->AddrLen) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Non-Discoverable devices are MMIO devices. Translate PCI IO requests to MMIO.
+ //
+
+ //
+ // VirtIo
+ //
+ if (CompareGuid (Dev->Device->Type, &gEdkiiNonDiscoverableVirtioDeviceGuid)) {
+ //
+ // Check for a valid data size
+ //
+ if ((Length != 1) && (Length != 2) &&
+ (Length != 4) && (Length != 8)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = VirtioPciIoToMemIoTranslation (Desc->AddrRangeMin, Offset, &Address, &IsDevConfigSpace);
+ if (!EFI_ERROR (Status)) {
+ if (IsDevConfigSpace == TRUE) { // Device-specific configuration registers
+ //
+ // The device-specific memory area of Virtio-MMIO can only be written in
+ // byte accesses. This is not currently in the Virtio spec.
+ //
+ MmioReadBuffer8 (Address, Length, Buffer);
+ } else if (Length < 8) { // 32-bit MMIO registers
+ ReadData = MmioRead32 (Address);
+ // The PCI IO register width may not be the same as MMIO register.
+ // Virtio MMIO registers are always 32-bit
+ CopyMem (Buffer, &ReadData, Length);
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
}
/**
@@ -427,8 +571,72 @@ PciIoIoWrite (
IN OUT VOID *Buffer
)
{
- ASSERT (FALSE);
- return EFI_UNSUPPORTED;
+ NON_DISCOVERABLE_PCI_DEVICE *Dev;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+ UINTN Length;
+ UINTN Address;
+ UINT32 WriteData;
+ BOOLEAN IsDevConfigSpace;
+ EFI_STATUS Status;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This);
+
+ //
+ // Only allow accesses to the BARs we emulate
+ //
+ Status = GetBarResource (Dev, BarIndex, &Desc);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Length = Count << ((UINTN)Width & 0x3);
+ if (Offset + Length > Desc->AddrLen) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Non-Discoverable devices are MMIO devices. Translate PCI IO requests to MMIO.
+ //
+
+ //
+ // VirtIo
+ //
+ if (CompareGuid (Dev->Device->Type, &gEdkiiNonDiscoverableVirtioDeviceGuid)) {
+ //
+ // Check for a valid data size
+ //
+ if ((Length != 1) && (Length != 2) &&
+ (Length != 4) && (Length != 8)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = VirtioPciIoToMemIoTranslation (Desc->AddrRangeMin, Offset, &Address, &IsDevConfigSpace);
+ if (!EFI_ERROR (Status)) {
+ if (IsDevConfigSpace == TRUE) { // Device-specific configuration registers
+ //
+ // The device-specific memory area of Virtio-MMIO can only be written in
+ // byte accesses. This is not currently in the Virtio spec.
+ //
+ MmioWriteBuffer8 (Address, Length, Buffer);
+ } else if (Length < 8) { // 32-bit MMIO registers
+ // The PCI IO register width may not be the same as MMIO register.
+ // Virtio MMIO registers are always 32-bit
+ CopyMem (&WriteData, Buffer, Length);
+ MmioWrite32 (Address, WriteData);
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ return Status;
}
/**
@@ -1408,6 +1616,7 @@ InitializePciIoProtocol (
{
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
INTN Idx;
+ UINT32 VirtioMagicValue;
InitializeListHead (&Dev->UncachedAllocationList);
@@ -1471,6 +1680,15 @@ InitializePciIoProtocol (
Dev->ConfigSpace.Hdr.ClassCode[1] = 0x9; // UFS controller subclass;
Dev->ConfigSpace.Hdr.ClassCode[2] = PCI_CLASS_MASS_STORAGE;
Dev->BarOffset = 0;
+ } else if (CompareGuid (Dev->Device->Type,
+ &gEdkiiNonDiscoverableVirtioDeviceGuid)) {
+ Dev->ConfigSpace.Hdr.VendorId = VIRTIO_VENDOR_ID; // Required Virtio vendor
+ Dev->ConfigSpace.Hdr.DeviceId = 0x1000; // Required Virtio device id
+ Dev->ConfigSpace.Hdr.RevisionID = 0x0;
+ Dev->ConfigSpace.Hdr.ClassCode[0] = 0x0; // don't care
+ Dev->ConfigSpace.Hdr.ClassCode[1] = 0x0; // don't care
+ Dev->ConfigSpace.Hdr.ClassCode[2] = 0x0; // don't care
+ Dev->BarOffset = 0;
} else {
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
}
@@ -1496,6 +1714,18 @@ InitializePciIoProtocol (
}
Dev->ConfigSpace.Device.Bar[Idx] = (UINT32)Desc->AddrRangeMin;
+
+ //
+ // Initialize Virtio device Id
+ //
+ if (CompareGuid (Dev->Device->Type, &gEdkiiNonDiscoverableVirtioDeviceGuid)) {
+ VirtioMagicValue = MmioRead32 (Dev->ConfigSpace.Device.Bar[Idx] + VIRTIO_MMIO_OFFSET_MAGIC);
+ if (VirtioMagicValue == VIRTIO_MMIO_MAGIC) {
+ Dev->ConfigSpace.Device.SubsystemID = MmioRead32 (Dev->ConfigSpace.Device.Bar[Idx] +
+ VIRTIO_MMIO_OFFSET_DEVICE_ID);
+ }
+ }
+
Dev->BarCount++;
if (Desc->AddrSpaceGranularity == 64) {
--
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 ` Daniil Egranov [this message]
2018-03-07 1:36 ` [PATCH 4/4] VirtioPciDeviceDxe: Added non-discoverable " Daniil Egranov
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-4-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