use memory_addr::{PageIter4K, PhysAddr};
use page_table_multiarch::{MappingFlags, PageSize, PagingHandler};
use super::Backend;
use crate::{GuestPhysAddr, npt::NestedPageTable as PageTable};
impl<H: PagingHandler> Backend<H> {
pub const fn new_alloc(populate: bool) -> Self {
Self::Alloc {
populate,
_phantom: core::marker::PhantomData,
}
}
pub(crate) fn map_alloc(
&self,
start: GuestPhysAddr,
size: usize,
flags: MappingFlags,
pt: &mut PageTable<H>,
populate: bool,
) -> bool {
debug!(
"map_alloc: [{:#x}, {:#x}) {:?} (populate={})",
start,
start + size,
flags,
populate
);
if populate {
for addr in PageIter4K::new(start, start + size).unwrap() {
if H::alloc_frame()
.and_then(|frame| pt.map(addr, frame, PageSize::Size4K, flags).ok())
.is_none()
{
return false;
}
}
true
} else {
pt.map_region(
start,
|_va| PhysAddr::from(0),
size,
MappingFlags::empty(),
false,
)
.is_ok()
}
}
pub(crate) fn unmap_alloc(
&self,
start: GuestPhysAddr,
size: usize,
pt: &mut PageTable<H>,
_populate: bool,
) -> bool {
debug!("unmap_alloc: [{:#x}, {:#x})", start, start + size);
for addr in PageIter4K::new(start, start + size).unwrap() {
if let Ok((frame, _, page_size)) = pt.unmap(addr) {
if page_size.is_huge() {
return false;
}
H::dealloc_frame(frame);
} else {
}
}
true
}
pub(crate) fn handle_page_fault_alloc(
&self,
vaddr: GuestPhysAddr,
orig_flags: MappingFlags,
pt: &mut PageTable<H>,
populate: bool,
) -> bool {
if populate {
false } else {
let Some(frame) = H::alloc_frame() else {
return false;
};
pt.remap(vaddr, frame, orig_flags)
}
}
}