On 21 November 2017 at 20:17, Laszlo Ersek <ler...@redhat.com> wrote:
> On 11/21/17 18:57, Ard Biesheuvel wrote:
>>
>>
>>> On 21 Nov 2017, at 17:49, Laszlo Ersek <ler...@redhat.com> wrote:
>>>
>>>> On 11/17/17 17:09, Ard Biesheuvel wrote:
>>>> Equivalent to the PrePi based platforms, this patch implements the
>>>> newly introduced ArmVirtMemInfo library class via a separate PEIM
>>>> and PPI.
>>>>
>>>> The reason is that ArmVirtPlatformLib has populated the ArmPlatformLib
>>>> API function ArmPlatformInitializeSystemMemory () to retrieve memory
>>>> information from the DT, ensuring that it will be present when
>>>> MemoryPeim() is executed. This is a bit of a hack, and someting we
>>>> will need to get rid of if we want to reduce our dependency on
>>>> ArmPlatformLib altogether.
>>>
>>> OK, so whenever I try to look at this code, my brain crashes. This
>>> occasion is no exception. All the more reason to clean it all up; thanks
>>> for doing that.
>>>
>>> So, I guess we are talking about the following call stack. If you agree,
>>> please add it to the commit message (IMO it's OK to exceed the preferred
>>> 74 chars width for such sections):
>>>
>>>  ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf 
>>> [ArmVirtPkg/ArmVirtQemu.dsc]
>>>    InitializeMemory()                            
>>> [ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.c]
>>>      ArmPlatformInitializeSystemMemory()         
>>> [ArmVirtPkg/Library/ArmVirtPlatformLib/Virt.c]
>>>        //
>>>        // set PcdSystemMemorySize from the DT
>>>        //
>>>      MemoryPeim()                                
>>> [ArmVirtPkg/Library/ArmVirtMemoryInitPeiLib/ArmVirtMemoryInitPeiLib.c]
>>>        InitMmu()                                 
>>> [ArmVirtPkg/Library/ArmVirtMemoryInitPeiLib/ArmVirtMemoryInitPeiLib.c]
>>>          ArmPlatformGetVirtualMemoryMap()        
>>> [ArmVirtPkg/Library/ArmVirtPlatformLib/VirtMem.c]
>>>            //
>>>            // consume PcdSystemMemorySize
>>>            //
>>>
>>> Here we have two ArmVirtPlatformLib actions:
>>>
>>> - The "PCD consumption" half of that has been moved -- well, copied, for
>>>  now -- to QemuVirtMemInfoLib, in patch 12/15.
>>>
>>> - And we are now looking for a new home for the "PCD production" half.
>>>
>>
>> Yes
>>
>>>> Putting this code in a ArmVirtMemInfo library constructor is
>>>> problematic as well, given that the implementation uses other
>>>> libraries, among which PcdLib, and so we need to find another way to
>>>> run it before MemoryPeim()
>>>
>>> Hm, this claim could be true :) , but I'm not totally convinced by the
>>> way you put it.
>>>
>>> First off, I notice that
>>> "ArmVirtPkg/Library/ArmVirtPlatformLib/ArmVirtPlatformLib.inf" does not
>>> spell out PcdLib as a dependency. This is quite bad, because it uses
>>> PCDs.
>>>
>>> However, ultimately, "gEfiPeiPcdPpiGuid" does end up in the final DEPEX
>>> of "MemoryInitPeim.inf", according to the ArmVirtQemu build report file.
>>> This must be due to some of the library instances already pulling in
>>> PeiPcdLib.
>>>
>>> Therefore, if we modify the constructor of QemuVirtMemInfoLib to parse
>>> the DT and to set the PCD, *plus* we spell out PcdLib in the
>>> QemuVirtMemInfoLib INF file, then the ultimate DEPEX for the
>>> MemoryInitPeim module should remain the same. And, the PeiPcdLib
>>> constructor should run before the QemuVirtMemInfoLib constructor
>>> (parsing the DT and setting the PCD).
>>>
>>> What's wrong with this argument?
>>>
>>
>> I guess you’re right. Direct dependencies between libraries with 
>> constructors are handled correctly by the tools, I simply managed to confuse 
>> myself due to the issues with transitive dependencies which you surely 
>> remember.
>
> Right, I suspected that this experience was in the background. If I
> remember correctly, the issue was when some libraries had constructors
> while some others had none (and required explicit init function calls
> instead). In some cases this mixing was not possible to avoid due to
> circular dependencies between constructors, but in turn the explicit
> calls didn't get ordered right, or some such. *shudder* :)
>

The core of the issue is that transitive library dependencies are not
honoured in the ordering of constructor invocations if they pass
through a library that has no constructor itself.

I.e., libA with a constructor

depending on libB with no constructor

depending on libC with a constructor

Currently, libA's constructor may be called before libC's constructor,
which is clearly a bug, and which is the reason why I /think/ we
generally shouldn't be relying on other libraries in constructor
implementations.

>>
>>>> So instead, create a separate PEIM that encapsulates the
>>>> ArmVirtMemInfo code and exposes it via a PPI. Another ArmVirtMemInfo
>>>> library class implementation is also provided that depexes on the PPI,
>>>> which ensures that the code is called in the correct order.
>>>
>>> I understand what this does, but I find it very complex.
>>>
>>> Sometimes, whenever we want to make sure that a PCD is set dynamically
>>> "no later than" it's consumed by a "common" module outside of
>>> ArmVirtPkg, we create a dedicated library instance (with all the right
>>> library dependencies spelled out in its INF file), set the PCD in its
>>> constructor, and hook it into the consumer module via NULL class
>>> resolution.
>>>
>>> In this case, we have a lib instance that is used through an actual lib
>>> class already, so I would suggest to add a constructor function, and to
>>> spell out the PcdLib dependency in the INF file.
>>>
>>> ... In fact, this is something that I missed in patch 12 --
>>> QemuVirtMemInfoLib already uses PCDs, but doesn't include "PcdLib" under
>>> [LibraryClasses]. That is a bug inherited from ArmVirtPlatformLib (see
>>> above), and should be fixed. And then we should only need the
>>> constructor.
>>>
>>> What do you think?
>>>
>>
>> I think you’re right.
>>
>> So how do you propose i go about creating two versions of 
>> QemuVirtMemInfoLib, only one of which has a constructor? Share the .c file 
>> between two infs in the same directory?
>
> Hm, I think I missed the impact on ArmVirtQemuKernel. In the current
> set, its DSC file is only modified in patch 12. (I missed that too.) Are
> any changes necessary for ArmVirtQemuKernel that are not contained in
> this set?
>
> Either way, what you propose above seems to be the standard approach to
> me: use two INF files, keep the bulk of the code in one (shared) C file,
> and add the constructor to another (non-shared) C file (i.e., referenced
> by only one of the INF files). Should the constructor need shared
> utility functions from the shared C file, add an internal header for those.
>

Would you object to having a single .c file, but only declare the
constructor in one of the two .INFs? The code will be pruned anyway,
due to our use of -ffunction-sections
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to