Regards, Ray
>-----Original Message----- >From: Laszlo Ersek [mailto:[email protected]] >Sent: Wednesday, February 24, 2016 5:40 PM >To: Ni, Ruiyu <[email protected]>; Marcel Apfelbaum <[email protected]> >Cc: Justen, Jordan L <[email protected]>; [email protected]; >Tian, Feng <[email protected]>; Fan, Jeff <[email protected]>; Marcel >Apfelbaum (GMail address) <[email protected]> >Subject: Re: [edk2] [Patch V4 4/4] MdeModulePkg: Add generic >PciHostBridgeDxe driver. > >On 02/24/16 03:46, Ni, Ruiyu wrote: >> Laszlo, >> >> PciBus summarize all the resource requirements for a root bridge, >> and submit the resource requirement summary to PciHostBridge driver. >> So the allocations occur for each root bridge, but not for each BAR. >> >> >> For the Add[Io/Memory]Space operations, I see two options: >> 1. A flag to tell PciHostBridge the resources have been already added >> by platform. PciHostBridge only adds the resources when the flag is >> not set. >> >> 2. PciHostBridge guarantees the resources reported by each root >> bridge have been added. Part of the resources may have been added. >> PciHostBridge adds the remaining part. >> >> I prefer option 2 because it doesn't need an additional flag - >> additional flag means additional interface. >> >> You strongly prefer option 1? > >No, my preference for option 1 is not strong. Option 2 can be certainly >accommodated in OvmfPkg, so if option 2 is your preference, I suggest we >go with that. > >> For the Allocate[Io/Memory]Space operation, I think we might be aligned: >> >> For each root bridge (not each BAR, but I think BAR or root bridge >> doesn't bother you), > >Actually, that difference is crucial. See below. > >> PciHostBridge calls Allocate[Io/Memory]Space to >> allocate the required resources. If allocation fails, >> PciHostBridgeResourceConflict() is called to inform platform. >> >> But we do have some small differences for the allocation: >> >> The current allocation algorithm uses EfiGcdAllocateAddress. You could >> check PciHostBridge.c: >> >> AllocateResource() function for the detailed implementation. It's >> different from what you suggested: >> >> EfiGcdAllocateMaxAddressSearchTopDown. Do you think it matters? > >EfiGcdAllocateAddress is correct if the driver allocates memory space >(or IO space) for the *entire root bridge aperture*. > >My suggestion with EfiGcdAllocateMaxAddressSearchTopDown was for the >allocation of an *individual BAR*. > >So, if the driver is supposed to allocate the *entire bridge aperture* >in one fell swoop, then EfiGcdAllocateAddress is correct. > >*However*, this only takes us back to the original question of >overlapping apertures, between separate bridges! > >Consider the following example. You have two root bridges, and the >32-bit MMIO aperture for each is [3.0GB, 3.5GB). > >(i) According to option #2 above, the *first* gDS->AddMemorySpace() >operation will ensure that the [3.0GB, 3.5GB) range *exists* as MMIO in >the GCD memory space map. Fine. > >(ii) Then the logic in PciHostBridgeDxe will determine, for the *second* >root bridge, according to option #2, that the [3.0GB, 3.5GB) range >*already* exists as MMIO in the GCD memory space map, without gaps. So >there will be no need for another gDS->AddMemorySpace() call. This is >fine as well. > >(iii) Then the driver *allocates* the [3.0GB, 3.5GB) MMIO range for the >*first* root bridge, with the gDS->AllocateMemorySpace() call. It works >perfectly. No. The driver does *NOT* allocate [3G, 3.5G) for root bridge #0. It just allocates the resource that is really required by root bridge #0. for example, [3G, 3.3G). > >(iv) Then the driver tries to allocate the same [3.0GB, 3.5GB) MMIO >range for the *second* root bridge, with another >gDS->AllocateMemorySpace() call. This fails, because that range is no >longer free! Hence the driver calls PciHostBridgeResourceConflict(). > When the real requirement for root bridge #1 is <= 0.2G, the allocation still succeeds. Though the driver uses EfiGcdAllocateAddress type, it tries different base address to allocate. So it ultimately searches to 3.3G as a valid base address for allocation. When the real requirement for root bridge #1 is > 0.2G, the allocation fails. That's a fatal error which will call PciHostBridgeResourceConflict(). >Unfortunately, the allocation failure in (iv) would be a bug in the >driver -- the two root bridges want to *share* the [3.0GB, 3.5GB) MMIO >range between them, and the driver should permit it. It is not a >resource conflict between the root bridges, but a valid configuration on >QEMU. > >Thanks >Laszlo > > > >> >> >> >> Regards, >> >> Ray >> >> >> >> *From:*Laszlo Ersek [mailto:[email protected]] >> *Sent:* Tuesday, February 23, 2016 4:49 PM >> *To:* Ni, Ruiyu <[email protected]>; Marcel Apfelbaum ><[email protected]> >> *Cc:* Justen, Jordan L <[email protected]>; >> [email protected]; Tian, Feng <[email protected]>; Fan, Jeff >> <[email protected]>; Marcel Apfelbaum (GMail address) >> <[email protected]> >> *Subject:* Re: [edk2] [Patch V4 4/4] MdeModulePkg: Add generic >> PciHostBridgeDxe driver. >> >> >> >> (Adding Marcel's gmail address -- I think that's the one he is >> subscribed to edk2-devel with.) >> >> On 02/23/16 06:13, Ni, Ruiyu wrote: >>> Marcel, >>> I see two requirements from your mail: >>> 1. non-continuously resources: root bridge #1 uses [2G, 2.4G) and [2.8G, >3G) while >>> root bridge #2 uses [2.4G, 2.8G) >>> 2. sharable resources among root bridges: All root bridges in same pci >segment >>> can share one common range of resources. >>> >>> Requirement #1 is not supported by MdeModulePkg/PciBus driver and I >guess >>> it's not the urgent requirement and doesn't block OVMF PciHostBridge >porting. >> >> That's correct. >> >>> Requirement #2 can be interpreted as it's valid when the resources claimed >by >>> different root bridges overlap. No matter which segment they belong to. >>> >>> The overlap can be like root bridge #1 claims [2G, 2.4G) while root bridge >#2 >>> claims [2.2G, 2.6G) -- [2.2G, 2.4G) is shared by both root bridges. >>> In such case, PCI devices under root bridge #1 can only use resources [2G, >2.4G) >>> and root bridge #2 can only use [2.2G, 2.6G). GCD services can guarantee >there >>> is no resource conflict -- if [2.2G, 2.3G) is used by one device under root >bridge #1, >>> it won't be used by device under root bridge #2. >> >> Correct as well. >> >>> >>> An extreme case is both root bridges claim [2G, 3G) which is the OVMF >case. >> >> Right. >> >>> So the change to PciHostBridgeDxe can be: >>> 1. Checks whether the resources claimed by the root bridges are already >added, >>> and call AddMemorySpace/AddIoSpace for those resource ranges which >haven't >>> been added. >> >> Do you mean that PciHostBridgeDxe would determine "gaps" in the memory >> space map / IO space map, by calling GetMemorySpaceMap() and >> GetIoSpaceMap(), and taking the intersection of each map with the >> bridge's corresponding aperture(s)? >> >> I can imagine this, but I don't readily understand how this is useful. >> Probably as a basis for the next step: >> >>> 2. Call AllocateMemorySpace/AllocateIoSpace to occupy these resources >in GCD. >>> The Allocation shouldn't fail, otherwise it's a fatal error and >PciHostBridgeDxe driver >>> will assert and exit. >> >> I understand how step (1) is the basis for step (2) -- one can only >> allocate from the memory & IO space maps what has been added to them >> earlier --, but I don't understand how step (2) is supposed to help with >> overlapping apertures. Assuming the allocation is made with >> EfiGcdAllocateAddress, then a conflict for the shared range [2.2G, 2.4G) >> -- using your example at the top -- will be reported. >> >> Furthermore, I'm not sure why the entire aperture for a root bridge >> should be allocated up-front. I thought the allocations occur only for >> specific BARs -- is that incorrect? >> >> For OVMF's purposes, the following would be ideal: >> >> (a) PciHostBridgeDxe should let the platform populate the memory and IO >> space maps as appropriate. This could happen in several ways, for >> example: (i) creation of resource descriptor HOBs during PEI, from which >> the DXE core would prime the memory and IO space maps, or (ii) in the >> constructor of the PciHostBridgeLib instance that the platform links >> into PciHostBridgeDxe. >> >> (b) no explicit overlap checks whatsoever between root bridge apertures >> >> (c) when a BAR is being allocated, allocate the right type of resource >> with GcdAllocateType = EfiGcdAllocateMaxAddressSearchTopDown. >> >> Start the top-down search from the highest address in the bridge's >> aperture. If the allocation fails completely (i.e., no free room from >> the aperture's top, down to zero), report failure. >> >> If the allocation succeeds, but the allocation address is below the base >> address of the bridge's aperture, *undo* the allocation, and report >> failure again. >> >> Otherwise, the BAR allocation succeeds. >> >> >> The above strategy would give full flexibility to the platform, and it >> would ensure that no BAR is allocated outside the respective bridge >> aperture. It would handle overlaps between apertures automatically. >> >> It would also handle the case transparently when a bridge aperture is a >> *proper superset* of what is available in the GCD memory space map. For >> example, assume the GCD memory space map only has MMIO added at >[3.0G, >> 3.5G), and "nothing" at [2.0G, 3.0G) -- a gap. Then a bridge aperture of >> [2.0G, 3.5G) would "just work", without changing the GCD memory space >> map. GCD would satisfy BAR allocations from [3.0G, 3.5G), and any >> addresses allocated from that range would *also* satisfy the bridge >> aperture, automatically. >> >> Do you see any problems with the idea in (a) through (c)? >> >> Thank you >> Laszlo >> _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

