70 lines
2.2 KiB
Rust
70 lines
2.2 KiB
Rust
//! Virtual memory table interface
|
|
use core::ops::{Deref, DerefMut};
|
|
|
|
use abi::error::Error;
|
|
use bitflags::bitflags;
|
|
|
|
// TODO EXECUTABLE
|
|
bitflags! {
|
|
/// Describes how a page translation mapping should behave
|
|
#[derive(Clone, Copy)]
|
|
pub struct MapAttributes: u64 {
|
|
/// The data mapped can be read by the user process
|
|
const USER_READ = 1 << 0;
|
|
/// The data mapped can be written to by the user process
|
|
const USER_WRITE = 1 << 1;
|
|
/// The mapping is not global across the address spaces
|
|
const NON_GLOBAL = 1 << 2;
|
|
}
|
|
}
|
|
|
|
/// Interface for non-terminal tables to retrieve the next level of address translation tables
|
|
pub trait NextPageTable {
|
|
/// Type for the next-level page table
|
|
type NextLevel;
|
|
type TableRef: Deref<Target = Self::NextLevel>;
|
|
type TableRefMut: DerefMut<Target = Self::NextLevel>;
|
|
|
|
/// Tries looking up a next-level table at given index, allocating and mapping one if it is not
|
|
/// present there
|
|
fn get_mut_or_alloc(&mut self, index: usize) -> Result<Self::TableRefMut, Error>;
|
|
/// Returns a mutable reference to a next-level table at `index`, if present
|
|
fn get_mut(&mut self, index: usize) -> Option<Self::TableRefMut>;
|
|
|
|
fn get(&self, index: usize) -> Option<Self::TableRef>;
|
|
}
|
|
|
|
/// Interface for a single level of address translation
|
|
#[const_trait]
|
|
pub trait EntryLevel: Copy {
|
|
const SHIFT: usize;
|
|
const SIZE: usize = 1 << Self::SHIFT;
|
|
|
|
/// Returns the index into a page table for a given address
|
|
#[inline]
|
|
fn index(addr: usize) -> usize {
|
|
(addr >> Self::SHIFT) & 0x1FF
|
|
}
|
|
/// Returns the offset of an address from the page start at current level
|
|
#[inline]
|
|
fn page_offset(addr: usize) -> usize {
|
|
addr & (Self::SIZE - 1)
|
|
}
|
|
|
|
#[inline]
|
|
fn align_up(addr: usize) -> usize {
|
|
(addr + Self::SIZE - 1) & !(Self::SIZE - 1)
|
|
}
|
|
|
|
#[inline]
|
|
fn page_count(addr: usize) -> usize {
|
|
(addr + Self::SIZE - 1) / Self::SIZE
|
|
}
|
|
}
|
|
|
|
/// Tag trait to mark that the page table level may point to a next-level table
|
|
pub trait NonTerminalEntryLevel: EntryLevel {
|
|
/// Tag type of the level this entry level may point to
|
|
type NextLevel: EntryLevel;
|
|
}
|