On 07/28/17 12:19, Ni, Ruiyu wrote: > Laszlo, > Thanks for raising this questions. > Please see my embedded reply in below > > Thanks/Ray > >> -----Original Message----- >> From: edk2-devel [mailto:[email protected]] On Behalf Of >> Laszlo Ersek >> Sent: Thursday, July 27, 2017 7:23 PM >> To: Ni, Ruiyu <[email protected]>; [email protected] >> Cc: Marcel Apfelbaum <[email protected]>; Aleksandr Bezzubikov >> <[email protected]>; Zeng, Star <[email protected]> >> Subject: [edk2] bus number padding [was: MdeModulePkg/PciBus: Avoid >> hang when BUS pad resource is not in top] >> >> Hello Ray, >> >> please excuse me for hijacking this thread a little bit, but I'm very happy >> that >> you happen to be looking at this exact part of the code, which is also what >> I've been discussing with Marcel and Aleksandr (CC'd) due to a different >> reason. >> >> (The relevant sub-thread is at >> >> Allow RedHat PCI bridges reserve more buses than necessary during init >> >> http://mid.mail-archive.com/d0bd04f4-1ac4-0e3a-885f- >> [email protected] >> >> but it's very long, so I'm not asking you to read that -- instead, please >> let me >> ask you our question independently and in a self-contained >> form.) >> >> In "OvmfPkg/PciHotPlugInitDxe/", we plan to return some BUS resource >> paddings, from the >> EFI_PCI_HOT_PLUG_INIT_PROTOCOL.GetResourcePadding() >> function. >> >> QEMU has no "root" hotplug controllers, only "non-root" hotplug controllers >> (using the terminology from "12.6 PCI Hot Plug PCI Initialization Protocol" >> in >> the PI-1.6 spec). Therefore OVMF's >> EFI_PCI_HOT_PLUG_INIT_PROTOCOL.GetRootHpcList() returns an empty >> array. >> The BUS resource padding that we'd like to return from >> GetResourcePadding() would be for "non-root" hotplug controllers. >> >> According to the PI spec, this is a valid thing to do: >> >> * From "12.5 Sample Implementation for a Platform Containing PCI >> Hot Plug* Slots": >> >>> [...] For all the root HPCs and the nonroot HPCs, call >>> EFI_PCI_HOT_PLUG_INIT_PROTOCOL.GetResourcePadding() to obtain the >>> amount of overallocation and add that amount to the requests from the >>> physical devices. Reprogram the bus numbers by taking into account the >>> bus resource padding information. [...] >> >> * From "12.6 PCI Hot Plug PCI Initialization Protocol, >> EFI_PCI_HOT_PLUG_INIT_PROTOCOL.GetResourcePadding()": >> >>> [...] This member function is called for all the root HPCs and nonroot >>> HPCs that are detected by the PCI bus enumerator. [...] The PCI bus >>> driver is responsible for adding this resource request to the resource >>> requests by the physical PCI devices. [...] >> >> I searched PciBusDxe for GetResourcePadding() call sites, and there are >> two: >> >> (1) In "MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c", function >> GetResourcePaddingForHpb(). This call site seems to work as follows, >> for our purposes: >> >> GetResourcePaddingPpb() >> [MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c] >> GetResourcePaddingForHpb() >> [MdeModulePkg/Bus/Pci/PciBusDxe/PciHotPlugSupport.c] >> gPciHotPlugInit->GetResourcePadding() >> // >> // and then save the resource descriptors, including the bus >> // padding, in PciIoDevice->ResourcePaddingDescriptors >> // >> >> ResourcePaddingPolicy() >> [MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c] >> ApplyResourcePadding() >> [MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c] >> // >> // translate IO and MMIO resources from >> // PciDev->ResourcePaddingDescriptors to internal padding >> // representation >> // >> >> This call site and processing seem to be active for "non-root" >> hotplug controllers, but they do not consider bus numbers, only IO >> and MMIO. > [Ray] It's in bus allocation phase. So the PciBus driver only cares about the > bus padding. > PciBus driver firstly allocates the bus resource and programs the PCI-PCI > bridges > to set the bus numbers. > After that, PciBus allocates the IO/MMIO resources and program the BARs in > PCI devices & PCI-PCI bridges. > So it's good here. >> >> (2) In the PciScanBus() function, file >> "MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c", we have another >> GetResourcePadding() call -- your present patch is updating this >> code part. >> >> From the resource padding list returned by this GetResourcePadding() >> invocation, PciBusDxe cares only about the bus numbers. I think >> that's probably fine. However, in this location, >> GetResourcePadding() is called *only* for "root" hotplug >> controllers, of which QEMU has none. >> >> The end result is that bus number paddings are not considered at all for >> "non-root" hotplug controllers: > [Ray] Bus number padding should be considered for "non-root" HPCs. > So I agree it's a bug/gap I need to fix. I noticed that already before your > question. > And I do have a plan to fix it though the priority is not very high.
Awesome, thank you! It is not very urgent for us. Do you agree that I file a TianoCore BZ about this? > >> - site (1) is active for "non-root" HPCs, but it ignores bus number >> paddings, >> - site (2) processes bus number paddings, but it is inactive for >> "non-root" HPCs. >> >> This doesn't seem to match what the PI spec says. Is this behavior >> intentional >> in PciBusDxe? If so, what is the reason for it? > [Ray] In summary, site(1) is good. Site(2) contains a bug/gap. > Would you please submit a Bugzilla to record this issue? Thank you for answering my question :) I've now filed the following TianoCore BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=656 > But can you just return the non-root HPCs as root for a workaround? > What prevent you from reporting the HPC as non-root? Yes, I've thought of this as well. The problem is that the "a-priori" knowledge of the root HPCs, that the PI spec mentions for GetRootHpcList(), is actually *dynamic* knowledge in QEMU's case. In "OvmfPkg/PciHotPlugInitDxe", I could only collect the affected bridges by doing a full (recursive) PCI hierarchy enumeration, and look into the config space of each "candidate" controller. However, PciBusDxe already implements the full enumeration, so I don't think PciHotPlugInitDxe should it do internally. (In particular in a platform hook that could be called from a "sensitive" location in PciBusDxe.) > My opinion is the differences between non-root and root HPCs are: > 1. Explicitly initialization is needed for root HPCs I agree that this is one difference. Such initialization is not needed in QEMU's case however. > 2. Root HPCs may not be detected as hot-pluggable by PciBus using standard > ways I agree that this is the other difference. All of QEMU's hotplug controllers can be enumerated in standard ways however. > If your platform doesn't report any root HPCs, why not just report non-root > as root ones? (See above:) because the list of non-root HPCs is not known to OVMF in any static way, it is dynamic (boot time) information. And, QEMU does not expose this information to OVMF in any dedicated, easy-to-consume way. The only way to find out about the non-root HPCs is to actually traverse the PCI hierarchy. Given that PciBusDxe is in the middle of doing exactly that, I think that OvmfPkg/PciHotPlugInitDxe should not perform an "internal" enumeration in GetRootHpcList(). I don't think that OvmfPkg should have a private implementation of this PCI traversal, when the "main" traversal is already done in PciBusDxe. (And, likely much better than what I could write.) When you fix TianoCore BZ#656, that will be perfect for us. :) Thank you very much! Laszlo _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

