diff --git a/aarch64/src/kalloc.rs b/aarch64/src/kalloc.rs index 304a006..ff50101 100644 --- a/aarch64/src/kalloc.rs +++ b/aarch64/src/kalloc.rs @@ -10,6 +10,11 @@ struct FreeList { } unsafe impl Send for FreeList {} +#[derive(Debug)] +pub enum Error { + NoFreeBlocks, +} + impl FreeList { pub fn put(&mut self, page: &mut Page4K) { let ptr = (page as *mut Page4K).addr(); @@ -22,13 +27,13 @@ impl FreeList { self.next = ptr::NonNull::new(f); } - pub fn get(&mut self) -> Option<&'static mut Page4K> { - let mut next = self.next?; + pub fn get(&mut self) -> Result<&'static mut Page4K, Error> { + let mut next = self.next.ok_or(Error::NoFreeBlocks)?; let next = unsafe { next.as_mut() }; self.next = next.next; let pg = unsafe { &mut *(next as *mut FreeList as *mut Page4K) }; pg.clear(); - Some(pg) + Ok(pg) } } @@ -41,7 +46,7 @@ pub unsafe fn free_pages(pages: &mut [Page4K]) { } } -pub fn alloc() -> Option<&'static mut Page4K> { +pub fn alloc() -> Result<&'static mut Page4K, Error> { static mut NODE: LockNode = LockNode::new(); let mut lock = FREE_LIST.lock(unsafe { &NODE }); let fl = &mut *lock; diff --git a/aarch64/src/main.rs b/aarch64/src/main.rs index 862f70f..cbc3590 100644 --- a/aarch64/src/main.rs +++ b/aarch64/src/main.rs @@ -31,8 +31,6 @@ use vm::PageTable; #[cfg(not(test))] core::arch::global_asm!(include_str!("l.S")); -type Result = core::result::Result; - static mut KPGTBL: PageTable = PageTable::empty(); unsafe fn print_memory_range(name: &str, start: &*const c_void, end: &*const c_void) { diff --git a/aarch64/src/vm.rs b/aarch64/src/vm.rs index 80ebb72..631fd19 100644 --- a/aarch64/src/vm.rs +++ b/aarch64/src/vm.rs @@ -7,7 +7,6 @@ use crate::{ etext_addr, heap_addr, text_addr, PhysAddr, }, registers::rpi_mmio, - Result, }; use bitstruct::bitstruct; use core::fmt; @@ -17,6 +16,17 @@ use num_enum::{FromPrimitive, IntoPrimitive}; #[cfg(not(test))] use port::println; +#[derive(Debug)] +pub enum VmError { + AllocationFailed(kalloc::Error), +} + +impl From for VmError { + fn from(err: kalloc::Error) -> VmError { + VmError::AllocationFailed(err) + } +} + pub const PAGE_SIZE_4K: usize = 4 * 1024; pub const PAGE_SIZE_2M: usize = 2 * 1024 * 1024; pub const PAGE_SIZE_1G: usize = 1 * 1024 * 1024 * 1024; @@ -248,8 +258,8 @@ impl Table { } } - pub fn entry_mut(&mut self, level: Level, va: usize) -> Option<&mut Entry> { - Some(&mut self.entries[Self::index(level, va)]) + pub fn entry_mut(&mut self, level: Level, va: usize) -> Result<&mut Entry, VmError> { + Ok(&mut self.entries[Self::index(level, va)]) } fn child_table(&self, entry: Entry) -> Option<&Table> { @@ -261,12 +271,14 @@ impl Table { } fn next(&self, level: Level, va: usize) -> Option<&Table> { - let idx = Self::index(level, va); - let entry = self.entries[idx]; + let index = Self::index(level, va); + let entry = self.entries[index]; self.child_table(entry) } - fn next_mut(&mut self, level: Level, va: usize) -> Option<&mut Table> { + // TODO return Result + fn next_mut(&mut self, level: Level, va: usize) -> Result<&mut Table, VmError> { + // Try to get a valid page table entry. If it doesn't exist, create it. let index = Self::index(level, va); let mut entry = self.entries[index]; // println!("next_mut(level:{:?}, va:{:016x}, index:{}): entry:{:?}", level, va, index, entry); @@ -278,9 +290,13 @@ impl Table { write_volatile(&mut self.entries[index], entry); } } + + // TODO Check that the entry is a table + + // Return the address of the next table, as found in the entry. let raw_ptr = entry.virt_page_addr(); let next_table = unsafe { &mut *(raw_ptr as *mut Table) }; - Some(next_table) + Ok(next_table) } } @@ -291,7 +307,7 @@ impl PageTable { PageTable { entries: [Entry::empty(); 512] } } - pub fn map_to(&mut self, entry: Entry, va: usize, page_size: PageSize) -> Result<()> { + pub fn map_to(&mut self, entry: Entry, va: usize, page_size: PageSize) -> Result<(), VmError> { // println!("map_to(entry: {:?}, va: {:#x}, page_size {:?})", entry, va, page_size); let old_entry = match page_size { PageSize::Page4K => self @@ -308,16 +324,14 @@ impl PageTable { } }; - if let Some(old_entry) = old_entry { - let entry = entry.with_valid(true); - // println!("Some {:?}, New {:?}", old_entry, entry); - // println!("{:p}", old_entry); - unsafe { - write_volatile(old_entry, entry); - } - return Ok(()); + let old_entry = old_entry?; + let entry = entry.with_valid(true); + // println!("Some {:?}, New {:?}", old_entry, entry); + // println!("{:p}", old_entry); + unsafe { + write_volatile(old_entry, entry); } - Err("Allocation failed") + return Ok(()); } pub fn map_phys_range( @@ -326,7 +340,7 @@ impl PageTable { end: PhysAddr, entry: Entry, page_size: PageSize, - ) -> Result<()> { + ) -> Result<(), VmError> { for pa in PhysAddr::step_by_rounded(start, end, page_size.size()) { self.map_to(entry.with_phys_addr(pa), pa.to_virt(), page_size)?; }