86 lines
2.9 KiB
Rust
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;
|
|
}
|