From: Laszlo Ersek <lersek@redhat.com>
To: Anthony PERARD <anthony.perard@citrix.com>,
edk2-devel@ml01.01.org, xen-devel@lists.xenproject.org
Subject: Re: [PATCH RFC 05/14] OvmfPkg/Library: add XenPciHostBridgeLib
Date: Thu, 5 Jan 2017 11:15:46 +0100 [thread overview]
Message-ID: <4f7db46c-1728-076b-64eb-afba6b4864bb@redhat.com> (raw)
In-Reply-To: <20161208153340.2285-6-anthony.perard@citrix.com>
On 12/08/16 16:33, Anthony PERARD wrote:
> A copy of OvmfPkg/Library/PciHostBridgeLib
>
> Removing support for pci bus enumeration, I think, and only use scan of
> already enumerated pci bus.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> ---
> .../Library/XenPciHostBridgeLib/XenPciHostBridge.h | 75 ++++
> .../XenPciHostBridgeLib/XenPciHostBridgeLib.c | 291 +++++++++++++
> .../XenPciHostBridgeLib/XenPciHostBridgeLib.inf | 58 +++
> OvmfPkg/Library/XenPciHostBridgeLib/XenSupport.c | 456 +++++++++++++++++++++
> 4 files changed, 880 insertions(+)
> create mode 100644 OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridge.h
> create mode 100644 OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.c
> create mode 100644 OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.inf
> create mode 100644 OvmfPkg/Library/XenPciHostBridgeLib/XenSupport.c
(1) I think the following subject line is more idiomatic:
OvmfPkg: add XenPciHostBridgeLib
Then, I'll practically repeat my comments for the previous patch:
(2) You might want to add Citrix copyright notices to new files.
(3) The Xen-related code that remains in the original PciHostBridgeLib
instance should be possible to remove later; if that's the case, can you
please write a subsequent patch for that too?
(4) The removed functionality should be named more precisely in the
commit message:
- PciHostBridgeGetRootBridges(): the search for extra PCI root buses
(which come from QEMU's pxb and pxb-pcie devices) is removed (hence the
"etc/extra-pci-roots" fw_cfg file is no longer consulted either, which
is otherwise used to speed up the search).
The Xen-specific ScanForRootBridges() function call is hardwired.
(5) It would be nice to hint at the reason (which is implemented in a
later patch) why a separate module is a good idea here. That is, why the
expected PVH2 functionality is best not added to the current
PciHostBridgeLib instance.
More below:
> diff --git a/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridge.h b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridge.h
> new file mode 100644
> index 0000000..c23d40c
> --- /dev/null
> +++ b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridge.h
> @@ -0,0 +1,75 @@
> +/** @file
> + Header file of OVMF instance of PciHostBridgeLib.
> +
> + Copyright (c) 2016, Intel Corporation. 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
> + distribution. The full text of the license may be found at
> + http://opensource.org/licenses/bsd-license.php.
> +
> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
> + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +
> +PCI_ROOT_BRIDGE *
> +ScanForRootBridges (
> + UINTN *NumberOfRootBridges
> +);
> +
> +/**
> + Initialize a PCI_ROOT_BRIDGE structure.
> +
> + @param[in] Supports Supported attributes.
> +
> + @param[in] Attributes Initial attributes.
> +
> + @param[in] AllocAttributes Allocation attributes.
> +
> + @param[in] RootBusNumber The bus number to store in RootBus.
> +
> + @param[in] MaxSubBusNumber The inclusive maximum bus number that can be
> + assigned to any subordinate bus found behind any
> + PCI bridge hanging off this root bus.
> +
> + The caller is repsonsible for ensuring that
> + RootBusNumber <= MaxSubBusNumber. If
> + RootBusNumber equals MaxSubBusNumber, then the
> + root bus has no room for subordinate buses.
> +
> + @param[in] Io IO aperture.
> +
> + @param[in] Mem MMIO aperture.
> +
> + @param[in] MemAbove4G MMIO aperture above 4G.
> +
> + @param[in] PMem Prefetchable MMIO aperture.
> +
> + @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
> +
> + @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the
> + caller) that should be filled in by this
> + function.
> +
> + @retval EFI_SUCCESS Initialization successful. A device path
> + consisting of an ACPI device path node, with
> + UID = RootBusNumber, has been allocated and
> + linked into RootBus.
> +
> + @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
> +**/
> +EFI_STATUS
> +InitRootBridge (
> + IN UINT64 Supports,
> + IN UINT64 Attributes,
> + IN UINT64 AllocAttributes,
> + IN UINT8 RootBusNumber,
> + IN UINT8 MaxSubBusNumber,
> + IN PCI_ROOT_BRIDGE_APERTURE *Io,
> + IN PCI_ROOT_BRIDGE_APERTURE *Mem,
> + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
> + IN PCI_ROOT_BRIDGE_APERTURE *PMem,
> + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
> + OUT PCI_ROOT_BRIDGE *RootBus
> + );
> diff --git a/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.c b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.c
> new file mode 100644
> index 0000000..efcd830
> --- /dev/null
> +++ b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.c
> @@ -0,0 +1,291 @@
> +/** @file
> + OVMF's instance of the PCI Host Bridge Library.
> +
> + Copyright (C) 2016, Red Hat, Inc.
> + Copyright (c) 2016, Intel Corporation. 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
> + distribution. The full text of the license may be found at
> + http://opensource.org/licenses/bsd-license.php.
> +
> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
> + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +#include <PiDxe.h>
> +
> +#include <IndustryStandard/Pci.h>
> +#include <IndustryStandard/Q35MchIch9.h>
> +
> +#include <Protocol/PciHostBridgeResourceAllocation.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PciHostBridgeLib.h>
> +#include <Library/PciLib.h>
> +#include <Library/QemuFwCfgLib.h>
> +#include "XenPciHostBridge.h"
> +
> +
> +#pragma pack(1)
> +typedef struct {
> + ACPI_HID_DEVICE_PATH AcpiDevicePath;
> + EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
> +} OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH;
> +#pragma pack ()
> +
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
> + L"Mem", L"I/O", L"Bus"
> +};
> +
> +
> +STATIC
> +CONST
> +OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
> + {
> + {
> + ACPI_DEVICE_PATH,
> + ACPI_DP,
> + {
> + (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
> + (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
> + }
> + },
> + EISA_PNP_ID(0x0A03), // HID
> + 0 // UID
> + },
> +
> + {
> + END_DEVICE_PATH_TYPE,
> + END_ENTIRE_DEVICE_PATH_SUBTYPE,
> + {
> + END_DEVICE_PATH_LENGTH,
> + 0
> + }
> + }
> +};
> +
> +/**
> + Initialize a PCI_ROOT_BRIDGE structure.
> +
> + @param[in] Supports Supported attributes.
> +
> + @param[in] Attributes Initial attributes.
> +
> + @param[in] AllocAttributes Allocation attributes.
> +
> + @param[in] RootBusNumber The bus number to store in RootBus.
> +
> + @param[in] MaxSubBusNumber The inclusive maximum bus number that can be
> + assigned to any subordinate bus found behind any
> + PCI bridge hanging off this root bus.
> +
> + The caller is repsonsible for ensuring that
> + RootBusNumber <= MaxSubBusNumber. If
> + RootBusNumber equals MaxSubBusNumber, then the
> + root bus has no room for subordinate buses.
> +
> + @param[in] Io IO aperture.
> +
> + @param[in] Mem MMIO aperture.
> +
> + @param[in] MemAbove4G MMIO aperture above 4G.
> +
> + @param[in] PMem Prefetchable MMIO aperture.
> +
> + @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
> +
> + @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the
> + caller) that should be filled in by this
> + function.
> +
> + @retval EFI_SUCCESS Initialization successful. A device path
> + consisting of an ACPI device path node, with
> + UID = RootBusNumber, has been allocated and
> + linked into RootBus.
> +
> + @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
> +**/
> +EFI_STATUS
> +InitRootBridge (
> + IN UINT64 Supports,
> + IN UINT64 Attributes,
> + IN UINT64 AllocAttributes,
> + IN UINT8 RootBusNumber,
> + IN UINT8 MaxSubBusNumber,
> + IN PCI_ROOT_BRIDGE_APERTURE *Io,
> + IN PCI_ROOT_BRIDGE_APERTURE *Mem,
> + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
> + IN PCI_ROOT_BRIDGE_APERTURE *PMem,
> + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
> + OUT PCI_ROOT_BRIDGE *RootBus
> + )
> +{
> + OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
> +
> + //
> + // Be safe if other fields are added to PCI_ROOT_BRIDGE later.
> + //
> + ZeroMem (RootBus, sizeof *RootBus);
> +
> + RootBus->Segment = 0;
> +
> + RootBus->Supports = Supports;
> + RootBus->Attributes = Attributes;
> +
> + RootBus->DmaAbove4G = FALSE;
> +
> + RootBus->AllocationAttributes = AllocAttributes;
> + RootBus->Bus.Base = RootBusNumber;
> + RootBus->Bus.Limit = MaxSubBusNumber;
> + CopyMem (&RootBus->Io, Io, sizeof (*Io));
> + CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));
> + CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G));
> + CopyMem (&RootBus->PMem, PMem, sizeof (*PMem));
> + CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G));
> +
> + RootBus->NoExtendedConfigSpace = (PcdGet16 (PcdOvmfHostBridgePciDevId) !=
> + INTEL_Q35_MCH_DEVICE_ID);
> +
> + DevicePath = AllocateCopyPool (sizeof mRootBridgeDevicePathTemplate,
> + &mRootBridgeDevicePathTemplate);
> + if (DevicePath == NULL) {
> + DEBUG ((EFI_D_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
> + return EFI_OUT_OF_RESOURCES;
> + }
> + DevicePath->AcpiDevicePath.UID = RootBusNumber;
> + RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
> +
> + DEBUG ((EFI_D_INFO,
> + "%a: populated root bus %d, with room for %d subordinate bus(es)\n",
> + __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
> + return EFI_SUCCESS;
> +}
> +
> +
> +/**
> + Uninitialize a PCI_ROOT_BRIDGE structure set up with InitRootBridge().
> +
> + param[in] RootBus The PCI_ROOT_BRIDGE structure, allocated by the caller and
> + initialized with InitRootBridge(), that should be
> + uninitialized. This function doesn't free RootBus.
> +**/
> +STATIC
> +VOID
> +UninitRootBridge (
> + IN PCI_ROOT_BRIDGE *RootBus
> + )
> +{
> + FreePool (RootBus->DevicePath);
> +}
> +
> +
> +/**
> + Return all the root bridge instances in an array.
> +
> + @param Count Return the count of root bridge instances.
> +
> + @return All the root bridge instances in an array.
> + The array should be passed into PciHostBridgeFreeRootBridges()
> + when it's not used.
> +**/
> +PCI_ROOT_BRIDGE *
> +EFIAPI
> +PciHostBridgeGetRootBridges (
> + UINTN *Count
> + )
> +{
> + ASSERT (PcdGetBool (PcdPciDisableBusEnumeration));
> + return ScanForRootBridges (Count);
> +}
> +
> +
> +/**
> + Free the root bridge instances array returned from
> + PciHostBridgeGetRootBridges().
> +
> + @param The root bridge instances array.
> + @param The count of the array.
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeFreeRootBridges (
> + PCI_ROOT_BRIDGE *Bridges,
> + UINTN Count
> + )
> +{
> + if (Bridges == NULL && Count == 0) {
> + return;
> + }
> + ASSERT (Bridges != NULL && Count > 0);
> +
> + do {
> + --Count;
> + UninitRootBridge (&Bridges[Count]);
> + } while (Count > 0);
> +
> + FreePool (Bridges);
> +}
> +
> +
> +/**
> + Inform the platform that the resource conflict happens.
> +
> + @param HostBridgeHandle Handle of the Host Bridge.
> + @param Configuration Pointer to PCI I/O and PCI memory resource
> + descriptors. The Configuration contains the resources
> + for all the root bridges. The resource for each root
> + bridge is terminated with END descriptor and an
> + additional END is appended indicating the end of the
> + entire resources. The resource descriptor field
> + values follow the description in
> + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
> + .SubmitResources().
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeResourceConflict (
> + EFI_HANDLE HostBridgeHandle,
> + VOID *Configuration
> + )
> +{
> + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
> + UINTN RootBridgeIndex;
> + DEBUG ((EFI_D_ERROR, "PciHostBridge: Resource conflict happens!\n"));
> +
> + RootBridgeIndex = 0;
> + Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
> + while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
> + DEBUG ((EFI_D_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
> + for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
> + ASSERT (Descriptor->ResType <
> + ARRAY_SIZE (mPciHostBridgeLibAcpiAddressSpaceTypeStr)
> + );
> + DEBUG ((EFI_D_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
> + mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
> + Descriptor->AddrLen, Descriptor->AddrRangeMax
> + ));
> + if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
> + DEBUG ((EFI_D_ERROR, " Granularity/SpecificFlag = %ld / %02x%s\n",
> + Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
> + ((Descriptor->SpecificFlag &
> + EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
> + ) != 0) ? L" (Prefetchable)" : L""
> + ));
> + }
> + }
> + //
> + // Skip the END descriptor for root bridge
> + //
> + ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
> + Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
> + (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
> + );
> + }
> +}
> diff --git a/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.inf b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.inf
> new file mode 100644
> index 0000000..3b8f003
> --- /dev/null
> +++ b/OvmfPkg/Library/XenPciHostBridgeLib/XenPciHostBridgeLib.inf
> @@ -0,0 +1,58 @@
> +## @file
> +# OVMF's instance of the PCI Host Bridge Library.
> +#
> +# Copyright (C) 2016, Red Hat, Inc.
> +# Copyright (c) 2016, Intel Corporation. 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
> +# distribution. The full text of the license may be found at
> +# http://opensource.org/licenses/bsd-license.php
> +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
> +# IMPLIED.
> +#
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = XenPciHostBridgeLib
> + FILE_GUID = 9F2BC05E-51EA-4AED-9A3E-7699641734E8
(6) You forgot to generate a new FILE_GUID with uuidgen.
Thanks
Laszlo
> + MODULE_TYPE = DXE_DRIVER
> + VERSION_STRING = 1.0
> + LIBRARY_CLASS = PciHostBridgeLib
> +
> +#
> +# The following information is for reference only and not required by the build
> +# tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64 IPF EBC
> +#
> +
> +[Sources]
> + XenPciHostBridgeLib.c
> + XenSupport.c
> + XenPciHostBridge.h
> +
> +[Packages]
> + MdeModulePkg/MdeModulePkg.dec
> + MdePkg/MdePkg.dec
> + OvmfPkg/OvmfPkg.dec
> +
> +[LibraryClasses]
> + BaseMemoryLib
> + DebugLib
> + DevicePathLib
> + MemoryAllocationLib
> + PciLib
> +
> +[Pcd]
> + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase
> + gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize
> + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base
> + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size
> + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base
> + gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size
> + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
> + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
> diff --git a/OvmfPkg/Library/XenPciHostBridgeLib/XenSupport.c b/OvmfPkg/Library/XenPciHostBridgeLib/XenSupport.c
> new file mode 100644
> index 0000000..a45945f
> --- /dev/null
> +++ b/OvmfPkg/Library/XenPciHostBridgeLib/XenSupport.c
> @@ -0,0 +1,456 @@
> +/** @file
> + Scan the entire PCI bus for root bridges to support OVMF above Xen.
> +
> + Copyright (c) 2016, Intel Corporation. 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
> + distribution. The full text of the license may be found at
> + http://opensource.org/licenses/bsd-license.php.
> +
> + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
> + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +
> +**/
> +#include <PiDxe.h>
> +
> +#include <IndustryStandard/Pci.h>
> +#include <IndustryStandard/Q35MchIch9.h>
> +
> +#include <Protocol/PciHostBridgeResourceAllocation.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PciHostBridgeLib.h>
> +#include <Library/PciLib.h>
> +#include "XenPciHostBridge.h"
> +
> +STATIC
> +VOID
> +PcatPciRootBridgeBarExisted (
> + IN UINTN Address,
> + OUT UINT32 *OriginalValue,
> + OUT UINT32 *Value
> + )
> +{
> + //
> + // Preserve the original value
> + //
> + *OriginalValue = PciRead32 (Address);
> +
> + //
> + // Disable timer interrupt while the BAR is probed
> + //
> + DisableInterrupts ();
> +
> + PciWrite32 (Address, 0xFFFFFFFF);
> + *Value = PciRead32 (Address);
> + PciWrite32 (Address, *OriginalValue);
> +
> + //
> + // Enable interrupt
> + //
> + EnableInterrupts ();
> +}
> +
> +STATIC
> +VOID
> +PcatPciRootBridgeParseBars (
> + IN UINT16 Command,
> + IN UINTN Bus,
> + IN UINTN Device,
> + IN UINTN Function,
> + IN UINTN BarOffsetBase,
> + IN UINTN BarOffsetEnd,
> + IN PCI_ROOT_BRIDGE_APERTURE *Io,
> + IN PCI_ROOT_BRIDGE_APERTURE *Mem,
> + IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
> + IN PCI_ROOT_BRIDGE_APERTURE *PMem,
> + IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G
> +
> +)
> +{
> + UINT32 OriginalValue;
> + UINT32 Value;
> + UINT32 OriginalUpperValue;
> + UINT32 UpperValue;
> + UINT64 Mask;
> + UINTN Offset;
> + UINT64 Base;
> + UINT64 Length;
> + UINT64 Limit;
> + PCI_ROOT_BRIDGE_APERTURE *MemAperture;
> +
> + for (Offset = BarOffsetBase; Offset < BarOffsetEnd; Offset += sizeof (UINT32)) {
> + PcatPciRootBridgeBarExisted (
> + PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
> + &OriginalValue, &Value
> + );
> + if (Value == 0) {
> + continue;
> + }
> + if ((Value & BIT0) == BIT0) {
> + //
> + // IO Bar
> + //
> + if (Command & EFI_PCI_COMMAND_IO_SPACE) {
> + Mask = 0xfffffffc;
> + Base = OriginalValue & Mask;
> + Length = ((~(Value & Mask)) & Mask) + 0x04;
> + if (!(Value & 0xFFFF0000)) {
> + Length &= 0x0000FFFF;
> + }
> + Limit = Base + Length - 1;
> +
> + if (Base < Limit) {
> + if (Io->Base > Base) {
> + Io->Base = Base;
> + }
> + if (Io->Limit < Limit) {
> + Io->Limit = Limit;
> + }
> + }
> + }
> + } else {
> + //
> + // Mem Bar
> + //
> + if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
> +
> + Mask = 0xfffffff0;
> + Base = OriginalValue & Mask;
> + Length = Value & Mask;
> +
> + if ((Value & (BIT1 | BIT2)) == 0) {
> + //
> + // 32bit
> + //
> + Length = ((~Length) + 1) & 0xffffffff;
> +
> + if ((Value & BIT3) == BIT3) {
> + MemAperture = PMem;
> + } else {
> + MemAperture = Mem;
> + }
> + } else {
> + //
> + // 64bit
> + //
> + Offset += 4;
> + PcatPciRootBridgeBarExisted (
> + PCI_LIB_ADDRESS (Bus, Device, Function, Offset),
> + &OriginalUpperValue,
> + &UpperValue
> + );
> +
> + Base = Base | LShiftU64 ((UINT64) OriginalUpperValue, 32);
> + Length = Length | LShiftU64 ((UINT64) UpperValue, 32);
> + Length = (~Length) + 1;
> +
> + if ((Value & BIT3) == BIT3) {
> + MemAperture = PMemAbove4G;
> + } else {
> + MemAperture = MemAbove4G;
> + }
> + }
> +
> + Limit = Base + Length - 1;
> + if (Base < Limit) {
> + if (MemAperture->Base > Base) {
> + MemAperture->Base = Base;
> + }
> + if (MemAperture->Limit < Limit) {
> + MemAperture->Limit = Limit;
> + }
> + }
> + }
> + }
> + }
> +}
> +
> +PCI_ROOT_BRIDGE *
> +ScanForRootBridges (
> + UINTN *NumberOfRootBridges
> + )
> +{
> + UINTN PrimaryBus;
> + UINTN SubBus;
> + UINT8 Device;
> + UINT8 Function;
> + UINTN NumberOfDevices;
> + UINTN Address;
> + PCI_TYPE01 Pci;
> + UINT64 Attributes;
> + UINT64 Base;
> + UINT64 Limit;
> + UINT64 Value;
> + PCI_ROOT_BRIDGE_APERTURE Io, Mem, MemAbove4G, PMem, PMemAbove4G, *MemAperture;
> + PCI_ROOT_BRIDGE *RootBridges;
> + UINTN BarOffsetEnd;
> +
> +
> + *NumberOfRootBridges = 0;
> + RootBridges = NULL;
> +
> + //
> + // After scanning all the PCI devices on the PCI root bridge's primary bus,
> + // update the Primary Bus Number for the next PCI root bridge to be this PCI
> + // root bridge's subordinate bus number + 1.
> + //
> + for (PrimaryBus = 0; PrimaryBus <= PCI_MAX_BUS; PrimaryBus = SubBus + 1) {
> + SubBus = PrimaryBus;
> + Attributes = 0;
> + Io.Base = Mem.Base = MemAbove4G.Base = PMem.Base = PMemAbove4G.Base = MAX_UINT64;
> + Io.Limit = Mem.Limit = MemAbove4G.Limit = PMem.Limit = PMemAbove4G.Limit = 0;
> + //
> + // Scan all the PCI devices on the primary bus of the PCI root bridge
> + //
> + for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
> +
> + for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
> +
> + //
> + // Compute the PCI configuration address of the PCI device to probe
> + //
> + Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0);
> +
> + //
> + // Read the Vendor ID from the PCI Configuration Header
> + //
> + if (PciRead16 (Address) == MAX_UINT16) {
> + if (Function == 0) {
> + //
> + // If the PCI Configuration Read fails, or a PCI device does not
> + // exist, then skip this entire PCI device
> + //
> + break;
> + } else {
> + //
> + // If PCI function != 0, VendorId == 0xFFFF, we continue to search
> + // PCI function.
> + //
> + continue;
> + }
> + }
> +
> + //
> + // Read the entire PCI Configuration Header
> + //
> + PciReadBuffer (Address, sizeof (Pci), &Pci);
> +
> + //
> + // Increment the number of PCI device found on the primary bus of the
> + // PCI root bridge
> + //
> + NumberOfDevices++;
> +
> + //
> + // Look for devices with the VGA Palette Snoop enabled in the COMMAND
> + // register of the PCI Config Header
> + //
> + if ((Pci.Hdr.Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) != 0) {
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
> + }
> +
> + BarOffsetEnd = 0;
> +
> + //
> + // PCI-PCI Bridge
> + //
> + if (IS_PCI_BRIDGE (&Pci)) {
> + //
> + // Get the Bus range that the PPB is decoding
> + //
> + if (Pci.Bridge.SubordinateBus > SubBus) {
> + //
> + // If the suborinate bus number of the PCI-PCI bridge is greater
> + // than the PCI root bridge's current subordinate bus number,
> + // then update the PCI root bridge's subordinate bus number
> + //
> + SubBus = Pci.Bridge.SubordinateBus;
> + }
> +
> + //
> + // Get the I/O range that the PPB is decoding
> + //
> + Value = Pci.Bridge.IoBase & 0x0f;
> + Base = ((UINT32) Pci.Bridge.IoBase & 0xf0) << 8;
> + Limit = (((UINT32) Pci.Bridge.IoLimit & 0xf0) << 8) | 0x0fff;
> + if (Value == BIT0) {
> + Base |= ((UINT32) Pci.Bridge.IoBaseUpper16 << 16);
> + Limit |= ((UINT32) Pci.Bridge.IoLimitUpper16 << 16);
> + }
> + if (Base < Limit) {
> + if (Io.Base > Base) {
> + Io.Base = Base;
> + }
> + if (Io.Limit < Limit) {
> + Io.Limit = Limit;
> + }
> + }
> +
> + //
> + // Get the Memory range that the PPB is decoding
> + //
> + Base = ((UINT32) Pci.Bridge.MemoryBase & 0xfff0) << 16;
> + Limit = (((UINT32) Pci.Bridge.MemoryLimit & 0xfff0) << 16) | 0xfffff;
> + if (Base < Limit) {
> + if (Mem.Base > Base) {
> + Mem.Base = Base;
> + }
> + if (Mem.Limit < Limit) {
> + Mem.Limit = Limit;
> + }
> + }
> +
> + //
> + // Get the Prefetchable Memory range that the PPB is decoding
> + //
> + Value = Pci.Bridge.PrefetchableMemoryBase & 0x0f;
> + Base = ((UINT32) Pci.Bridge.PrefetchableMemoryBase & 0xfff0) << 16;
> + Limit = (((UINT32) Pci.Bridge.PrefetchableMemoryLimit & 0xfff0)
> + << 16) | 0xfffff;
> + MemAperture = &PMem;
> + if (Value == BIT0) {
> + Base |= LShiftU64 (Pci.Bridge.PrefetchableBaseUpper32, 32);
> + Limit |= LShiftU64 (Pci.Bridge.PrefetchableLimitUpper32, 32);
> + MemAperture = &PMemAbove4G;
> + }
> + if (Base < Limit) {
> + if (MemAperture->Base > Base) {
> + MemAperture->Base = Base;
> + }
> + if (MemAperture->Limit < Limit) {
> + MemAperture->Limit = Limit;
> + }
> + }
> +
> + //
> + // Look at the PPB Configuration for legacy decoding attributes
> + //
> + if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA)
> + == EFI_PCI_BRIDGE_CONTROL_ISA) {
> + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
> + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
> + Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
> + }
> + if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA)
> + == EFI_PCI_BRIDGE_CONTROL_VGA) {
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
> + if ((Pci.Bridge.BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16)
> + != 0) {
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
> + }
> + }
> +
> + BarOffsetEnd = OFFSET_OF (PCI_TYPE01, Bridge.Bar[2]);
> + } else {
> + //
> + // Parse the BARs of the PCI device to get what I/O Ranges, Memory
> + // Ranges, and Prefetchable Memory Ranges the device is decoding
> + //
> + if ((Pci.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
> + BarOffsetEnd = OFFSET_OF (PCI_TYPE00, Device.Bar[6]);
> + }
> + }
> +
> + PcatPciRootBridgeParseBars (
> + Pci.Hdr.Command,
> + PrimaryBus,
> + Device,
> + Function,
> + OFFSET_OF (PCI_TYPE00, Device.Bar),
> + BarOffsetEnd,
> + &Io,
> + &Mem, &MemAbove4G,
> + &PMem, &PMemAbove4G
> + );
> +
> + //
> + // See if the PCI device is an IDE controller
> + //
> + if (IS_CLASS2 (&Pci, PCI_CLASS_MASS_STORAGE,
> + PCI_CLASS_MASS_STORAGE_IDE)) {
> + if (Pci.Hdr.ClassCode[0] & 0x80) {
> + Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
> + Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
> + }
> + if (Pci.Hdr.ClassCode[0] & 0x01) {
> + Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
> + }
> + if (Pci.Hdr.ClassCode[0] & 0x04) {
> + Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
> + }
> + }
> +
> + //
> + // See if the PCI device is a legacy VGA controller or
> + // a standard VGA controller
> + //
> + if (IS_CLASS2 (&Pci, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) ||
> + IS_CLASS2 (&Pci, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA)
> + ) {
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
> + Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO_16;
> + }
> +
> + //
> + // See if the PCI Device is a PCI - ISA or PCI - EISA
> + // or ISA_POSITIVIE_DECODE Bridge device
> + //
> + if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
> + if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA ||
> + Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_EISA ||
> + Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE) {
> + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
> + Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO_16;
> + Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
> + }
> + }
> +
> + //
> + // If this device is not a multi function device, then skip the rest
> + // of this PCI device
> + //
> + if (Function == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
> + break;
> + }
> + }
> + }
> +
> + //
> + // If at least one PCI device was found on the primary bus of this PCI
> + // root bridge, then the PCI root bridge exists.
> + //
> + if (NumberOfDevices > 0) {
> + RootBridges = ReallocatePool (
> + (*NumberOfRootBridges) * sizeof (PCI_ROOT_BRIDGE),
> + (*NumberOfRootBridges + 1) * sizeof (PCI_ROOT_BRIDGE),
> + RootBridges
> + );
> + ASSERT (RootBridges != NULL);
> + InitRootBridge (
> + Attributes, Attributes, 0,
> + (UINT8) PrimaryBus, (UINT8) SubBus,
> + &Io, &Mem, &MemAbove4G, &PMem, &PMemAbove4G,
> + &RootBridges[*NumberOfRootBridges]
> + );
> + RootBridges[*NumberOfRootBridges].ResourceAssigned = TRUE;
> + //
> + // Increment the index for the next PCI Root Bridge
> + //
> + (*NumberOfRootBridges)++;
> + }
> + }
> +
> + return RootBridges;
> +}
>
next prev parent reply other threads:[~2017-01-05 10:15 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-08 15:33 [PATCH RFC 00/14] Specific platform to run OVMF in Xen PVH and HVM guests Anthony PERARD
2016-12-08 15:33 ` [PATCH RFC 01/14] OvmfPkg: Create platform XenOvmf Anthony PERARD
2017-01-04 19:14 ` Laszlo Ersek
2016-12-08 15:33 ` [PATCH RFC 02/14] OvmfPkg/XenOvmf: Update debug IO port for Xen Anthony PERARD
2017-01-04 19:23 ` Laszlo Ersek
2016-12-08 15:33 ` [PATCH RFC 03/14] OvmfPkg/XenOvmf.dsc: Introduce XenResetVector Anthony PERARD
2017-01-04 19:49 ` Laszlo Ersek
2017-01-10 15:58 ` Anthony PERARD
2016-12-08 15:33 ` [PATCH RFC 04/14] OvmfPkg: Introduce XenPlatformPei Anthony PERARD
2017-01-05 9:59 ` Laszlo Ersek
2017-01-10 16:08 ` Anthony PERARD
2016-12-08 15:33 ` [PATCH RFC 05/14] OvmfPkg/Library: add XenPciHostBridgeLib Anthony PERARD
2017-01-05 10:15 ` Laszlo Ersek [this message]
2016-12-08 15:33 ` [PATCH RFC 06/14] OvmfPkg/XenPlatformPei: Add xen PVH specific code Anthony PERARD
2017-01-05 10:30 ` Laszlo Ersek
2017-01-10 16:18 ` Anthony PERARD
2017-01-10 16:54 ` Laszlo Ersek
2016-12-08 15:33 ` [PATCH RFC 07/14] OvmfPkg/XenResetVector: Add new entry point for Xen PVH Anthony PERARD
2017-01-05 10:36 ` Laszlo Ersek
2016-12-08 15:33 ` [PATCH RFC 08/14] OvmfPkg/PlatformBootManagerLib: Workaround missing PCI bus on " Anthony PERARD
2017-01-05 10:38 ` Laszlo Ersek
2016-12-08 15:33 ` [PATCH RFC 09/14] OvmfPkg/ResetSystemLib: Add missing dependency on PciLib Anthony PERARD
2017-01-05 10:46 ` Laszlo Ersek
2016-12-08 15:33 ` [PATCH RFC 10/14] UefiCpuPkg/BaseXApicX2ApicLib: Fix initialisation on my system and Anthony PERARD
2016-12-09 6:48 ` Kinney, Michael D
2016-12-12 12:38 ` Anthony PERARD
[not found] ` <58dbbeb0-f600-ef3f-7f8c-5c110b0aa809@citrix.com>
2016-12-12 12:40 ` [Xen-devel] " Anthony PERARD
2016-12-08 15:33 ` [PATCH RFC 11/14] OvmfPkg/XenOvmf: Adding XenTimerLocalApic Anthony PERARD
2017-01-05 11:26 ` Laszlo Ersek
2016-12-08 15:33 ` [PATCH RFC 12/14] OvmfPkg/PlatformBootManagerLib: Use a Xen console for ConOut/ConIn Anthony PERARD
2017-01-05 16:38 ` Laszlo Ersek
2016-12-08 15:33 ` [PATCH RFC 13/14] OvmfPkg: Introduce XenIoPvhDxe to initialize Grant Tables Anthony PERARD
2017-01-05 16:58 ` Laszlo Ersek
2016-12-08 15:33 ` [PATCH RFC 14/14] XenOvmf: Use a different RTC Anthony PERARD
2017-01-05 17:02 ` Laszlo Ersek
2017-01-04 19:52 ` [PATCH RFC 00/14] Specific platform to run OVMF in Xen PVH and HVM guests Laszlo Ersek
2017-01-10 14:55 ` Anthony PERARD
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=4f7db46c-1728-076b-64eb-afba6b4864bb@redhat.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