Memory Management
Physical/virtual memory management, allocators, and grants.
src/memory/emergency.rs
Memory pressure governor and sacred emergency frame reserve.
EMERGENCY_UI_FRAMES const
const EMERGENCY_UI_FRAMES : usizeFixed UI reserve — never touched by normal allocations.
PressureState enum
enum PressureState {
Normal = 0,
Warning = 1,
Emergency = 2,
Evacuating = 3,
Picker = 4,
Restoring = 5,
}buffer_frames fn
fn buffer_frames() -> usizereserve_frames fn
fn reserve_frames() -> usizestate fn
fn state() -> PressureStateset_state fn
fn set_state(next : PressureState)system_frozen fn
fn system_frozen() -> boolset_system_frozen fn
fn set_system_frozen(frozen : bool)emergency_watermark fn
fn emergency_watermark() -> usizewarning_watermark_frames fn
fn warning_watermark_frames(_total : usize, buffer : usize) -> usizeemergency_watermark_frames fn
fn emergency_watermark_frames(_total : usize, _buffer : usize) -> usizeinit_reserve fn
fn init_reserve()Initialize the sacred reserve after the physical memory allocator is ready.
check_before_alloc fn
fn check_before_alloc() -> boolCalled before every normal frame allocation.
alloc_emergency_frame fn
fn alloc_emergency_frame() -> Option<Frame>Pop one frame from the UI portion of the sacred reserve (emergency path only).
on_oom fn
fn on_oom()stats_string fn
fn stats_string(buf : &mut [u8]) -> usizesrc/memory/kernel_mapper.rs
KernelMapper struct
struct KernelMapper { /* … */ }A guard to the global lock protecting the upper 128 TiB of kernel address space.
NOTE: Use this with great care! Since heap allocations may also require this lock when the heap needs to be expended, it must not be held while memory allocations are done!
src/memory/mod.rs
Memory management
Some code was borrowed from Phil Opp's Blog
free_frames fn
fn free_frames() -> usizeGet the number of frames available
used_frames fn
fn used_frames() -> usizeGet the number of frames used
total_frames fn
fn total_frames() -> usizeallocate_p2frame fn
fn allocate_p2frame(order : u32) -> Option<Frame>Allocate a range of frames
allocate_frame fn
fn allocate_frame() -> Option<Frame>allocate_p2frame_complex fn
fn allocate_p2frame_complex(_req_order : u32, _flags :(), _strategy : Option<()>, min_order : u32,) -> Option<(Frame, usize)>deallocate_p2frame fn
unsafe fn deallocate_p2frame(orig_frame : Frame, order : u32)deallocate_frame fn
unsafe fn deallocate_frame(frame : Frame)map_device_memory fn
unsafe fn map_device_memory(addr : PhysicalAddress, len : usize) -> VirtualAddressFrame struct
struct Frame { /* … */ }Frame::containing fn
fn containing(address : PhysicalAddress) -> FrameCreate a frame containing address
Frame::base fn
fn base(self) -> PhysicalAddressGet the address of this frame
Enomem struct
struct Enomem { /* … */ }RaiiFrame struct
struct RaiiFrame { /* … */ }PageInfo struct
struct PageInfo { /* … */ }Section struct
struct Section { /* … */ }MAX_SECTION_SIZE_BITS const
const MAX_SECTION_SIZE_BITS : u32MAX_SECTION_SIZE const
const MAX_SECTION_SIZE : usizeMAX_SECTION_PAGE_COUNT const
const MAX_SECTION_PAGE_COUNT : usizeinit_mm fn
fn init_mm(allocator : BumpAllocator<RmmA>)AddRefError enum
enum AddRefError {
CowToShared,
SharedToCow,
RcOverflow,
}RefKind enum
enum RefKind {
Cow,
Shared,
}RefCount enum
enum RefCount {
One,
Shared,
Cow,
}get_page_info fn
fn get_page_info(frame : Frame) -> Option<&'static PageInfo>Segv struct
struct Segv { /* … */ }ArchIntCtx trait
trait ArchIntCtx { /* … */ }page_fault_handler fn
fn page_fault_handler(stack : &mut impl ArchIntCtx, code : GenericPfFlags, faulting_address : VirtualAddress,) -> Result<(), Segv>the_zeroed_frame fn
fn the_zeroed_frame() ->(Frame, &'static PageInfo)init_frame fn
fn init_frame(init_rc : RefCount) -> Result<Frame, PfError>TheFrameAllocator struct
struct TheFrameAllocator { /* … */ }src/startup/memory.rs
BootloaderMemoryKind enum
enum BootloaderMemoryKind {
Null = 0,
Free = 1,
Reclaim = 2,
Reserved = 3,
Kernel = 0x100,
Device = 0x101,
IdentityMap = 0x102,
}register_memory_region fn
fn register_memory_region(base : usize, size : usize, kind : BootloaderMemoryKind)register_bootloader_areas fn
fn register_bootloader_areas(areas_base : usize, areas_size : usize)init fn
unsafe fn init(low_limit : Option<usize>, high_limit : Option<usize>)src/allocator/linked_list.rs
Allocator struct
struct Allocator { /* … */ }src/allocator/slab.rs
Allocator struct
struct Allocator { /* … */ }src/allocator/mod.rs
init fn
unsafe fn init()src/context/memory.rs
MMAP_MIN_DEFAULT const
const MMAP_MIN_DEFAULT : usizepage_flags fn
fn page_flags(flags : MapFlags) -> PageFlags<RmmA>map_flags fn
fn map_flags(page_flags : PageFlags<RmmA>) -> MapFlagsUnmapResult struct
struct UnmapResult { /* … */ }AddrSpaceWrapper struct
struct AddrSpaceWrapper { /* … */ }AddrSpace struct
struct AddrSpace { /* … */ }AddrSpaceWrapper::try_clone fn
fn try_clone(&self) -> Result<Arc<AddrSpaceWrapper>>Attempt to clone an existing address space so that all mappings are copied (CoW).
AddrSpaceWrapper::borrow_frame_enforce_rw_allocated fn
fn borrow_frame_enforce_rw_allocated(self : &Arc<Self>, page : Page) -> Result<RaiiFrame>Borrows a page from user memory, requiring that the frame be Allocated and read/write. This is intended to be used for user-kernel shared memory.
UserGrants struct
struct UserGrants { /* … */ }PageSpan struct
struct PageSpan { /* … */ }PageSpan::before fn
fn before(self, span : Self) -> Option<Self>Returns the span from the start of self until the start of the specified span.
PageSpan::after fn
fn after(self, span : Self) -> Option<Self>Returns the span from the end of the given span until the end of self.
PageSpan::between fn
fn between(start : Page, end : Page) -> SelfReturns the span between two pages, [start, end), truncating to zero if end < start.
UserGrants::contains fn
fn contains(&self, page : Page) -> Option<(Page, &GrantInfo)>Returns the grant, if any, which occupies the specified page
UserGrants::conflicts fn
fn conflicts(&self, span : PageSpan) -> impl Iterator<Item =(Page, &'_ GrantInfo)> + '_Returns an iterator over all grants that occupy some part of the requested region
UserGrants::find_free_near fn
fn find_free_near(&self, min : usize, page_count : usize, _near : Option<Page>,) -> Option<PageSpan>Return a free region with the specified size
GrantInfo struct
struct GrantInfo { /* … */ }Provider enum
enum Provider {
Allocated,
AllocatedShared,
PhysBorrowed,
External,
FmapBorrowed,
}Enumeration of various types of grants.
Grant struct
struct Grant { /* … */ }GrantFileRef struct
struct GrantFileRef { /* … */ }Grant::borrow fn
fn borrow(src_address_space_lock : Arc<AddrSpaceWrapper>, src_address_space : &mut AddrSpace, src_base : Page, dst_base : Page, page_count : usize, map_flags : MapFlags, dst_mapper : &mut PageMapper, dst_flusher : &mut Flusher, eager : bool, _allow_phys : bool, is_pinned_userscheme_borrow : bool,) -> Result<Grant>Borrow all pages in the range [src_base, src_base+page_count) from src_address_space, mapping them into [dst_base, dst_base+page_count). The destination pages will lazily read the page tables of the source pages, but once present in the destination address space, pages that are unmaped or moved will not be made visible to the destination address space.
Grant::transfer fn
fn transfer(mut self, dst_base : Page, flags : PageFlags<RmmA>, src_mapper : &mut PageMapper, mut dst_mapper : Option<&mut PageMapper>, src_flusher : &mut Flusher, dst_flusher : &mut impl GenericFlusher,) -> Result<Grant>Move a grant between two address spaces.
Grant::span fn
fn span(&self) -> PageSpanExtract out a region into a separate grant. The return value is as follows: (before, new split, after). Before and after may be None, which occurs when the split off region is at the start or end of the page respectively.
Panics
Panics if the start or end addresses of the region is not aligned to the page size. To round up the size to the nearest page size, use .round() on the region.
Also panics if the given region isn't completely contained within the grant. Use grant.intersect to find a sub-region that works.
DANGLING const
const DANGLING : usizeTable struct
struct Table { /* … */ }AccessMode enum
enum AccessMode {
Read,
Write,
InstrFetch,
}PfError enum
enum PfError {
Segv,
Oom,
NonfatalInternalError,
RecursionLimitExceeded,
}CowResult struct
struct CowResult { /* … */ }copy_frame_to_frame_directly fn
unsafe fn copy_frame_to_frame_directly(dst : Frame, src : Frame)try_correcting_page_tables fn
fn try_correcting_page_tables(faulting_page : Page, access : AccessMode) -> Result<(), PfError>MmapMode enum
enum MmapMode {
Cow,
Shared,
}BorrowedFmapSource struct
struct BorrowedFmapSource { /* … */ }handle_notify_files fn
fn handle_notify_files(notify_files : Vec<UnmapResult>)CopyMappingsMode enum
enum CopyMappingsMode {
Owned,
Borrowed,
}GenericFlusher trait
trait GenericFlusher { /* … */ }NopFlusher struct
struct NopFlusher { /* … */ }Flusher struct
struct Flusher { /* … */ }