use core::marker::PhantomData;
use core::ops::Range;
use crate::PageFormat;
use crate::walkers::*;
use num_traits::{FromPrimitive, PrimInt, Unsigned};
pub trait PageTableMapper<PTE, Error>
where
PTE: FromPrimitive + PrimInt + Unsigned,
{
const PTE_NOT_FOUND: Error;
const PAGE_NOT_PRESENT: Error;
const NOT_IMPLEMENTED: Error;
fn read_pte(&self, phys_addr: PTE) -> Result<PTE, Error>;
fn write_pte(&mut self, phys_addr: PTE, value: PTE) -> Result<(), Error>;
fn read_bytes(&self, _bytes: &mut [u8], _phys_addr: PTE) -> Result<usize, Error> {
Err(Self::NOT_IMPLEMENTED)
}
fn write_bytes(&mut self, _phys_addr: PTE, _bytes: &[u8]) -> Result<usize, Error> {
Err(Self::NOT_IMPLEMENTED)
}
fn alloc_page(&mut self) -> Result<PTE, Error> {
Err(Self::NOT_IMPLEMENTED)
}
fn free_page(&mut self, _pte: PTE) {
}
}
pub struct AddressSpace<'a, PTE, Mapper, Error>
where
PTE: FromPrimitive + PrimInt + Unsigned,
Mapper: PageTableMapper<PTE, Error>,
{
format: PageFormat<'a, PTE>,
root: PTE,
mapper: &'a mut Mapper,
error: core::marker::PhantomData<Error>,
}
impl<'a, PTE, Mapper, Error> AddressSpace<'a, PTE, Mapper, Error>
where
PTE: FromPrimitive + PrimInt + Unsigned,
Mapper: PageTableMapper<PTE, Error>,
{
pub fn new(format: PageFormat<'a, PTE>, mapper: &'a mut Mapper, root: PTE) -> Self {
Self {
format,
mapper,
root,
error: PhantomData,
}
}
pub fn read_pte(&self, virt_addr: usize) -> Result<PTE, Error> {
let mut walker = PteReader {
mapper: self.mapper,
pte: None,
error: PhantomData,
};
self.format.walk(self.root, virt_addr..virt_addr + 1, &mut walker)?;
match walker.pte {
Some(pte) => Ok(pte),
_ => Err(Mapper::PTE_NOT_FOUND),
}
}
pub fn write_pte(&mut self, virt_addr: usize, pte: PTE) -> Result<(), Error> {
let mut walker = PteWriter {
mapper: self.mapper,
pte,
error: PhantomData,
};
self.format.walk_mut(self.root, virt_addr..virt_addr + 1, &mut walker)?;
Ok(())
}
pub fn allocate_range(&mut self, range: Range<usize>, mask: PTE) -> Result<(), Error> {
let mut walker = PteAllocator {
mapper: self.mapper,
mask: Some(mask),
format: &self.format,
error: PhantomData,
};
self.format.walk_mut(self.root, range, &mut walker)?;
Ok(())
}
pub fn map_range(&mut self, range: Range<usize>, mask: PTE) -> Result<(), Error> {
let mut walker = PteMapper {
mapper: self.mapper,
mask,
format: &self.format,
error: PhantomData,
};
self.format.walk_mut(self.root, range, &mut walker)?;
Ok(())
}
pub fn protect_range(&mut self, range: Range<usize>, mask: (PTE, PTE)) -> Result<(), Error> {
let mut walker = PteProtector {
mapper: self.mapper,
mask,
format: &self.format,
error: PhantomData,
};
self.format.walk_mut(self.root, range, &mut walker)?;
Ok(())
}
pub fn free_range(&mut self, range: Range<usize>) -> Result<(), Error> {
let flags = PteRemovalFlags::all();
let mut walker = PteRemover {
mapper: self.mapper,
flags,
format: &self.format,
error: PhantomData,
};
self.format.walk_mut(self.root, range, &mut walker)?;
Ok(())
}
pub fn unmap_range(&mut self, range: Range<usize>) -> Result<(), Error> {
let flags = PteRemovalFlags::empty();
let mut walker = PteRemover {
mapper: self.mapper,
flags,
format: &self.format,
error: PhantomData,
};
self.format.walk_mut(self.root, range, &mut walker)?;
Ok(())
}
pub fn copy_from(&mut self, data: &mut [u8], address: usize) -> Result<(), Error> {
let range = address..address + data.len();
let mut walker = CopyFromWalker {
mapper: self.mapper,
offset: 0,
data,
format: &self.format,
error: PhantomData,
};
self.format.walk(self.root, range, &mut walker)?;
Ok(())
}
pub fn copy_to(&mut self, address: usize, data: &[u8]) -> Result<(), Error> {
let range = address..address + data.len();
let mut walker = CopyToWalker {
mapper: self.mapper,
offset: 0,
data,
format: &self.format,
error: PhantomData,
};
self.format.walk(self.root, range, &mut walker)?;
Ok(())
}
}