maint: sync up other architectures with mmap(file)

This commit is contained in:
2025-02-26 16:21:56 +02:00
parent 43acdb9e13
commit 72633eb339
43 changed files with 522 additions and 262 deletions
+45 -5
View File
@@ -6,7 +6,7 @@ use core::{
use libk_mm_interface::{
address::{AsPhysicalAddress, PhysicalAddress},
pointer::PhysicalRefMut,
process::ProcessAddressSpaceManager,
process::{PageAttributeUpdate, ProcessAddressSpaceManager},
table::{
EntryLevel, EntryLevelDrop, EntryLevelExt, MapAttributes, NextPageTable, TableAllocator,
},
@@ -70,7 +70,15 @@ impl<TA: TableAllocator> ProcessAddressSpaceManager<TA> for ProcessAddressSpaceI
Ok(())
}
unsafe fn unmap_page(&mut self, address: usize) -> Result<PhysicalAddress, Error> {
unsafe fn update_page_attributes(
&mut self,
address: usize,
update: &PageAttributeUpdate,
) -> Result<(), Error> {
self.update_l3_entry(address, |entry| entry.update(update))
}
unsafe fn unmap_page(&mut self, address: usize) -> Result<(PhysicalAddress, bool), Error> {
self.pop_l3_entry(address)
}
@@ -118,7 +126,11 @@ impl<TA: TableAllocator> ProcessAddressSpaceImpl<TA> {
Ok(())
}
fn pop_l3_entry(&mut self, virt: usize) -> Result<PhysicalAddress, Error> {
fn update_l3_entry<F: FnOnce(&mut PageEntry<L3>) -> Result<(), Error>>(
&mut self,
virt: usize,
mapper: F,
) -> Result<(), Error> {
let l1i = virt.page_index::<L1>();
let l2i = virt.page_index::<L2>();
let l3i = virt.page_index::<L3>();
@@ -127,12 +139,33 @@ impl<TA: TableAllocator> ProcessAddressSpaceImpl<TA> {
let mut l2 = self.l1.get_mut(l1i).ok_or(Error::DoesNotExist)?;
let mut l3 = l2.get_mut(l2i).ok_or(Error::DoesNotExist)?;
let page = l3[l3i].as_page().ok_or(Error::DoesNotExist)?;
let entry = &mut l3[l3i];
if !entry.is_present() {
return Err(Error::DoesNotExist);
}
mapper(entry)?;
super::tlb_flush_va_asid(virt, self.asid as usize);
Ok(())
}
fn pop_l3_entry(&mut self, virt: usize) -> Result<(PhysicalAddress, bool), Error> {
let l1i = virt.page_index::<L1>();
let l2i = virt.page_index::<L2>();
let l3i = virt.page_index::<L3>();
// TODO somehow drop tables if they're known to be empty?
let mut l2 = self.l1.get_mut(l1i).ok_or(Error::DoesNotExist)?;
let mut l3 = l2.get_mut(l2i).ok_or(Error::DoesNotExist)?;
let entry = l3[l3i];
let page = entry.as_page().ok_or(Error::DoesNotExist)?;
let dirty = entry.is_dirty();
l3[l3i] = PageEntry::INVALID;
super::tlb_flush_va_asid(virt, self.asid as usize);
Ok(page)
Ok((page, dirty))
}
fn read_l3_entry(&self, virt: usize) -> Option<(PhysicalAddress, MapAttributes)> {
@@ -178,6 +211,9 @@ fn to_page_attributes(src: MapAttributes) -> PageAttributes {
if src.intersects(MapAttributes::USER_READ | MapAttributes::USER_WRITE) {
result |= PageAttributes::U;
}
if src.contains(MapAttributes::DIRTY) {
result |= PageAttributes::SW_DIRTY;
}
result
}
@@ -192,5 +228,9 @@ fn to_map_attributes(src: PageAttributes) -> MapAttributes {
}
}
if src.contains(PageAttributes::SW_DIRTY) {
result |= MapAttributes::DIRTY;
}
result
}
+22 -2
View File
@@ -6,6 +6,7 @@ use core::{
use libk_mm_interface::{
address::{AsPhysicalAddress, PhysicalAddress},
pointer::{PhysicalRef, PhysicalRefMut},
process::PageAttributeUpdate,
table::{
page_index, EntryLevel, EntryLevelDrop, NextPageTable, NonTerminalEntryLevel,
TableAllocator,
@@ -88,6 +89,8 @@ impl<L: EntryLevel> PageTable<L> {
}
impl<L: EntryLevel> PageEntry<L> {
// Upper + lower 10 bits
const ATTR_MASK: u64 = 0xFFC00000000003FF;
pub const INVALID: Self = Self(0, PhantomData);
/// Constructs a [PageEntry] from its raw representation.
@@ -103,6 +106,23 @@ impl<L: EntryLevel> PageEntry<L> {
self.0 & PageAttributes::V.bits() != 0
}
pub fn update(&mut self, update: &PageAttributeUpdate) -> Result<(), Error> {
let mut attrs = self.attributes();
if let Some(write) = update.user_write {
attrs.set(PageAttributes::W, write);
}
if let Some(dirty) = update.dirty {
attrs.set(PageAttributes::SW_DIRTY, dirty);
}
self.0 &= !Self::ATTR_MASK;
self.0 |= attrs.bits() & Self::ATTR_MASK;
Ok(())
}
pub const fn is_dirty(&self) -> bool {
self.0 & PageAttributes::SW_DIRTY.bits() != 0
}
pub fn attributes(self) -> PageAttributes {
PageAttributes::from_bits_retain(self.0)
}
@@ -211,7 +231,7 @@ impl<L: NonTerminalEntryLevel> PageEntry<L> {
& (PageAttributes::R | PageAttributes::W | PageAttributes::X | PageAttributes::V)
.bits()
== PageAttributes::V.bits())
.then_some((self.0 << 2) & !0xFFF)
.then_some((self.0 & !Self::ATTR_MASK) << 2)
.map(PhysicalAddress::from_u64)
}
}
@@ -232,7 +252,7 @@ impl PageEntry<L3> {
pub fn as_page(&self) -> Option<PhysicalAddress> {
(self.0 & PageAttributes::V.bits() != 0)
.then_some((self.0 << 2) & !0xFFF)
.then_some((self.0 & !Self::ATTR_MASK) << 2)
.map(PhysicalAddress::from_u64)
}
}