2023-06-24 17:18:31 -05:00
|
|
|
//! Page table and associated structures implementation
|
|
|
|
|
2023-07-20 13:47:50 -05:00
|
|
|
use core::{fmt::Debug, mem::MaybeUninit};
|
2023-06-20 19:07:48 -05:00
|
|
|
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Page entry permission
|
2023-06-20 19:07:48 -05:00
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
|
|
|
#[repr(u8)]
|
|
|
|
pub enum Permission {
|
2023-06-24 17:16:14 -05:00
|
|
|
/// No page present
|
2023-06-20 19:07:48 -05:00
|
|
|
#[default]
|
|
|
|
Empty,
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Points to another pagetable
|
2023-06-20 19:07:48 -05:00
|
|
|
Node,
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Page is read only
|
2023-06-20 19:07:48 -05:00
|
|
|
Readonly,
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Page is readable and writable
|
2023-06-20 19:07:48 -05:00
|
|
|
Write,
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Page is readable and executable
|
2023-06-20 19:07:48 -05:00
|
|
|
Exec,
|
|
|
|
}
|
|
|
|
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Page table entry
|
2023-06-20 19:07:48 -05:00
|
|
|
#[derive(Clone, Copy, Default, PartialEq, Eq)]
|
|
|
|
pub struct PtEntry(u64);
|
|
|
|
impl PtEntry {
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Create new
|
2023-07-11 03:33:25 -05:00
|
|
|
///
|
2023-06-24 17:21:40 -05:00
|
|
|
/// # Safety
|
|
|
|
/// - `ptr` has to point to valid data and shall not be deallocated
|
|
|
|
/// troughout the entry lifetime
|
2023-06-20 19:07:48 -05:00
|
|
|
#[inline]
|
|
|
|
pub unsafe fn new(ptr: *mut PtPointedData, permission: Permission) -> Self {
|
|
|
|
Self(ptr as u64 | permission as u64)
|
|
|
|
}
|
|
|
|
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Get permission
|
2023-06-20 19:07:48 -05:00
|
|
|
#[inline]
|
|
|
|
pub fn permission(&self) -> Permission {
|
|
|
|
unsafe { core::mem::transmute(self.0 as u8 & 0b111) }
|
|
|
|
}
|
|
|
|
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Get pointer to the data (leaf) or next page table (node)
|
2023-06-20 19:07:48 -05:00
|
|
|
#[inline]
|
|
|
|
pub fn ptr(&self) -> *mut PtPointedData {
|
|
|
|
(self.0 & !((1 << 12) - 1)) as _
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Debug for PtEntry {
|
|
|
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
|
|
f.debug_struct("PtEntry")
|
|
|
|
.field("ptr", &self.ptr())
|
|
|
|
.field("permission", &self.permission())
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Page table
|
2023-06-20 19:07:48 -05:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
|
|
#[repr(align(4096))]
|
2023-07-20 13:47:50 -05:00
|
|
|
pub struct PageTable {
|
|
|
|
pub childen: u8,
|
|
|
|
pub table: [PtEntry; 256],
|
2023-06-20 19:07:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for PageTable {
|
|
|
|
fn default() -> Self {
|
2023-06-24 17:16:14 -05:00
|
|
|
// SAFETY: It's fine, zeroed page table entry is valid (= empty)
|
2023-07-20 13:47:50 -05:00
|
|
|
Self {
|
|
|
|
childen: 0,
|
|
|
|
table: unsafe { MaybeUninit::zeroed().assume_init() },
|
|
|
|
}
|
2023-06-20 19:07:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Data page table entry can possibly point to
|
2023-06-20 19:07:48 -05:00
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
#[repr(C, align(4096))]
|
|
|
|
pub union PtPointedData {
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Node - next page table
|
2023-07-11 03:33:25 -05:00
|
|
|
pub pt: PageTable,
|
2023-06-24 17:16:14 -05:00
|
|
|
/// Leaf
|
2023-06-20 19:07:48 -05:00
|
|
|
pub page: u8,
|
|
|
|
}
|