Files
RedBear-OS/src/page/entry.rs
T
Andrey Turkin a96ea6f5f3 Allow physical address bits be anywhere in PTE entry
Before this commit, RMM assumed base physical address was presented in PTE as is, i.e. physical page address was shifted exactly to PAGE_SHIFT, so physical address can be extracted from PTE by simply masking off some bits and can be placed in PTE by simple addition/OR.

This is not the case for RISC-V which has 4Kb base page so 12 bits PAGE_SHIFT, yet physical page address is only shifted 10 bits in PTE.

This commit removes this assumption.

 NOTE: This commit changes meaning of constants:
 * ENTRY_ADDRESS_SIZE from "total physical size in bytes" to "total physical size in PAGES"
 * ENTRY_ADDRESS_MASK from "mask of physical bits in PTE" to "mask of physical bits starting at bit 0"
2024-09-23 08:47:27 +03:00

60 lines
1.4 KiB
Rust

use core::marker::PhantomData;
use crate::{Arch, PageFlags, PhysicalAddress};
#[derive(Clone, Copy, Debug)]
pub struct PageEntry<A> {
data: usize,
phantom: PhantomData<A>,
}
impl<A: Arch> PageEntry<A> {
#[inline(always)]
pub fn new(address: usize, flags: usize) -> Self {
let data = (((address >> A::PAGE_SHIFT) & A::ENTRY_ADDRESS_MASK) << A::ENTRY_ADDRESS_SHIFT)
| flags;
Self::from_data(data)
}
#[inline(always)]
pub fn from_data(data: usize) -> Self {
Self {
data,
phantom: PhantomData,
}
}
#[inline(always)]
pub fn data(&self) -> usize {
self.data
}
#[inline(always)]
pub fn address(&self) -> Result<PhysicalAddress, PhysicalAddress> {
let addr = PhysicalAddress(
((self.data >> A::ENTRY_ADDRESS_SHIFT) & A::ENTRY_ADDRESS_MASK) << A::PAGE_SHIFT,
);
if self.present() {
Ok(addr)
} else {
Err(addr)
}
}
#[inline(always)]
pub fn flags(&self) -> PageFlags<A> {
unsafe { PageFlags::from_data(self.data & A::ENTRY_FLAGS_MASK) }
}
#[inline(always)]
pub fn set_flags(&mut self, flags: PageFlags<A>) {
self.data &= !A::ENTRY_FLAGS_MASK;
self.data |= flags.data();
}
#[inline(always)]
pub fn present(&self) -> bool {
self.data & A::ENTRY_FLAG_PRESENT != 0
}
}