-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replaces the freelist-based page allocator and can be used for lifetime of kernel. Signed-off-by: Graham MacDonald <[email protected]>
- Loading branch information
Showing
10 changed files
with
585 additions
and
114 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/// This module acts as an interface between the portable allocator and the | ||
/// arch-specific use of it. | ||
/// | ||
/// The page allocator is constructed and finalised in a number of phases: | ||
/// 1. `init_page_allocator` to create a fixed size allocator assuming everything | ||
/// is in use except a small number of statically defined pages available for | ||
/// setting up the initial page tables. | ||
/// 2. `free_unused_ranges` to mark available ranges as the inverse of the | ||
/// physical memory map within the bounds of the available memory. | ||
use crate::kmem; | ||
use crate::kmem::physaddr_as_ptr_mut; | ||
use crate::vm::Page4K; | ||
use port::bitmapalloc::BitmapPageAlloc; | ||
use port::bitmapalloc::BitmapPageAllocError; | ||
use port::mem::PhysRange; | ||
use port::{ | ||
mcslock::{Lock, LockNode}, | ||
mem::PAGE_SIZE_4K, | ||
}; | ||
|
||
/// Set up bitmap page allocator assuming everything is allocated. | ||
static PAGE_ALLOC: Lock<BitmapPageAlloc<16, PAGE_SIZE_4K>> = Lock::new( | ||
"page_alloc", | ||
const { BitmapPageAlloc::<16, PAGE_SIZE_4K>::new_all_allocated(PAGE_SIZE_4K) }, | ||
); | ||
|
||
/// The bitmap allocator has all pages marked as allocated initially. We'll | ||
/// add some pages (mark free) to allow us to set up the page tables and build | ||
/// a memory map. Once the memory map has been build, we can mark all the unused | ||
/// space as available. This allows us to use only one page allocator throughout. | ||
pub fn init_page_allocator() { | ||
let node = LockNode::new(); | ||
let mut lock = PAGE_ALLOC.lock(&node); | ||
let page_alloc = &mut *lock; | ||
|
||
let early_pages_range = kmem::early_pages_range(); | ||
if let Err(err) = page_alloc.mark_free(&early_pages_range) { | ||
panic!("Couldn't mark early pages free: range: {} err: {:?}", early_pages_range, err); | ||
} | ||
} | ||
|
||
/// Free unused pages in mem that aren't covered by the memory map. Assumes | ||
/// that custom_map is sorted. | ||
pub fn free_unused_ranges<'a>( | ||
available_mem: &PhysRange, | ||
used_ranges: impl Iterator<Item = &'a PhysRange>, | ||
) -> Result<(), BitmapPageAllocError> { | ||
let node = LockNode::new(); | ||
let mut lock = PAGE_ALLOC.lock(&node); | ||
let page_alloc = &mut *lock; | ||
|
||
page_alloc.free_unused_ranges(available_mem, used_ranges) | ||
} | ||
|
||
/// Try to allocate a page | ||
pub fn allocate() -> Result<&'static mut Page4K, BitmapPageAllocError> { | ||
let node = LockNode::new(); | ||
let mut lock = PAGE_ALLOC.lock(&node); | ||
let page_alloc = &mut *lock; | ||
|
||
match page_alloc.allocate() { | ||
Ok(page_pa) => Ok(unsafe { &mut *physaddr_as_ptr_mut::<Page4K>(page_pa) }), | ||
Err(err) => Err(err), | ||
} | ||
} | ||
|
||
/// Return a tuple of (bytes used, total bytes available) based on the page allocator. | ||
pub fn usage_bytes() -> (usize, usize) { | ||
let node = LockNode::new(); | ||
let mut lock = PAGE_ALLOC.lock(&node); | ||
let page_alloc = &mut *lock; | ||
page_alloc.usage_bytes() | ||
} |
This file contains 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
Oops, something went wrong.