When inserting a new memory region into a MemorySet, the mapping procedure may fail after partially mapping the region if the physical frame allocator runs out of free frames.
The current workflow is:
/// Add a memory region to this set.
pub fn insert(&mut self, region: MemoryRegion<PT::VA>) -> HvResult {
...
self.pt.map(®ion)?;
self.regions.insert(region.start, region);
Ok(())
}
During map():
fn map(&mut self, region: &MemoryRegion<VA>) -> HvResult {
...
while size > 0 {
...
self.inner
.map_page(page, paddr, region.flags)
.map_err(|e: PagingError| {
error!(
"failed to map page: {:#x?}({:?}) -> {:#x?}, {:?}",
vaddr, page_size, paddr, e
);
e
})?;
...
}
Ok(())
}
If the allocator cannot provide enough frames during page table creation (e.g., intermediate page tables), map_page() returns an error and the mapping process aborts.
Problem
This leads to an inconsistent state:
- Some virtual pages in the region are mapped
- Others remain unmapped
- The region is not inserted into
self.regions
- Page table state and memory region metadata become inconsistent