88//!
99//! SPDX-License-Identifier: Apache-2.0
1010//!
11- use crate :: { GCD , protocols:: PROTOCOL_DB } ;
11+ use crate :: { GCD , allocator :: DEFAULT_PAGE_ALLOCATION_GRANULARITY , protocols:: PROTOCOL_DB } ;
1212use core:: ffi:: c_void;
1313use patina:: {
1414 guids:: ZERO ,
@@ -211,13 +211,16 @@ pub(crate) fn with_global_lock<F: Fn() + std::panic::RefUnwindSafe>(f: F) -> Res
211211
212212/// Allocates a chunk of memory of the specified size from the system allocator.
213213///
214+ /// The memory allocated will be 64Kb aligned to simplify alignment requirements such
215+ /// as AArch64 runtime memory.
216+ ///
214217/// ## Safety
215218/// This function is intended for test code only. The caller must ensure that the size is valid
216219/// for allocation.
217220pub ( crate ) unsafe fn get_memory ( size : usize ) -> & ' static mut [ u8 ] {
218221 // SAFETY: Test code - allocates memory from the system allocator with UEFI page alignment.
219222 // The returned slice is intentionally leaked for test simplicity and valid for 'static lifetime.
220- let addr = unsafe { alloc:: alloc:: alloc ( alloc:: alloc:: Layout :: from_size_align ( size, 0x1000 ) . unwrap ( ) ) } ;
223+ let addr = unsafe { alloc:: alloc:: alloc ( alloc:: alloc:: Layout :: from_size_align ( size, 0x10000 ) . unwrap ( ) ) } ;
221224 // SAFETY: The allocated pointer is valid for `size` bytes and properly aligned.
222225 unsafe { core:: slice:: from_raw_parts_mut ( addr, size) }
223226}
@@ -285,16 +288,17 @@ pub(crate) fn build_test_hob_list(mem_size: u64) -> *const c_void {
285288 // SAFETY: Test code - allocates memory for the test HOB list.
286289 let mem = unsafe { get_memory ( mem_size as usize ) } ;
287290 let mem_base = mem. as_mut_ptr ( ) as u64 ;
291+ assert ! ( mem_size >= 0x1B0000 ) ;
288292
289293 // Build a test HOB list that describes memory layout as follows:
290294 //
291295 // Base: offset 0 ************
292296 // HobList: offset base+0 HOBS
293297 // Empty: offset base+HobListSize N/A
294- // SystemMemory offset base+0xE0000 SystemMemory (resource_descriptor1)
295- // Reserved offset base+0xF0000 Untested SystemMemory (resource_descriptor2)
296- // FreeMemory offset base+0x100000 FreeMemory (phit)
297- // End offset base+0x200000 ************
298+ // SystemMemory offset base+0x0E0000 SystemMemory (resource_descriptor1)
299+ // Reserved offset base+0x190000 Untested SystemMemory (resource_descriptor2)
300+ // FreeMemory offset base+0x1A0000 FreeMemory (phit)
301+ // End offset base+mem_size ************
298302 //
299303 // The test HOB list will also include resource descriptor hobs that describe MMIO/IO as follows:
300304 // MMIO at 0x10000000 size 0x1000000 (resource_descriptor3)
@@ -304,9 +308,15 @@ pub(crate) fn build_test_hob_list(mem_size: u64) -> *const c_void {
304308 // Reserved Legacy I/O at 0x0000 size 0x1000 (resource_descriptor7)
305309 //
306310 // The test HOB list will also include resource allocation hobs that describe allocations as follows:
307- // A Memory Allocation Hob for each memory type. This will be placed in the SystemMemory region at base+0xE0000 as
308- // 4K allocations. There is also a Memory Allocation Hob for MMIO space at 0x10000000 for 0x2000 bytes.
309- // A Firmware Volume HOB located in the FirmwareDevice region at 0x10000000
311+ // A Memory Allocation Hob for each memory type. This will be placed in the SystemMemory region at base+0xE0000 with
312+ // appropriate granularity for each type (64KB for runtime types on aarch64, 4KB otherwise). There is also a Memory
313+ // Allocation Hob for MMIO space at 0x10000000 for 0x2000 bytes. A Firmware Volume HOB located in the FirmwareDevice
314+ // region at 0x10000000
315+ //
316+ // The system memory is of length 0xB0000 bytes. This includes 0xA0000 for the regular allocations plus 0x10000 for
317+ // potential stack allocations. 0xA0000 bytes allows for each memory type to be aligned up to 64kb. Really, only
318+ // 0x70000 bytes is needed for that in the current layout of allocation hobs, but leaving room provides flexibility
319+ // for future changes.
310320 //
311321 let phit = hob:: PhaseHandoffInformationTable {
312322 header : header:: Hob {
@@ -319,11 +329,13 @@ pub(crate) fn build_test_hob_list(mem_size: u64) -> *const c_void {
319329 memory_top : mem_base + mem_size,
320330 memory_bottom : mem_base,
321331 free_memory_top : mem_base + mem_size,
322- free_memory_bottom : mem_base + 0x100000 ,
332+ free_memory_bottom : mem_base + 0x1A0000 ,
323333 end_of_hob_list : mem_base
324334 + core:: mem:: size_of :: < hob:: PhaseHandoffInformationTable > ( ) as u64
325335 + core:: mem:: size_of :: < hob:: Cpu > ( ) as u64
326336 + ( core:: mem:: size_of :: < ResourceDescriptorV2 > ( ) as u64 ) * 7
337+ + ( core:: mem:: size_of :: < hob:: MemoryAllocation > ( ) as u64 ) * 11 // 10 memory type allocations + 1 MMIO
338+ + core:: mem:: size_of :: < hob:: FirmwareVolume > ( ) as u64
327339 + core:: mem:: size_of :: < header:: Hob > ( ) as u64 ,
328340 } ;
329341
@@ -345,7 +357,7 @@ pub(crate) fn build_test_hob_list(mem_size: u64) -> *const c_void {
345357 resource_type : hob:: EFI_RESOURCE_SYSTEM_MEMORY ,
346358 resource_attribute : hob:: TESTED_MEMORY_ATTRIBUTES | hob:: EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE ,
347359 physical_start : mem_base + 0xE0000 ,
348- resource_length : 0x10000 ,
360+ resource_length : 0xB0000 ,
349361 } ,
350362 attributes : efi:: MEMORY_WB ,
351363 } ;
@@ -360,7 +372,7 @@ pub(crate) fn build_test_hob_list(mem_size: u64) -> *const c_void {
360372 owner : efi:: Guid :: from_fields ( 0 , 0 , 0 , 0 , 0 , & [ 0u8 ; 6 ] ) ,
361373 resource_type : hob:: EFI_RESOURCE_SYSTEM_MEMORY ,
362374 resource_attribute : hob:: INITIALIZED_MEMORY_ATTRIBUTES | hob:: EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE ,
363- physical_start : mem_base + 0xF0000 ,
375+ physical_start : mem_base + 0x190000 ,
364376 resource_length : 0x10000 ,
365377 } ,
366378 attributes : efi:: MEMORY_WB ,
@@ -516,7 +528,8 @@ pub(crate) fn build_test_hob_list(mem_size: u64) -> *const c_void {
516528 cursor = cursor. offset ( resource_descriptor7. v1 . header . length as isize ) ;
517529
518530 //memory allocation HOBs.
519- for ( idx, memory_type) in [
531+ let mut address: u64 = resource_descriptor1. v1 . physical_start ;
532+ for memory_type in [
520533 efi:: RESERVED_MEMORY_TYPE ,
521534 efi:: LOADER_CODE ,
522535 efi:: LOADER_DATA ,
@@ -529,16 +542,29 @@ pub(crate) fn build_test_hob_list(mem_size: u64) -> *const c_void {
529542 efi:: PAL_CODE ,
530543 ]
531544 . iter ( )
532- . enumerate ( )
533545 {
534- allocation_hob_template. alloc_descriptor . memory_base_address =
535- resource_descriptor1. v1 . physical_start + idx as u64 * 0x1000 ;
546+ let granularity = match * memory_type {
547+ efi:: RESERVED_MEMORY_TYPE
548+ | efi:: RUNTIME_SERVICES_CODE
549+ | efi:: RUNTIME_SERVICES_DATA
550+ | efi:: ACPI_MEMORY_NVS => crate :: allocator:: RUNTIME_PAGE_ALLOCATION_GRANULARITY ,
551+ _ => DEFAULT_PAGE_ALLOCATION_GRANULARITY ,
552+ } as u64 ;
553+
554+ // Make sure the memory region is aligned as needed.
555+ address = patina:: base:: align_up ( address, granularity) . unwrap ( ) ;
556+ allocation_hob_template. alloc_descriptor . memory_base_address = address;
536557 allocation_hob_template. alloc_descriptor . memory_type = * memory_type;
558+ allocation_hob_template. alloc_descriptor . memory_length = granularity;
537559
538560 core:: ptr:: copy ( & allocation_hob_template, cursor as * mut hob:: MemoryAllocation , 1 ) ;
539561 cursor = cursor. offset ( allocation_hob_template. header . length as isize ) ;
562+ address += granularity;
540563 }
541564
565+ // Double check this never over-runs the memory region.
566+ assert ! ( address <= resource_descriptor1. v1. physical_start + resource_descriptor1. v1. resource_length) ;
567+
542568 // memory allocation HOB for MMIO space
543569 allocation_hob_template. alloc_descriptor . memory_base_address = resource_descriptor3. v1 . physical_start ;
544570 allocation_hob_template. alloc_descriptor . memory_length = 0x2000 ;
0 commit comments