From ceb82e7d081399dd91cc6e0e8eabd5b7260afac0 Mon Sep 17 00:00:00 2001 From: Adttil <2429917001@qq.com> Date: Fri, 29 Nov 2024 08:35:27 +0800 Subject: [PATCH 1/3] VirtioDxe: add support of MMIO Bar for virtio devices As some virtio devices support MMIO BAR, add support for it in Virtio10Dxe and VirtioPciDeviceDXE. Signed-off-by: jiangdongxu --- OvmfPkg/Include/Protocol/VirtioDevice.h | 12 +++ .../VirtioMmioDeviceLib/VirtioMmioDevice.c | 1 + OvmfPkg/Virtio10Dxe/Virtio10.c | 1 + OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c | 89 +++++++++++++++---- 4 files changed, 85 insertions(+), 18 deletions(-) diff --git a/OvmfPkg/Include/Protocol/VirtioDevice.h b/OvmfPkg/Include/Protocol/VirtioDevice.h index ad37f4e3..802b8970 100644 --- a/OvmfPkg/Include/Protocol/VirtioDevice.h +++ b/OvmfPkg/Include/Protocol/VirtioDevice.h @@ -466,6 +466,16 @@ EFI_STATUS IN VOID *Mapping ); +/** + * Note: Zero virtio devices has BAR0 of type MMIO but not PIO which do not + * flow the virtio 0.95 spec due to hw limiation. We extend edk2 to support + * such variant. + */ +typedef enum { + VirtioCfgSpaceAcessIo = 0, + VirtioCfgSpaceAcessMem +} VIRTIO_CFG_SPACE_ACCESS_MODE; + /// /// This protocol provides an abstraction over the VirtIo transport layer /// @@ -482,6 +492,8 @@ struct _VIRTIO_DEVICE_PROTOCOL { // INT32 SubSystemDeviceId; + VIRTIO_CFG_SPACE_ACCESS_MODE CfgAccessMode; + VIRTIO_GET_DEVICE_FEATURES GetDeviceFeatures; VIRTIO_SET_GUEST_FEATURES SetGuestFeatures; diff --git a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c index fac32422..a340711d 100644 --- a/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c +++ b/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c @@ -17,6 +17,7 @@ STATIC CONST VIRTIO_DEVICE_PROTOCOL mMmioDeviceProtocolTemplate = { 0, // Revision 0, // SubSystemDeviceId + 0, // CfgAccessMode VirtioMmioGetDeviceFeatures, // GetDeviceFeatures VirtioMmioSetGuestFeatures, // SetGuestFeatures VirtioMmioSetQueueAddress, // SetQueueAddress diff --git a/OvmfPkg/Virtio10Dxe/Virtio10.c b/OvmfPkg/Virtio10Dxe/Virtio10.c index 970524f6..b968b016 100644 --- a/OvmfPkg/Virtio10Dxe/Virtio10.c +++ b/OvmfPkg/Virtio10Dxe/Virtio10.c @@ -954,6 +954,7 @@ Virtio10UnmapSharedBuffer ( STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = { VIRTIO_SPEC_REVISION (1, 0, 0), 0, // SubSystemDeviceId, filled in dynamically + 0, // CfgAccessMode Virtio10GetDeviceFeatures, Virtio10SetGuestFeatures, Virtio10SetQueueAddress, diff --git a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c index b4ac195b..61ff376d 100644 --- a/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c +++ b/OvmfPkg/VirtioPciDeviceDxe/VirtioPciDevice.c @@ -23,6 +23,7 @@ STATIC VIRTIO_DEVICE_PROTOCOL mDeviceProtocolTemplate = { 0, // Revision 0, // SubSystemDeviceId + 0, // CfgAccessMode VirtioPciGetDeviceFeatures, // GetDeviceFeatures VirtioPciSetGuestFeatures, // SetGuestFeatures VirtioPciSetQueueAddress, // SetQueueAddress @@ -117,14 +118,25 @@ VirtioPciIoRead ( return EFI_INVALID_PARAMETER; } - return PciIo->Io.Read ( - PciIo, - Width, - PCI_BAR_IDX0, - FieldOffset, - Count, - Buffer - ); + if (Dev->VirtioDevice.CfgAccessMode == VirtioCfgSpaceAcessIo) { + return PciIo->Io.Read ( + PciIo, + Width, + PCI_BAR_IDX0, + FieldOffset, + Count, + Buffer + ); + } else { + return PciIo->Mem.Read ( + PciIo, + Width, + PCI_BAR_IDX0, + FieldOffset, + Count, + Buffer + ); + } } /** @@ -197,14 +209,25 @@ VirtioPciIoWrite ( return EFI_INVALID_PARAMETER; } - return PciIo->Io.Write ( - PciIo, - Width, - PCI_BAR_IDX0, - FieldOffset, - Count, - &Value - ); + if (Dev->VirtioDevice.CfgAccessMode == VirtioCfgSpaceAcessIo) { + return PciIo->Io.Write ( + PciIo, + Width, + PCI_BAR_IDX0, + FieldOffset, + Count, + &Value + ); + } else { + return PciIo->Mem.Write ( + PciIo, + Width, + PCI_BAR_IDX0, + FieldOffset, + Count, + &Value + ); + } } /** @@ -332,6 +355,7 @@ VirtioPciInit ( EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; PCI_TYPE00 Pci; + VOID *Resources; ASSERT (Device != NULL); PciIo = Device->PciIo; @@ -373,6 +397,27 @@ VirtioPciInit ( Device->DeviceSpecificConfigurationOffset = VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI; + Status = PciIo->GetBarAttributes(PciIo, PCI_BAR_IDX0, NULL, &Resources); + if (EFI_ERROR (Status)) { + return Status; + } + + if (*(UINT8 *)Resources == ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR) { + EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR *Descriptor; + + Descriptor = Resources; + if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) { + Device->VirtioDevice.CfgAccessMode = VirtioCfgSpaceAcessMem; + DEBUG ((DEBUG_INFO, "%a: Legacy Virtio MMIO BAR used.\n", __FUNCTION__)); + } else { + Device->VirtioDevice.CfgAccessMode = VirtioCfgSpaceAcessIo; + DEBUG ((DEBUG_INFO, "%a: Legacy Virtio IO BAR used.\n", __FUNCTION__)); + } + } else { + DEBUG ((DEBUG_WARN, "%a: Cannot determine BAR0 type, assume IO.\n", __FUNCTION__)); + Device->VirtioDevice.CfgAccessMode = VirtioCfgSpaceAcessIo; + } + return EFI_SUCCESS; } @@ -434,6 +479,7 @@ VirtioPciDeviceBindingStart ( { VIRTIO_PCI_DEVICE *Device; EFI_STATUS Status; + UINT64 Attributes; Device = (VIRTIO_PCI_DEVICE *)AllocateZeroPool (sizeof *Device); if (Device == NULL) { @@ -473,11 +519,18 @@ VirtioPciDeviceBindingStart ( goto ClosePciIo; } + Status = Device->PciIo->Attributes (Device->PciIo, + EfiPciIoAttributeOperationSupported, + 0, &Attributes); + if (EFI_ERROR (Status)) { + goto ClosePciIo; + } + + Attributes &= (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_IO); Status = Device->PciIo->Attributes ( Device->PciIo, EfiPciIoAttributeOperationEnable, - (EFI_PCI_IO_ATTRIBUTE_IO | - EFI_PCI_IO_ATTRIBUTE_BUS_MASTER), + Attributes | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL ); if (EFI_ERROR (Status)) { -- 2.43.0