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 PageAttribute: u32 {
const Read = 1;
const Write = 1 << 2;
const PrivilegeExecute = 1 << 3;
const UserExcute = 1 << 4;
const UserAccess = 1 << 5;
const Device = 1 << 6;
const NonCache = 1 << 7;
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct MapConfig {
pub vaddr: *const u8,
pub paddr: usize,
pub attrs: PageAttribute,
}
#[repr(C)]
#[derive(Clone)]
pub struct PTEConfig {
pub paddr: usize,
pub is_block: bool,
pub attributes: PageAttribute,
}
impl PTEConfig {
pub(crate) fn new(paddr: usize, is_block: bool, attrs: PageAttribute) -> Self {
Self {
paddr,
is_block,
attributes: attrs,
}
}
pub fn valid(&self) -> bool {
self.attributes.contains(PageAttribute::Read)
}
}
impl Debug for PTEConfig {
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.attributes
)
}
}
pub trait PTEArch: Sync + Send + Clone + Copy + 'static {
fn page_size() -> usize;
fn level() -> usize;
fn new_pte(config: PTEConfig) -> usize;
fn read_pte(pte: usize) -> PTEConfig;
}
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: PTEConfig,
}
impl Debug for PageAttribute {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
macro_rules! field {
($e:ident,$name:expr) => {
if self.contains(PageAttribute::$e) {
f.write_str($name)?
} else {
f.write_str("-")?
}
};
}
f.write_str("P-")?;
field!(Read, "R");
field!(Write, "W");
field!(PrivilegeExecute, "X");
f.write_str(", U-")?;
if self.contains(PageAttribute::UserAccess) {
field!(Read, "R");
field!(Write, "W");
} else {
f.write_str("--")?;
}
field!(UserExcute, "X");
f.write_str(", ")?;
f.write_str(if self.contains(PageAttribute::NonCache) {
"NonCache"
} else if self.contains(PageAttribute::Device) {
"Device"
} else {
"Cache"
})?;
f.write_str(")")
}
}