Reviewed-By: Olivier Martin <[email protected]> On 23/02/15 14:28, Laszlo Ersek wrote: > In the Linux kernel tree, > "Documentation/devicetree/bindings/pci/host-generic-pci.txt" describes the > device tree bindings of a Generic PCI host controller. > > Recent QEMU patches from Alexander Graf implement such a controller on the > "virt" machine type of qemu-system-(aarch64|arm): > > pcie@10000000 { > // > // (devfn<<8, 0, 0) PCI irq > // ---------------- ------- > interrupt-map-mask = <0x1800 0x0 0x0 0x7>; > > // gic irq > // (devfn<<8, 0, 0) pin+1 phandle (type, nr, level) > // ---------------- ----- -------- ----------------- > interrupt-map = < 0x0 0x0 0x0 0x1 0x8001 0x0 0x3 0x4 > 0x0 0x0 0x0 0x2 0x8001 0x0 0x4 0x4 > 0x0 0x0 0x0 0x3 0x8001 0x0 0x5 0x4 > 0x0 0x0 0x0 0x4 0x8001 0x0 0x6 0x4 > 0x800 0x0 0x0 0x1 0x8001 0x0 0x4 0x4 > 0x800 0x0 0x0 0x2 0x8001 0x0 0x5 0x4 > 0x800 0x0 0x0 0x3 0x8001 0x0 0x6 0x4 > 0x800 0x0 0x0 0x4 0x8001 0x0 0x3 0x4 > 0x1000 0x0 0x0 0x1 0x8001 0x0 0x5 0x4 > 0x1000 0x0 0x0 0x2 0x8001 0x0 0x6 0x4 > 0x1000 0x0 0x0 0x3 0x8001 0x0 0x3 0x4 > 0x1000 0x0 0x0 0x4 0x8001 0x0 0x4 0x4 > 0x1800 0x0 0x0 0x1 0x8001 0x0 0x6 0x4 > 0x1800 0x0 0x0 0x2 0x8001 0x0 0x3 0x4 > 0x1800 0x0 0x0 0x3 0x8001 0x0 0x4 0x4 > 0x1800 0x0 0x0 0x4 0x8001 0x0 0x5 0x4>; > > #interrupt-cells = <0x1>; > > // > // child base cpu base > // type address address size > // --------- -------------- -------------- -------------- > ranges = <0x1000000 0x0 0x0 0x0 0x3eff0000 0x0 0x10000 > 0x2000000 0x0 0x10000000 0x0 0x10000000 0x0 0x2eff0000>; > > // > // PCIe config PCIe config > // space base space size > // -------------- ------------- > reg = <0x0 0x3f000000 0x0 0x1000000>; > > // > // allowed bus numbers; inclusive range > // > bus-range = <0x0 0xf>; > > #size-cells = <0x2>; > #address-cells = <0x3>; > device_type = "pci"; > compatible = "pci-host-ecam-generic"; > }; > > Parse those properties of the compatible="pci-host-ecam-generic" node into > PCDs that are relevant for PCI enumeration in edk2: > > - gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress controls > MdePkg/Library/BasePciExpressLib, > > - gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration controls > OvmfPkg/AcpiPlatformDxe at this point, > > - the rest have been introduced earlier in this patchset, and will control > PCI range checks and translation. > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Laszlo Ersek <[email protected]> > --- > > Notes: > v3: > - rebase to current master, control OvmfPkg/AcpiPlatformDxe with > PcdPciDisableBusEnumeration (drop PcdOvmfPciEnabled) [Jordan] > > - suppress invalid '-Werror=maybe-uninitialized' warnings [Ard] -- these > warnings are invalid because: > * both IoSize and MmioSize are set to 0 before the loop, > * if either of them is zero after the loop, then the PcdSetXX() part > is not reached, > * otherwise, both are set to something nonzero, > * which means that code must have run that assigned values to *all* of > IoBase, IoTranslation, MmioBase, MmioTranslation. > > - QEMU only exposes, and we only support, 32-bit MMIO at this point; > rebase to the new PCDs [Olivier] > > - drop support for nonzero PCI memory translation [Alex, Peter, Rob et > al] > > v2: > - rebase to gArmPlatformTokenSpaceGuid PCDs [Olivier] > - control OvmfPkg/AcpiPlatformDxe with PcdOvmfPciEnabled [Jordan, > Laszlo] > > ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf | 10 + > ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c | 198 > +++++++++++++++++++- > ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc | 11 +- > 3 files changed, 208 insertions(+), 11 deletions(-) > > diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf > b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf > index 514ce2f..ff05c5e 100644 > --- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf > +++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf > @@ -27,6 +27,7 @@ > > [Packages] > MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > ArmPkg/ArmPkg.dec > ArmPlatformPkg/ArmPlatformPkg.dec > ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec > @@ -57,6 +58,15 @@ > gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum > gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum > gArmPlatformTokenSpaceGuid.PcdPL031RtcBase > + gArmPlatformTokenSpaceGuid.PcdPciBusMin > + gArmPlatformTokenSpaceGuid.PcdPciBusMax > + gArmPlatformTokenSpaceGuid.PcdPciIoBase > + gArmPlatformTokenSpaceGuid.PcdPciIoSize > + gArmPlatformTokenSpaceGuid.PcdPciIoTranslation > + gArmPlatformTokenSpaceGuid.PcdPciMmio32Base > + gArmPlatformTokenSpaceGuid.PcdPciMmio32Size > + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress > + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration > > [Protocols] > gEfiDevicePathProtocolGuid > diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c > b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c > index 751864d..be74d62 100644 > --- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c > +++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c > @@ -46,23 +46,25 @@ typedef enum { > PropertyTypeTimer, > PropertyTypePsci, > PropertyTypeFwCfg, > + PropertyTypePciHost, > } PROPERTY_TYPE; > > typedef struct { > PROPERTY_TYPE Type; > - CHAR8 Compatible[20]; > + CHAR8 Compatible[32]; > } PROPERTY; > > STATIC CONST PROPERTY CompatibleProperties[] = { > - { PropertyTypeGic, "arm,cortex-a15-gic" }, > - { PropertyTypeRtc, "arm,pl031" }, > - { PropertyTypeVirtio, "virtio,mmio" }, > - { PropertyTypeUart, "arm,pl011" }, > - { PropertyTypeTimer, "arm,armv7-timer" }, > - { PropertyTypeTimer, "arm,armv8-timer" }, > - { PropertyTypePsci, "arm,psci-0.2" }, > - { PropertyTypeFwCfg, "qemu,fw-cfg-mmio" }, > - { PropertyTypeUnknown, "" } > + { PropertyTypeGic, "arm,cortex-a15-gic" }, > + { PropertyTypeRtc, "arm,pl031" }, > + { PropertyTypeVirtio, "virtio,mmio" }, > + { PropertyTypeUart, "arm,pl011" }, > + { PropertyTypeTimer, "arm,armv7-timer" }, > + { PropertyTypeTimer, "arm,armv8-timer" }, > + { PropertyTypePsci, "arm,psci-0.2" }, > + { PropertyTypeFwCfg, "qemu,fw-cfg-mmio" }, > + { PropertyTypePciHost, "pci-host-ecam-generic" }, > + { PropertyTypeUnknown, "" } > }; > > typedef struct { > @@ -96,6 +98,176 @@ GetTypeFromNode ( > return PropertyTypeUnknown; > } > > +// > +// We expect the "ranges" property of "pci-host-ecam-generic" to consist of > +// records like this. > +// > +#pragma pack (1) > +typedef struct { > + UINT32 Type; > + UINT64 ChildBase; > + UINT64 CpuBase; > + UINT64 Size; > +} DTB_PCI_HOST_RANGE_RECORD; > +#pragma pack () > + > +#define DTB_PCI_HOST_RANGE_RELOCATABLE BIT31 > +#define DTB_PCI_HOST_RANGE_PREFETCHABLE BIT30 > +#define DTB_PCI_HOST_RANGE_ALIASED BIT29 > +#define DTB_PCI_HOST_RANGE_MMIO32 BIT25 > +#define DTB_PCI_HOST_RANGE_MMIO64 (BIT25 | BIT24) > +#define DTB_PCI_HOST_RANGE_IO BIT24 > +#define DTB_PCI_HOST_RANGE_TYPEMASK (BIT31 | BIT30 | BIT29 | BIT25 | > BIT24) > + > +/** > + Process the device tree node describing the generic PCI host controller. > + > + param[in] DeviceTreeBase Pointer to the device tree. > + > + param[in] Node Offset of the device tree node whose "compatible" > + property is "pci-host-ecam-generic". > + > + param[in] RegProp Pointer to the "reg" property of Node. The caller > + is responsible for ensuring that the size of the > + property is 4 UINT32 cells. > + > + @retval EFI_SUCCESS Parsing successful, properties parsed from Node > + have been stored in dynamic PCDs. > + > + @retval EFI_PROTOCOL_ERROR Parsing failed. PCDs are left unchanged. > +**/ > +STATIC > +EFI_STATUS > +EFIAPI > +ProcessPciHost ( > + IN CONST VOID *DeviceTreeBase, > + IN INT32 Node, > + IN CONST VOID *RegProp > + ) > +{ > + UINT64 ConfigBase, ConfigSize; > + CONST VOID *Prop; > + INT32 Len; > + UINT32 BusMin, BusMax; > + UINT32 RecordIdx; > + UINT64 IoBase, IoSize, IoTranslation; > + UINT64 MmioBase, MmioSize, MmioTranslation; > + > + // > + // Fetch the ECAM window. > + // > + ConfigBase = fdt64_to_cpu (((CONST UINT64 *)RegProp)[0]); > + ConfigSize = fdt64_to_cpu (((CONST UINT64 *)RegProp)[1]); > + > + // > + // Fetch the bus range (note: inclusive). > + // > + Prop = fdt_getprop (DeviceTreeBase, Node, "bus-range", &Len); > + if (Prop == NULL || Len != 2 * sizeof(UINT32)) { > + DEBUG ((EFI_D_ERROR, "%a: 'bus-range' not found or invalid\n", > + __FUNCTION__)); > + return EFI_PROTOCOL_ERROR; > + } > + BusMin = fdt32_to_cpu (((CONST UINT32 *)Prop)[0]); > + BusMax = fdt32_to_cpu (((CONST UINT32 *)Prop)[1]); > + > + // > + // Sanity check: the config space must accommodate all 4K register bytes of > + // all 8 functions of all 32 devices of all buses. > + // > + if (BusMax < BusMin || BusMax - BusMin == MAX_UINT32 || > + DivU64x32 (ConfigSize, SIZE_4KB * 8 * 32) < BusMax - BusMin + 1) { > + DEBUG ((EFI_D_ERROR, "%a: invalid 'bus-range' and/or 'reg'\n", > + __FUNCTION__)); > + return EFI_PROTOCOL_ERROR; > + } > + > + // > + // Iterate over "ranges". > + // > + Prop = fdt_getprop (DeviceTreeBase, Node, "ranges", &Len); > + if (Prop == NULL || Len == 0 || > + Len % sizeof (DTB_PCI_HOST_RANGE_RECORD) != 0) { > + DEBUG ((EFI_D_ERROR, "%a: 'ranges' not found or invalid\n", > __FUNCTION__)); > + return EFI_PROTOCOL_ERROR; > + } > + > + // > + // IoBase, IoTranslation, MmioBase and MmioTranslation are initialized only > + // in order to suppress '-Werror=maybe-uninitialized' warnings > *incorrectly* > + // emitted by some gcc versions. > + // > + IoBase = 0; > + IoTranslation = 0; > + MmioBase = 0; > + MmioTranslation = 0; > + > + // > + // IoSize and MmioSize are initialized to zero because the logic below > + // requires it. > + // > + IoSize = 0; > + MmioSize = 0; > + for (RecordIdx = 0; RecordIdx < Len / sizeof (DTB_PCI_HOST_RANGE_RECORD); > + ++RecordIdx) { > + CONST DTB_PCI_HOST_RANGE_RECORD *Record; > + > + Record = (CONST DTB_PCI_HOST_RANGE_RECORD *)Prop + RecordIdx; > + switch (fdt32_to_cpu (Record->Type) & DTB_PCI_HOST_RANGE_TYPEMASK) { > + case DTB_PCI_HOST_RANGE_IO: > + IoBase = fdt64_to_cpu (Record->ChildBase); > + IoSize = fdt64_to_cpu (Record->Size); > + IoTranslation = fdt64_to_cpu (Record->CpuBase) - IoBase; > + break; > + > + case DTB_PCI_HOST_RANGE_MMIO32: > + MmioBase = fdt64_to_cpu (Record->ChildBase); > + MmioSize = fdt64_to_cpu (Record->Size); > + MmioTranslation = fdt64_to_cpu (Record->CpuBase) - MmioBase; > + > + if (MmioBase > MAX_UINT32 || MmioSize > MAX_UINT32 || > + MmioBase + MmioSize > SIZE_4GB) { > + DEBUG ((EFI_D_ERROR, "%a: MMIO32 space invalid\n", __FUNCTION__)); > + return EFI_PROTOCOL_ERROR; > + } > + > + if (MmioTranslation != 0) { > + DEBUG ((EFI_D_ERROR, "%a: unsupported nonzero MMIO32 translation " > + "0x%Lx\n", __FUNCTION__, MmioTranslation)); > + return EFI_UNSUPPORTED; > + } > + > + break; > + } > + } > + if (IoSize == 0 || MmioSize == 0) { > + DEBUG ((EFI_D_ERROR, "%a: %a space empty\n", __FUNCTION__, > + (IoSize == 0) ? "IO" : "MMIO32")); > + return EFI_PROTOCOL_ERROR; > + } > + > + PcdSet64 (PcdPciExpressBaseAddress, ConfigBase); > + > + PcdSet32 (PcdPciBusMin, BusMin); > + PcdSet32 (PcdPciBusMax, BusMax); > + > + PcdSet64 (PcdPciIoBase, IoBase); > + PcdSet64 (PcdPciIoSize, IoSize); > + PcdSet64 (PcdPciIoTranslation, IoTranslation); > + > + PcdSet32 (PcdPciMmio32Base, (UINT32)MmioBase); > + PcdSet32 (PcdPciMmio32Size, (UINT32)MmioSize); > + > + PcdSetBool (PcdPciDisableBusEnumeration, FALSE); > + > + DEBUG ((EFI_D_INFO, "%a: Config[0x%Lx+0x%Lx) Bus[0x%x..0x%x] " > + "Io[0x%Lx+0x%Lx)@0x%Lx Mem[0x%Lx+0x%Lx)@0x%Lx\n", __FUNCTION__, > ConfigBase, > + ConfigSize, BusMin, BusMax, IoBase, IoSize, IoTranslation, MmioBase, > + MmioSize, MmioTranslation)); > + return EFI_SUCCESS; > +} > + > + > EFI_STATUS > EFIAPI > InitializeVirtFdtDxe ( > @@ -167,6 +339,12 @@ InitializeVirtFdtDxe ( > (PropType == PropertyTypePsci)); > > switch (PropType) { > + case PropertyTypePciHost: > + ASSERT (Len == 2 * sizeof (UINT64)); > + Status = ProcessPciHost (DeviceTreeBase, Node, RegProp); > + ASSERT_EFI_ERROR (Status); > + break; > + > case PropertyTypeFwCfg: > ASSERT (Len == 2 * sizeof (UINT64)); > > diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc > b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc > index 81e7103..29d0778 100644 > --- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc > +++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc > @@ -156,11 +156,11 @@ > gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, > 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, > 0xD1 } > !endif > > +[PcdsDynamicDefault.common] > ## If TRUE, OvmfPkg/AcpiPlatformDxe will not wait for PCI > # enumeration to complete before installing ACPI tables. > gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|TRUE > > -[PcdsDynamicDefault.common] > # System Memory Size -- 1 MB initially, actual size will be fetched from > DT > gArmTokenSpaceGuid.PcdSystemMemorySize|0x00100000 > > @@ -181,6 +181,15 @@ > ## PL031 RealTimeClock > gArmPlatformTokenSpaceGuid.PcdPL031RtcBase|0x0 > > + gArmPlatformTokenSpaceGuid.PcdPciBusMin|0x0 > + gArmPlatformTokenSpaceGuid.PcdPciBusMax|0x0 > + gArmPlatformTokenSpaceGuid.PcdPciIoBase|0x0 > + gArmPlatformTokenSpaceGuid.PcdPciIoSize|0x0 > + gArmPlatformTokenSpaceGuid.PcdPciIoTranslation|0x0 > + gArmPlatformTokenSpaceGuid.PcdPciMmio32Base|0x0 > + gArmPlatformTokenSpaceGuid.PcdPciMmio32Size|0x0 > + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0x0 > + > gArmVirtualizationTokenSpaceGuid.PcdArmPsciMethod|0 > > gArmVirtualizationTokenSpaceGuid.PcdFwCfgSelectorAddress|0x0 > -- > 1.8.3.1 > > > > ------------------------------------------------------------------------------ > Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server > from Actuate! Instantly Supercharge Your Business Reports and Dashboards > with Interactivity, Sharing, Native Excel Exports, App Integration & more > Get technology previously reserved for billion-dollar corporations, FREE > http://pubads.g.doubleclick.net/gampad/clk?id=190641631&iu=/4140/ostg.clktrk > _______________________________________________ > edk2-devel mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/edk2-devel >
-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you. ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No: 2557590 ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No: 2548782 ------------------------------------------------------------------------------ Download BIRT iHub F-Type - The Free Enterprise-Grade BIRT Server from Actuate! Instantly Supercharge Your Business Reports and Dashboards with Interactivity, Sharing, Native Excel Exports, App Integration & more Get technology previously reserved for billion-dollar corporations, FREE http://pubads.g.doubleclick.net/gampad/clk?id=190641631&iu=/4140/ostg.clktrk _______________________________________________ edk2-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/edk2-devel
