diff --git a/kernel/arch/i686/src/mem/mod.rs b/kernel/arch/i686/src/mem/mod.rs index 512518dc..fe72f1d3 100644 --- a/kernel/arch/i686/src/mem/mod.rs +++ b/kernel/arch/i686/src/mem/mod.rs @@ -64,6 +64,16 @@ impl KernelTableManager for KernelTableManagerImpl { .expect("Invalid virtual address") .into_u64() } + + unsafe fn unmap_physical_address(virt: usize) { + if virt < KERNEL_VIRT_OFFSET { + panic!("Invalid 'virtualized' address: {:#x}", virt); + } + let virt = virt - KERNEL_VIRT_OFFSET; + if virt >= fixed::FIXED_MAP_COUNT << L0::SHIFT { + todo!() + } + } } /// Sets up fixed MMU translation tables. diff --git a/kernel/arch/i686/src/mem/process.rs b/kernel/arch/i686/src/mem/process.rs index 9a7f906b..101d93d8 100644 --- a/kernel/arch/i686/src/mem/process.rs +++ b/kernel/arch/i686/src/mem/process.rs @@ -5,14 +5,16 @@ use libk_mm_interface::{ address::{AsPhysicalAddress, PhysicalAddress}, pointer::PhysicalRefMut, process::ProcessAddressSpaceManager, - table::{EntryLevel, EntryLevelExt, MapAttributes, NextPageTable, TableAllocator}, + table::{ + EntryLevel, EntryLevelDrop, EntryLevelExt, MapAttributes, NextPageTable, TableAllocator, + }, }; use yggdrasil_abi::error::Error; use crate::{mem::flush_tlb_entry, KernelTableManagerImpl}; use super::{ - fixed::clone_kernel_tables, + fixed::{clone_kernel_tables, KERNEL_SPLIT_L0}, table::{PageEntry, PageTable, L0, L3}, }; @@ -46,9 +48,7 @@ impl ProcessAddressSpaceManager for ProcessAddressSpaceI } unsafe fn clear(&mut self) { - // TODO - // self.l0 - // .drop_range::(0..((Self::UPPER_LIMIT_PFN * L3::SIZE).page_index::())); + self.l0.drop_range::(0..KERNEL_SPLIT_L0); } fn translate(&self, address: usize) -> Result<(PhysicalAddress, MapAttributes), Error> { @@ -123,3 +123,15 @@ impl ProcessAddressSpaceImpl { Some((page, l3[l3i].attributes().into())) } } + +impl Drop for ProcessAddressSpaceImpl { + fn drop(&mut self) { + // SAFETY: with safe usage of the ProcessAddressSpaceImpl, clearing and dropping + // is safe, no one refers to the memory + unsafe { + self.clear(); + let l0_phys = self.l0.as_physical_address(); + TA::free_page_table(l0_phys); + } + } +} diff --git a/kernel/arch/i686/src/mem/table.rs b/kernel/arch/i686/src/mem/table.rs index 31e30496..f831b044 100644 --- a/kernel/arch/i686/src/mem/table.rs +++ b/kernel/arch/i686/src/mem/table.rs @@ -1,13 +1,16 @@ use core::{ marker::PhantomData, - ops::{Index, IndexMut}, + ops::{Index, IndexMut, Range}, }; use bitflags::bitflags; use libk_mm_interface::{ address::{AsPhysicalAddress, PhysicalAddress}, pointer::{PhysicalRef, PhysicalRefMut}, - table::{EntryLevel, MapAttributes, NextPageTable, NonTerminalEntryLevel, TableAllocator}, + table::{ + EntryLevel, EntryLevelDrop, MapAttributes, NextPageTable, NonTerminalEntryLevel, + TableAllocator, + }, }; use yggdrasil_abi::error::Error; @@ -132,6 +135,16 @@ impl PageTable { Ok(table) } + + /// Recursively clears and deallocates the translation table. + /// + /// # Safety + /// + /// The caller must ensure the table is no longer in use and is not referenced anymore. + pub unsafe fn free(this: PhysicalRefMut) { + let physical = this.as_physical_address(); + TA::free_page_table(physical); + } } impl NextPageTable for PageTable { @@ -184,6 +197,39 @@ impl IndexMut for PageTable { } } +impl EntryLevelDrop for PageTable { + const FULL_RANGE: Range = 0..1024; + + unsafe fn drop_range(&mut self, _range: Range) {} +} + +impl EntryLevelDrop for PageTable { + const FULL_RANGE: Range = 0..1024; + + unsafe fn drop_range(&mut self, range: Range) { + for index in range { + let entry = self[index]; + + if let Some(table) = entry.as_table() { + let mut table_ref: PhysicalRefMut, KernelTableManagerImpl> = + PhysicalRefMut::map(table); + + table_ref.drop_all::(); + + TA::free_page_table(table); + } else if entry.is_present() { + // Memory must've been cleared beforehand, so no non-table entries must be present + panic!( + "Expected a table containing only tables, got table[{}] = {:#x?}", + index, entry.0 + ); + } + + self[index] = PageEntry::INVALID; + } + } +} + impl From for PageAttributes { fn from(value: MapAttributes) -> Self { let mut res = PageAttributes::WRITABLE; diff --git a/kernel/libk/src/module.rs b/kernel/libk/src/module.rs index 52d58549..c5501a2f 100644 --- a/kernel/libk/src/module.rs +++ b/kernel/libk/src/module.rs @@ -66,14 +66,15 @@ pub fn load_kernel_symbol_table>( let mut map = DefaultHashTable::new(); loop { - let mut len = [0; size_of::()]; + let mut len = [0; size_of::()]; + let mut value = [0; size_of::()]; + if symbol_file.read(&mut len)? != len.len() { break; } let len = u32::from_le_bytes(len) as usize; symbol_file.read_exact(&mut string_buffer[..len])?; let name = core::str::from_utf8(&string_buffer[..len]).unwrap(); - let mut value = [0; size_of::()]; symbol_file.read_exact(&mut value)?; let value = u64::from_le_bytes(value).try_into().unwrap(); map.insert(name.into(), value);