use core::marker::PhantomData;
use core::ops::Range;
use crate::address_space::PageTableMapper;
use crate::{PageFormat, PteType};
use num_traits::{FromPrimitive, PrimInt, Unsigned};
pub struct PteProtector<'a, PTE, Mapper, Error>
where
PTE: FromPrimitive + PrimInt + Unsigned,
Mapper: PageTableMapper<PTE, Error>,
{
pub mapper: &'a mut Mapper,
pub mask: (PTE, PTE),
pub format: &'a PageFormat<'a, PTE>,
pub error: PhantomData<Error>,
}
impl<'a, PTE, Mapper, Error> crate::PageWalkerMut<PTE, Error> for PteProtector<'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(&mut self, pte_type: PteType, _range: Range<usize>, pte: &mut PTE) -> Result<(), Error> {
let physical_mask = self.format.physical_mask;
if let PteType::Page(level) = pte_type {
let level = &self.format.levels[level];
if level.is_present(*pte) {
let clear_mask = self.mask.0 &
!(physical_mask | level.huge_page_bit.0 | level.present_bit.0);
let set_mask = self.mask.1 &
!(physical_mask | level.huge_page_bit.0 | level.present_bit.0);
*pte = (*pte & !clear_mask) | set_mask;
}
}
Ok(())
}
}