Add PEI memory bin support [Rebase & FF]#1486
Open
makubacki wants to merge 7 commits into
Open
Conversation
Contributor
✅ QEMU Validation PassedAll QEMU validation jobs completed successfully.
Workflow run: https://github.com/OpenDevicePartnership/patina/actions/runs/25883287456 Boot Time to EFI Shell
Dependencies
This comment was automatically generated by the Patina QEMU PR Validation Post workflow. |
5 tasks
65ae4ee to
0f8e356
Compare
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Contributor
|
@makubacki, you've requested reviews, but the PR is still in draft. Is this ready to be reviewed? |
os-d
reviewed
May 5, 2026
0f8e356 to
fbd70bd
Compare
Allow EfiMemoryTypeInformation to be easily duplicated, as it is a simple struct containing only Copy types. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Provide a stable constant to represent the maximum valid EFI memory instead of hardcoding the value based on the last valid memory type. INVALID_INFORMATION_INDEX is added as a sentinel value to indicate an invalid memory type index in the memory type information table. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Adds the following helpers to help working with page operations: - `align_pages_to_granularity(pages, granularity)` - Aligns a page count up to the specified byte granularity. This is useful for calculating aligned page counts for memory types with allocation granularities larger than the page size. - `page_shift_from_alignment(alignment)` - Converts a page-aligned byte granularity to the corresponding bit shift value. This is useful for determining the shift needed to convert between addresses and page frame numbers. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
6d1543a to
0516433
Compare
Memory bins are pre-allocated, per-type regions of memory for EFI runtime memory types (ReservedMemory, RuntimeServicesCode, RuntimeServicesData, ACPIMemoryNVS, ACPIReclaimMemory). By over reserving these regions at a fixed size, the memory map presented to the OS has a much greater chance of remaining stable across boots, which is required for S4 (hibernate) resume. This commit adds support for PEI memory bins allocated prior to DXE, such as in PEI, where the bin information is given to the Patina DXE core via HOBs. A new module called MemoryBinManager is added. It tracks bin state: preferred ranges, allocation statistics, and the memory type information published to the EFI config table in addition to related bin logic for when producing the EFI memory map. Two initialization paths are supported: Path A - PEI-provided bins: A Resource Descriptor HOB with owner GUID gEfiMemoryTypeInformationGuid describes a contiguous region PEI set aside for bins. Bins are divided within that region with per-type granularity. Free GCD pages within each bin range are claimed with ownership preservation so other allocators cannot expand into them. Path B - DXE-allocated bins: If a PEI region HOB does not exist, each bin type is allocated directly from the GCD using allocate-then-free with ownership preservation. After bin initialization, seed_bin_statistics_from_hobs() scans Memory Allocation HOBs whose Name matches gEfiMemoryTypeInformationGuid to account for these potential PEI-phase allocations inside bin regions in initial bin statistics. On every AllocatePages()/FreePages() call, record_allocation() and record_free() update the bin statistics for the relevant type. On free, if the pages fall within a bin range, GCD ownership is re-established to prevent other allocators from reclaiming those pages. GetMemoryMap() calls apply_bin_descriptors() after populating the EFI memory map. This post-processing step converts EfiConventionalMemory entries that overlap bin ranges to the bin's memory type, splitting entries at bin boundaries as needed. The buffer-size calculation is updated to account for up to two extra descriptors per active bin. install_memory_type_info_table() prefers the bin manager's peak-usage data when bins are initialized. The previous reserve_memory_pages() API on PageAllocator and SpinLockedFixedSizeBlockAllocator is removed with logic moved into MemoryBinManager. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Refactor Path B (DXE-allocated bins) to allocate a single contiguous block from the GCD instead of separate per-type allocations. The block is freed and then follows the same path as PEI-provided bins (Path A). In the process, some code is unified and the logic to map bin memory type allocators to their ranges can be simplified. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
The GCD struct held a large EFiMemoryTypeInformation array that each FixedSizeBlockAllocator wrote to with NonNull on every alloc, free, and pool expansion. This was used as a config table fallback for memory type allocation stats. This change replaces the NonNull<EFiMemoryTypeInformation> field in the FSB with a plain memory_type: efi::MemoryType field. In the process, this also eliminates two unsafe pointer dereferences and an update_gcd_stats() call on every allocation. An allocator stats dump now calculates stats on demand. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
- Enhance memory bin trace level logging detail. - Update memory_type_name() to return a static string to eliminate heap allocations in the call. - Dump memory bin stats at debug level in get_memory_map() when the memory_bin log target is enabled. - Dump allocator stats at trace level in get_memory_map() when trace trace logging is enabled. Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
0516433 to
4dd8235
Compare
Collaborator
Author
Testing was still in progress at the time. I've taken it out of draft. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
A few small commits for miscellaneous changes followed by the main commit for PEI memory bins.
sdk: Derive Clone and Copy for EFiMemoryTypeInformation
Allow
EfiMemoryTypeInformationto be easily duplicated, as it is a simple struct containing onlyCopytypes.sdk: Add
EFI_MAX_MEMORY_TYPEandINVALID_INFORMATION_INDEXconstantsProvide a stable constant to represent the maximum valid EFI memory instead of hardcoding the value based on the last valid memory type.
INVALID_INFORMATION_INDEXis added as a sentinel value to indicate an invalid memory type index in the memory type information table.sdk: Add more page helpers to base.rs
Adds the following helpers to help working with page operations:
align_pages_to_granularity(pages, granularity)- Aligns a page count up to the specified byte granularity. This is useful for calculating aligned page counts for memory types with allocation granularities larger than the page size.page_shift_from_alignment(alignment)- Converts a page-aligned byte granularity to the corresponding bit shift value. This is useful for determining the shift needed to convert between addresses and page frame numbers.patina_dxe_core: Add PEI memory bin support
Memory bins are pre-allocated, per-type regions of memory for EFI runtime memory types (
ReservedMemory,RuntimeServicesCode,RuntimeServicesData,ACPIMemoryNVS,ACPIReclaimMemory). By over reserving these regions at a fixed size, the memory map presented to the OS has a much greater chance of remaining stable across boots, which is required for S4 (hibernate) resume.This commit adds support for PEI memory bins allocated prior to DXE, such as in PEI, where the bin information is given to the Patina DXE core via HOBs.
A new module called
MemoryBinManageris added. It tracks bin state: preferred ranges, allocation statistics, and the memory type information published to the EFI config table in addition to related bin logic for when producing the EFI memory map.Two initialization paths are supported:
Path A - PEI-provided bins: A Resource Descriptor HOB with owner GUID
gEfiMemoryTypeInformationGuiddescribes a contiguous region PEI set aside for bins. Bins are divided within that region with per-type granularity. Free GCD pages within each bin range are claimed with ownership preservation so other allocators cannot expand into them.Path B - DXE-allocated bins: If a PEI region HOB does not exist, each bin type is allocated directly from the GCD using allocate-then-free with ownership preservation.
After bin initialization,
seed_bin_statistics_from_hobs()scans Memory Allocation HOBs whose Name matchesgEfiMemoryTypeInformationGuidto account for these potential PEI-phase allocations inside bin regions in initial bin statistics.On every
AllocatePages()/FreePages()call,record_allocation()andrecord_free()update the bin statistics for the relevant type. On free, if the pages fall within a bin range, GCD ownership is re-established to prevent other allocators from reclaiming those pages.GetMemoryMap()callsapply_bin_descriptors()after populating the EFI memory map. This post-processing step convertsEfiConventionalMemoryentries that overlap bin ranges to the bin's memory type, splitting entries at bin boundaries as needed. The buffer-size calculation is updated to account for up to two extra descriptors per active bin.install_memory_type_info_table()prefers the bin manager's peak-usage data when bins are initialized.The previous
reserve_memory_pages()API onPageAllocatorandSpinLockedFixedSizeBlockAllocatoris removed with logic moved intoMemoryBinManager.How This Was Tested
Integration Instructions
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiMemoryBinsEnabletoTRUEPEI Bins Active Example
PEI Output: Bin allocation
Patina DXE Output
memory_binlog target at tracePatina DXE Output: Init
Patina DXE Output: Memory Map
EfiReservedMemoryTypeallocations of RT types intentionally outside bin ranges.PEI Bins Inactive Example
Patina DXE Output
memory_binlog target at tracePatina DXE Output: Init
Patina DXE Output: Memory Map