page_table_generic/
lib.rs#![no_std]
use core::{alloc::Layout, fmt::Debug, ptr::NonNull};
pub mod err;
mod iter;
mod page_table_entry;
mod table;
pub use table::PageTableRef;
bitflags::bitflags! {
#[derive(Clone, Copy, PartialEq)]
pub struct AccessSetting: u32 {
const PrivilegeRead = 1;
const PrivilegeWrite = 1 << 2;
const PrivilegeExecute = 1 << 3;
const UserRead = 1 << 4;
const UserWrite = 1 << 5;
const UserExecute = 1 << 6;
}
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CacheSetting {
Normal,
Device,
NonCache,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct MapConfig {
pub vaddr: *const u8,
pub paddr: usize,
pub setting: PTESetting,
}
impl MapConfig {
pub fn new(
vaddr: *const u8,
paddr: usize,
access_setting: AccessSetting,
cache_setting: CacheSetting,
) -> Self {
Self {
vaddr,
paddr,
setting: PTESetting {
access_setting,
cache_setting,
},
}
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct PTESetting {
pub access_setting: AccessSetting,
pub cache_setting: CacheSetting,
}
#[repr(C)]
#[derive(Clone)]
pub struct PTEGeneric {
pub paddr: usize,
pub is_block: bool,
pub is_valid: bool,
pub setting: PTESetting,
}
impl PTEGeneric {
pub(crate) fn new(paddr: usize, is_block: bool, setting: PTESetting) -> Self {
Self {
paddr,
is_valid: true,
is_block,
setting,
}
}
pub fn valid(&self) -> bool {
self.is_valid
}
}
impl Debug for PTEGeneric {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"PTE PA:{:#p} Block: {} {:?}",
self.paddr as *const u8, self.is_block, self.setting
)
}
}
pub trait PTEArch: Sync + Send + Clone + Copy + 'static {
fn page_size() -> usize;
fn level() -> usize;
fn new_pte(config: PTEGeneric) -> usize;
fn read_pte(pte: usize) -> PTEGeneric;
}
pub trait Access {
fn va_offset(&self) -> usize;
unsafe fn alloc(&mut self, layout: Layout) -> Option<NonNull<u8>>;
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);
}
pub struct PTEInfo {
pub level: usize,
pub vaddr: *const u8,
pub pte: PTEGeneric,
}
impl Debug for PTESetting {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
macro_rules! field {
($e:ident,$name:expr) => {
if self.access_setting.contains(AccessSetting::$e) {
f.write_str($name)?
} else {
f.write_str("-")?
}
};
}
f.write_str("P-")?;
field!(PrivilegeRead, "R");
field!(PrivilegeWrite, "W");
field!(PrivilegeExecute, "X");
f.write_str(", U-")?;
field!(UserRead, "R");
field!(UserWrite, "W");
field!(UserExecute, "X");
f.write_str(", ")?;
f.write_fmt(format_args!("{:?}", self.cache_setting))?;
f.write_str(")")
}
}