docs: add code documentation

This commit is contained in:
2026-03-15 13:18:12 +01:00
parent 95a5037b91
commit dfb4d094a3
2 changed files with 35 additions and 11 deletions

View File

@@ -13,9 +13,12 @@ const BLOCK: u64 = 0b01;
const TABLE: u64 = 0b11; const TABLE: u64 = 0b11;
const PAGE: u64 = 0b11; const PAGE: u64 = 0b11;
/// Allow EL0 to access this section
pub const EL0_ACCESSIBLE: u64 = 1 << 6; pub const EL0_ACCESSIBLE: u64 = 1 << 6;
/// Allow a page or block to be written.
pub const WRITABLE: u64 = 0 << 7; pub const WRITABLE: u64 = 0 << 7;
/// Disallow a page or block to be written.
pub const READ_ONLY: u64 = 1 << 7; pub const READ_ONLY: u64 = 1 << 7;
const ACCESS_FLAG: u64 = 1 << 10; const ACCESS_FLAG: u64 = 1 << 10;
@@ -47,6 +50,7 @@ pub static mut TRANSLATIONTABLE_TTBR0: PageTable = PageTable([0; 512]);
static mut PAGING_BITMAP: [u64; MAX_PAGE_COUNT / 64] = [0; MAX_PAGE_COUNT / 64]; static mut PAGING_BITMAP: [u64; MAX_PAGE_COUNT / 64] = [0; MAX_PAGE_COUNT / 64];
/// Allocate a memory block of `size` starting at `virtual_address`.
pub fn allocate_memory( pub fn allocate_memory(
mut virtual_address: usize, mut virtual_address: usize,
mut size: usize, mut size: usize,
@@ -93,6 +97,10 @@ pub fn allocate_memory(
Ok(()) Ok(())
} }
/// Allocate a memory block of `size` starting at `virtual_address`,
/// with explicit `physical_address``.
///
/// Note: This can be used when mapping predefined regions.
pub fn allocate_memory_explicit( pub fn allocate_memory_explicit(
mut virtual_address: usize, mut virtual_address: usize,
mut size: usize, mut size: usize,
@@ -169,6 +177,7 @@ pub fn allocate_memory_explicit(
Ok(()) Ok(())
} }
/// Allocate a singe page.
pub fn alloc_page( pub fn alloc_page(
virtual_address: usize, virtual_address: usize,
base_table: &mut PageTable, base_table: &mut PageTable,
@@ -182,6 +191,7 @@ pub fn alloc_page(
) )
} }
/// Allocate a single page at an explicit `physical_address`.
pub fn alloc_page_explicit( pub fn alloc_page_explicit(
virtual_address: usize, virtual_address: usize,
physical_address: usize, physical_address: usize,
@@ -218,6 +228,7 @@ fn map_page(
Ok(()) Ok(())
} }
/// Allocate a level 2 block.
pub fn alloc_block_l2( pub fn alloc_block_l2(
virtual_addr: usize, virtual_addr: usize,
base_table: &mut PageTable, base_table: &mut PageTable,
@@ -226,6 +237,7 @@ pub fn alloc_block_l2(
map_l2_block(virtual_addr, reserve_block(), base_table, additional_flags) map_l2_block(virtual_addr, reserve_block(), base_table, additional_flags)
} }
/// Allocate a level 2 block, at a explicit `physical_address`.
pub fn alloc_block_l2_explicit( pub fn alloc_block_l2_explicit(
virtual_addr: usize, virtual_addr: usize,
physical_address: usize, physical_address: usize,
@@ -240,13 +252,17 @@ pub fn alloc_block_l2_explicit(
map_l2_block(virtual_addr, physical_address, base_table, additional_flags) map_l2_block(virtual_addr, physical_address, base_table, additional_flags)
} }
/// Map a `virtual_address` to a `physical_address`, **WITHOUT** reserving the physical addresses.
///
/// # NOTE
/// Use [`alloc_block_l2_explicit`] instead, **OR** reserve the memory with [`reserve_block_explicit`]
pub fn map_l2_block( pub fn map_l2_block(
virtual_addr: usize, virtual_address: usize,
physical_address: usize, physical_address: usize,
base_table: &mut PageTable, base_table: &mut PageTable,
additional_flags: u64, additional_flags: u64,
) -> Result<(), NovaError> { ) -> Result<(), NovaError> {
let (l1_off, l2_off, _) = virtual_address_to_table_offset(virtual_addr); let (l1_off, l2_off, _) = virtual_address_to_table_offset(virtual_address);
let offsets = [l1_off]; let offsets = [l1_off];
let table = navigate_table(base_table, &offsets)?; let table = navigate_table(base_table, &offsets)?;
@@ -261,6 +277,8 @@ pub fn map_l2_block(
Ok(()) Ok(())
} }
/// Reserve a physical address range.
pub fn reserve_range_explicit( pub fn reserve_range_explicit(
start_physical_address: usize, start_physical_address: usize,
end_physical_address: usize, end_physical_address: usize,
@@ -327,7 +345,8 @@ fn reserve_block() -> usize {
panic!("Out of Memory!"); panic!("Out of Memory!");
} }
fn reserve_block_explicit(physical_address: usize) -> Result<(), NovaError> { /// Reserve a level 2 block physical address range.
pub fn reserve_block_explicit(physical_address: usize) -> Result<(), NovaError> {
let page = physical_address / GRANULARITY; let page = physical_address / GRANULARITY;
for i in 0..L2_BLOCK_BITMAP_WORDS { for i in 0..L2_BLOCK_BITMAP_WORDS {
unsafe { unsafe {
@@ -372,16 +391,19 @@ fn virtual_address_to_table_offset(virtual_addr: usize) -> (usize, usize, usize)
(l1_off, l2_off, l3_off) (l1_off, l2_off, l3_off)
} }
/// Debugging function to navigate the translation tables.
pub fn sim_l3_access(addr: usize) { pub fn sim_l3_access(addr: usize) {
unsafe { unsafe {
let entry1 = TRANSLATIONTABLE_TTBR0.0[addr / LEVEL1_BLOCK_SIZE]; let entry1 = TRANSLATIONTABLE_TTBR0.0[addr / LEVEL1_BLOCK_SIZE];
let table2 = &mut *(get_table_entry_address(entry1) as *mut PageTable); let table2 = &mut *(entry_phys(entry1) as *mut PageTable);
let entry2 = table2.0[(addr % LEVEL1_BLOCK_SIZE) / LEVEL2_BLOCK_SIZE]; let entry2 = table2.0[(addr % LEVEL1_BLOCK_SIZE) / LEVEL2_BLOCK_SIZE];
let table3 = &mut *(get_table_entry_address(entry2) as *mut PageTable); let table3 = &mut *(entry_phys(entry2) as *mut PageTable);
let entry3 = table3.0[(addr % LEVEL2_BLOCK_SIZE) / GRANULARITY]; let entry3 = table3.0[(addr % LEVEL2_BLOCK_SIZE) / GRANULARITY];
} }
} }
/// Navigate the table tree, by following given offsets. This function
/// allocates new tables if required.
fn navigate_table<'a>( fn navigate_table<'a>(
initial_table: &'a mut PageTable, initial_table: &'a mut PageTable,
offsets: &'a [usize], offsets: &'a [usize],
@@ -394,6 +416,9 @@ fn navigate_table<'a>(
Ok(table) Ok(table)
} }
/// Get the next table one level down.
///
/// If table doesn't exit a page will be allocated for it.
fn next_table( fn next_table(
table: &mut PageTable, table: &mut PageTable,
offset: usize, offset: usize,
@@ -412,10 +437,10 @@ fn next_table(
NORMAL_MEM | WRITABLE | PXN | UXN, NORMAL_MEM | WRITABLE | PXN | UXN,
)?; )?;
Ok(unsafe { &mut *(get_table_entry_address(table.0[offset]) as *mut PageTable) }) Ok(unsafe { &mut *(entry_phys(table.0[offset]) as *mut PageTable) })
} }
1 => return Err(NovaError::Paging), 1 => return Err(NovaError::Paging),
3 => Ok(unsafe { &mut *(get_table_entry_address(table.0[offset]) as *mut PageTable) }), 3 => Ok(unsafe { &mut *(entry_phys(table.0[offset]) as *mut PageTable) }),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@@ -455,7 +480,8 @@ fn find_contiguous_free_bitmap_words(required_words: usize) -> Option<usize> {
None None
} }
/// Extracts the physical address out of an table entry.
#[inline] #[inline]
fn get_table_entry_address(entry: u64) -> u64 { fn entry_phys(entry: u64) -> u64 {
entry & 0x0000_FFFF_FFFF_F000 entry & 0x0000_FFFF_FFFF_F000
} }

View File

@@ -13,8 +13,7 @@ extern crate alloc;
use nova::{ use nova::{
aarch64::{ aarch64::{
mmu::{ mmu::{
allocate_memory_explicit, sim_l3_access, EL0_ACCESSIBLE, NORMAL_MEM, allocate_memory_explicit, sim_l3_access, EL0_ACCESSIBLE, NORMAL_MEM, PXN, UXN, WRITABLE,
PXN, UXN, WRITABLE,
}, },
registers::{daif, read_id_aa64mmfr0_el1}, registers::{daif, read_id_aa64mmfr0_el1},
}, },
@@ -74,7 +73,6 @@ pub extern "C" fn main() -> ! {
initialize_mmu_translation_tables(); initialize_mmu_translation_tables();
// Frame Buffer memory range // Frame Buffer memory range
// TODO: this is just temporary // TODO: this is just temporary
// TODO: Investigate why the size is off
allocate_memory_explicit( allocate_memory_explicit(
0x3c100000, 0x3c100000,
1080 * 1920 * 4, 1080 * 1920 * 4,