i686: free translation tables

This commit is contained in:
Mark Poliakov 2024-10-11 18:35:26 +03:00
parent c907fe032a
commit ce8ccf4af9
4 changed files with 78 additions and 9 deletions

View File

@ -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.

View File

@ -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<TA: TableAllocator> ProcessAddressSpaceManager<TA> for ProcessAddressSpaceI
}
unsafe fn clear(&mut self) {
// TODO
// self.l0
// .drop_range::<TA>(0..((Self::UPPER_LIMIT_PFN * L3::SIZE).page_index::<L0>()));
self.l0.drop_range::<TA>(0..KERNEL_SPLIT_L0);
}
fn translate(&self, address: usize) -> Result<(PhysicalAddress, MapAttributes), Error> {
@ -123,3 +123,15 @@ impl<TA: TableAllocator> ProcessAddressSpaceImpl<TA> {
Some((page, l3[l3i].attributes().into()))
}
}
impl<TA: TableAllocator> Drop for ProcessAddressSpaceImpl<TA> {
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);
}
}
}

View File

@ -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<L: EntryLevel> PageTable<L> {
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<TA: TableAllocator>(this: PhysicalRefMut<Self, KernelTableManagerImpl>) {
let physical = this.as_physical_address();
TA::free_page_table(physical);
}
}
impl NextPageTable for PageTable<L0> {
@ -184,6 +197,39 @@ impl<L: EntryLevel> IndexMut<usize> for PageTable<L> {
}
}
impl EntryLevelDrop for PageTable<L3> {
const FULL_RANGE: Range<usize> = 0..1024;
unsafe fn drop_range<TA: TableAllocator>(&mut self, _range: Range<usize>) {}
}
impl EntryLevelDrop for PageTable<L0> {
const FULL_RANGE: Range<usize> = 0..1024;
unsafe fn drop_range<TA: TableAllocator>(&mut self, range: Range<usize>) {
for index in range {
let entry = self[index];
if let Some(table) = entry.as_table() {
let mut table_ref: PhysicalRefMut<PageTable<L3>, KernelTableManagerImpl> =
PhysicalRefMut::map(table);
table_ref.drop_all::<TA>();
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<MapAttributes> for PageAttributes {
fn from(value: MapAttributes) -> Self {
let mut res = PageAttributes::WRITABLE;

View File

@ -66,14 +66,15 @@ pub fn load_kernel_symbol_table<P: AsRef<Path>>(
let mut map = DefaultHashTable::new();
loop {
let mut len = [0; size_of::<usize>()];
let mut len = [0; size_of::<u32>()];
let mut value = [0; size_of::<u64>()];
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::<u64>()];
symbol_file.read_exact(&mut value)?;
let value = u64::from_le_bytes(value).try_into().unwrap();
map.insert(name.into(), value);