> On Aug 8, 2015, at 8:12 AM, Laszlo Ersek <ler...@redhat.com> wrote:
> 
> On 08/08/15 08:13, Benjamin Herrenschmidt wrote:
>> Hi !
>> 
>> I'm still trying to get my head around the internals of EDK here so
>> bear with me if there's an obvious answer that I missed ... :-)
>> 
>> I'm trying to understand how I can properly reserve bits of memory
>> from my PrePei or Pei so that DXE won't stomp on them.
>> 
>> To simplify the discussion, let's assume that I have a resource
>> descriptor of type EFI_RESOURCE_SYSTEM_MEMORY that cover, well .. all
>> of my system memory.
>> 
>> Then on top of that, I have a number of EFI_HOB_TYPE_MEMORY_ALLOCATION
>> HOBs that represent bits of that memory that I want to reserve.
> 
> Yes, this matches how I think of it.
> 

If you look at the PEI Services Table you will see that there is only Allocate 
Pages/Pool and not free. Basically the transition from PEI to DXE is the “de 
facto free” of this memory. 

https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Pi/PiPeiCis.h 
<https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Pi/PiPeiCis.h>
  EFI_PEI_ALLOCATE_PAGES         AllocatePages;
  EFI_PEI_ALLOCATE_POOL           AllocatePool;

So the simple way to pass data between PEI and DXE is a HOB (Hand Off Block). 

If you really need to punch holes in the memory map, then you can use resource 
descriptors. 

Thanks,

Andrew Fish

>> From what I can see of the code in Gcd.c, this won't work, as
>> CoreInitializeMemoryServices() will not consider the allocation HOBs
>> before picking a piece of initial memory, and that initial memory will
>> be directed straight to the free list.
>> 
>> Or am I missing something ?
> 
> First, let's make sure I understand what you mean by "that initial
> memory will be directed straight to the free list" in
> CoreInitializeMemoryServices().
> 
> Do you mean the fact that CoreInitializeMemoryServices() does not look
> at EFI_HOB_TYPE_MEMORY_ALLOCATION HOBs, it "only" does some other (quite
> complex!) scanning, and then calls CoreAddMemoryDescriptor() at the end,
> with the comment
> 
>  //
>  // Declare the very first memory region, so the EFI Memory Services are 
> available.
>  //
> 
> without having looked at memory allocation HOBs?
> 
> If that's indeed your point, then maybe it will help to look at the call
> tree "context" in the DXE core, where this function --
> CoreInitializeMemoryServices() -- is called from:
> 
>  DxeMain()                        [MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c]
>    CoreInitializeMemoryServices() [MdeModulePkg/Core/Dxe/Gcd/Gcd.c]
>    AllocateRuntimeCopyPool()      
> [MdeModulePkg/Library/DxeCoreMemoryAllocationLib/MemoryAllocationLib.c]
>    AllocateRuntimeCopyPool()      
> [MdeModulePkg/Library/DxeCoreMemoryAllocationLib/MemoryAllocationLib.c]
>    ...
>    CoreInitializeGcdServices()    [MdeModulePkg/Core/Dxe/Gcd/Gcd.c]
> 
> The CoreInitializeGcdServices() function *does* look at the memory
> allocation HOBs, and processes them so that the allocations show up in
> the UEFI memory map.
> 
> My point is that CoreInitializeMemoryServices() is just part of the
> story. Very soon after it other processing occurs (without intervening
> external code) that "primes" the memory map so that memory allocation
> HOBs are honored, before DXE modules can actually call memory allocation
> boot services.
> 
> Yes, there are some memory allocations *between* those functions; I even
> spelled them out in the above call tree. Note however that these
> function calls are special: they are resolved to a DXE_CORE-specific
> memory allocation library instance (which is why I spelled out the
> pathnames to the right). Those work differently from the run-of-the-mill
> allocations used during DXE (which are based on the boot services). So,
> I think the above should be self-consistent.
> 
>> So I need to "split" my EFI_RESOURCE_SYSTEM_MEMORY resource descriptor
>> HOBs to "avoid" reserved regions of memory before starting DXE,
>> correct ?
> 
> No. That would be terrible.
> 
> There are two concepts here, the DXE memory *space* map (more precisely
> called GCD memory space map), and the UEFI memory map. The GCD memory
> space map and surrounding APIs are specified in the Platform
> Initialization specs. The UEFI memory map is layered on top of the GCD
> memory space map, and it is treated (and the surrounding APIs are
> treated) in the UEFI spec.
> 
> - The UEFI memory map (the higher level concept) describes, roughly, how
>  ranges of the address space are used for *software* purposes. See
>  EFI_MEMORY_TYPE.
> 
> - The GCD memory space map (the lower level concept) deals more with
>  *hardware* properties; for example it describes where system memory,
>  MMIO, persistent memory, etc, *exist*. See EFI_GCD_MEMORY_TYPE.
> 
> There's a hierarchy between them; for example, the UEFI memory map
> cannot list an EfiBootServicesCode range that would fall onto
> EfiGcdMemoryTypeMemoryMappedIo in the underlying GCD memory space map.
> 
> In the DXE phase and later, the GCD memory space map is manipulated with
> DXE services (gDS->... functions). See "7.2 Global Coherency Domain
> Services" in volume 2 of the Platform Init spec, v1.4. Whereas the UEFI
> memory map is affected by memory allocation *boot* services (gBS->...
> functions) that are defined in the UEFI spec.
> 
> ... Clearly, what I wrote above contains a lot of hand-waving, but I
> think it should be enough here for distinguishing the GCD memory space
> map from the UEFI memory map, and seeing that the latter is based on top
> of the former (or more-or-less "subdivides" the former).
> 
> Now, the "split" between these two concepts starts early; it is
> considered even in PEI.
> 
> Namely, the resource descriptor HOBs that you produce during PEI (or
> more generally called "the HOB producer phase") will prime the GCD
> memory *space* map. For example,
> 
> - EFI_RESOURCE_SYSTEM_MEMORY vs.
> - EFI_RESOURCE_MEMORY_MAPPED_IO
> 
> HOBS are turned into
> 
> - gDS->AddMemorySpace (EfiGcdMemoryTypeSystemMemory) vs.
> - gDS->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo)
> 
> calls, effectively. But, they both affect the GCD memory space map.
> 
> Whereas the EFI_HOB_TYPE_MEMORY_ALLOCATION kind of HOB will "prime" the
> UEFI memory map, on top of the underlying GCD memory space map.
> 
> Therefore, when you later call gBS->AllocatePool() or
> gBS->AllocatePages(), those functions will steer clear of the ranges
> originally set aside in PEI, with memory allocation HOBs.
> 
> Let me quote the Platform Init specification, v1.4, Volume 3:
> 
>  5.4 Memory Allocation HOB
>  5.4.1 Memory Allocation HOB
>  EFI_HOB_MEMORY_ALLOCATION
> 
>    Summary
> 
>      Describes all memory ranges used during the HOB producer phase
>      that exist outside the HOB list.
> 
>      This HOB type describes how memory is used, not the physical
>      attributes of memory.
> 
>    [...]
> 
>    Description
> 
>      The memory allocation HOB is used to describe memory usage outside
>      the HOB list. The HOB consumer phase does not make assumptions
>      about the contents of the memory that is allocated by the memory
>      allocation HOB, and it will not move the data unless it has
>      explicit knowledge of the memory allocation HOB's Name (EFI_GUID).
>      Memory may be allocated in either the HOB producer phase memory
>      area or other areas of present and initialized system memory.
> 
>      The HOB consumer phase reads all memory allocation HOBs and
>      allocates memory into the system memory map based on the following
>      fields of EFI_HOB_MEMORY_ALLOCATION_HEADER of each memory
>      allocation HOB:
> 
>      [...]
> 
> So, if you punched a hole in the GCD memory space map (by modifying your
> resource descriptor HOB installations), you wouldn't even be allowed to
> cover that hole with a memory allocation HOB. Because, the memory
> allocation HOB would describe an allocation for the UEFI memory map that
> could not be "carried" by the underlying GCD memory space map.
> 
> 
> Here's another argument. Using the memory allocation services in PEI,
> EFI_PEI_SERVICES.AllocatePages() and EFI_PEI_SERVICES.AllocatePool(),
> you can't allocate memory at a specific address. Unlike the
> gBS->AllocatePages() *boot service*, the similar PEI service does not
> allow the caller to request an at-address allocation.
> 
> - EFI_PEI_SERVICES.AllocatePages() -- implemented in PeiAllocatePages()
>  in "MdeModulePkg/Core/Pei/Memory/MemoryServices.c" -- allocates from
>  the free memory range tracked by the PHIT HOB.
> 
> - The EFI_PEI_SERVICES.AllocatePool() function -- implemented in
>  PeiAllocatePool() in "MdeModulePkg/Core/Pei/Memory/MemoryServices.c"
>  -- allocates *within* new HOBs.
> 
> Both of these come from the permanent PEI memory range, I think.
> 
> So, if you want to set aside system RAM at a specific address, during
> PEI, you have to overlay that with a memory allocation HOB.
> 
> (Side point: in order to keep such manually created memory allocation
> HOBs apart from the permanent PEI memory range (from which the PEI
> memory allocation services allocate), you must first install / publish
> the permanent PEI memory range accordingly. (And OVMF does that; see
> section "A comprehensive memory map of OVMF" in the OVMF whitepaper.))
> 
>> Now if I'm correct, then I don't understand how the code in
>> OvmfPkg/PlatformPei/MemDetect.c works, since as far as I can tell,
>> it declares system memory, then create allocation HOBs for areas that
>> are reserved, but doesn't take those area out of the system memory hob
>> list...
>> 
>> What am I missing ? :-)
> 
> I think you were missing the conceptual hierarchy between the GCD memory
> space map and the UEFI memory map, and which HOBs produced in PEI
> (resource vs. allocation), and which services called in DXE and later
> (gDS->... vs. gBS->...), affect which level.
> 
> ... I sincerely hope that someone who participated in the design &
> implementation of these parts will chime in. In any case, the above is
> how I think about this stuff.
> 
> Thanks
> Laszlo
> 
>> 
>> Thanks !
>> 
>> Cheers,
>> Ben.
>> 
>> 
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel
>> 
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel

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

Reply via email to