> 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