On 02/24/16 11:06, Ni, Ruiyu wrote:

>> -----Original Message-----
>> From: Laszlo Ersek [mailto:ler...@redhat.com]
>> Sent: Wednesday, February 24, 2016 5:40 PM
>> To: Ni, Ruiyu <ruiyu...@intel.com>; Marcel Apfelbaum <mar...@redhat.com>
>> Cc: Justen, Jordan L <jordan.l.jus...@intel.com>; edk2-de...@ml01.01.org;
>> Tian, Feng <feng.t...@intel.com>; Fan, Jeff <jeff....@intel.com>; Marcel
>> Apfelbaum (GMail address) <marcel.apfelb...@gmail.com>
>> Subject: Re: [edk2] [Patch V4 4/4] MdeModulePkg: Add generic
>> PciHostBridgeDxe driver.

[snip]

>> 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).

Ah! Now I finally understand it! The PCI bus driver first collects the
*cumulative* resource requirements for *all* of the devices behind the
root bridge (i.e., it consolidates all of the BARs into a single range,
paying attention to the size and alignment requirements of the
individual BARs), and *then* that allocation request is submitted to the
PCI host bridge driver.

It makes perfect sense.

>> (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().

Yep, it makes perfect sense now.

(I think the 0.2GB constant above has to do with powers-of-two alignment
& size requirements for the root bridge itself, right?)

Thanks for educating me about this!

I think if we go with option #2 for the IO and memory space *addition*,
then I can complete the rebase of OvmfPkg to the new driver. Please go
ahead with option #2 for PciHostBridgeDxe, as your time allows.

Thank you!
Laszlo

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to