use core::marker::PhantomData;
use core::ops::Range;
use crate::address_space::PageTableMapper;
use crate::PageFormat;
use num_traits::{FromPrimitive, PrimInt, Unsigned};
pub struct PteMapper<'a, PTE, Mapper, Error>
where
PTE: FromPrimitive + PrimInt + Unsigned,
Mapper: PageTableMapper<PTE, Error>,
{
pub mapper: &'a mut Mapper,
pub format: &'a PageFormat<'a, PTE>,
pub mask: PTE,
pub error: PhantomData<Error>,
}
impl<'a, PTE, Mapper, Error> crate::PageWalkerMut<PTE, Error> for PteMapper<'a, PTE, Mapper, Error>
where
PTE: FromPrimitive + PrimInt + Unsigned,
Mapper: PageTableMapper<PTE, Error>,
{
fn read_pte(&self, phys_addr: PTE) -> Result<PTE, Error> {
self.mapper.read_pte(phys_addr)
}
fn write_pte(&mut self, phys_addr: PTE, value: PTE) -> Result<(), Error> {
self.mapper.write_pte(phys_addr, value)
}
fn handle_pte_hole(&mut self, index: usize, _range: Range<usize>, pte: &mut PTE) -> Result<(), Error> {
let level = &self.format.levels[index];
match index {
0 => {
*pte = level.present_bit.1 | self.mask;
self.mask = self.mask + PTE::from(level.page_size()).unwrap_or(PTE::zero());
}
_ => {
let page_table = self.mapper.alloc_page()?;
*pte = page_table | level.present_bit.1 | level.page_table_mask |
level.huge_page_bit.0 ^ level.huge_page_bit.1;
}
}
Ok(())
}
}