yggdrasil/src/mem/table.rs

86 lines
2.9 KiB
Rust

//! Virtual memory table interface
use core::ops::{Deref, DerefMut};
use abi::error::Error;
use bitflags::bitflags;
use cfg_if::cfg_if;
use super::PhysicalAddress;
cfg_if! {
if #[cfg(target_arch = "aarch64")] {
pub use crate::arch::aarch64::table::{AddressSpace, PageAttributes, PageEntry, PageTable};
} else if #[cfg(target_arch = "x86_64")] {
pub use crate::arch::x86_64::mem::table::{AddressSpace, PageEntry, PageTable};
}
}
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 virtual memory address space management
pub trait VirtualMemoryManager {
/// Allocates a region of virtual memory inside the address space and maps it to physical
/// memory pages with given attributes
fn allocate(
&self,
hint: Option<usize>,
len: usize,
attrs: MapAttributes,
) -> Result<usize, Error>;
/// Insert a single 4KiB-page translation mapping into the table
fn map_page(
&self,
virt: usize,
phys: PhysicalAddress,
attrs: MapAttributes,
) -> Result<(), Error>;
/// Releases the virtual memory region from the address space and the pages it refers to
fn deallocate(&self, addr: usize, len: usize) -> Result<(), Error>;
}
/// 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 SIZE: usize;
/// Returns the index into a page table for a given address
fn index(addr: usize) -> usize;
/// Returns the offset of an address from the page start at current level
fn page_offset(addr: usize) -> usize;
}
/// 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;
}