Boot Time Memory Management
Boot Time Memory Management
Memory Management
Mike Rapoport
<[email protected]>
● Memory initialization
● memblock: API and internals
● From memblock to kmalloc
Even the physical page allocator … needs to allocate
memory to initialise itself. But how can the physical
page allocator allocate memory to initialise itself?
Tread carefully!
From _start: to mm_init()
● v2.0:
● v2.3.23pre3:
○ bootmem - a First Fit allocator which uses a bitmap to represent memory
From bootmem to memblock
memory reserved
base
size
flags
nid
● memblock_add(), memblock_add_node()
○ Register memory bank with memblock
● memblock_remove()
○ Make memory region invisible to the kernel
● memblock_reserve()
○ Mark used memory region as reserved
● memblock_free()
○ Mark memory region as free
Allocation APIs returning physical address
● memblock_phys_alloc()
○ Allocate chunk of requested size with specified alignment
● memblock_phys_alloc_range()
○ Allocate a chunk within certain range
● memblock_phys_alloc_try_nid()
○ Allocate a chunk on a certain NUMA node
● memblock_alloc_try_nid_raw(),
memblock_alloc_try_nid()
○ Allocate chunk of requested size with specified alignment from certain NUMA
node and within certain range
○ If constraints are too tight, try another node and then drop lower limit
● The “normal” variant clears the memory
● The ‘_raw’ variant does not!
○ Could be poisoned if VM debug is enabled
And their convenience wrappers
Functions that allocate memory, clear it and return its virtual address:
● memblock_alloc()
○ Allocate chunk of requested size with specified alignment
● memblock_alloc_from()
○ Allocate chunk above certain physical address
● memblock_alloc_low()
○ Allocate chunk in low memory
● memblock_alloc_node()
○ Allocate chunk in certain NUMA node
Convenience wrappers cont.
● memblock_alloc_raw()
○ Allocate chunk of requested size with specified alignment
● The memory is not cleared
○ Could be poisoned if VM debug is enabled
Under the hood
● memblock_find_in_range_node()
○ Find free area in given range and node
○ Traverses free memory areas
■ memory && !reserved
○ Can be top-down or bottom-up
● memblock_alloc_range_nid()
○ Try to find free memory with all the constraints
○ Retry on all nodes
○ Retry without mirroring requirement
■ Only on systems that support memory mirroring
○ Return physical address
● memblock_alloc_internal()
○ Try memblock_alloc_range_nid()
○ Retry without the lower bound
○ Return virtual address
Controlling memblock behaviour
● memblock_allow_resize()
○ Enable/disable resizing of memblock arrays
● memblock_set_bottom_up()
○ Set allocation direction (default is top-down)
● memblock_enforce_memory_limit()
● memblock_cap_memory_range()
● memblock_mem_limit_remove_map()
● memblock_set_current_limit()
● memblock_trim_memory()
Querying memblock state
● memblock_phys_mem_size(), memblock_reserved_size()
● memblock_start_of_DRAM(), memblock_end_of_DRAM()
● memblock_is_memory(), memblock_is_reserved()
○ Check for a given address
● memblock_is_region_memory(), memblock_is_region_reserved()
○ Check for a given range
● memblock_get_current_limit()
○ Get high limit for allowed allocations
Traversing memblock arrays
● for_each_free_mem_range(), for_each_free_mem_range_reverse()
○ Iterate over free memory areas
○ Take into account node and memory attributes
● for_each_reserved_mem_region()
○ Iterate over reserved memory areas
● for_each_mem_range(), for_each_mem_range_rev()
○ Iterate over intersection of memblock arrays
■ For example areas found in memory and absent in reserved
● for_each_mem_pfn_range()
● for_each_memblock()
● for_each_memblock_type()
Back to MM init