diff --git a/drivers/src/iommu/mod.rs b/drivers/src/iommu/mod.rs index f22b92d0..2b2a52c0 100644 --- a/drivers/src/iommu/mod.rs +++ b/drivers/src/iommu/mod.rs @@ -89,7 +89,7 @@ mod tests { .unwrap() .build() }; - let hyp_mem = HypPageAlloc::new(&mut hw_map); + let hyp_mem = HypPageAlloc::new(&mut hw_map).unwrap(); let (page_tracker, host_pages) = PageTracker::from(hyp_mem, PageSize::Size4k as u64); // Leak the backing ram so it doesn't get freed std::mem::forget(backing_mem); diff --git a/page-tracking/src/page_info.rs b/page-tracking/src/page_info.rs index ed165583..74b968ab 100644 --- a/page-tracking/src/page_info.rs +++ b/page-tracking/src/page_info.rs @@ -523,7 +523,7 @@ pub struct PageMap { impl PageMap { /// Builds a new `PageMap` from a populated `HwMemMap`. It will track ownership information /// for each page in the system. - pub fn build_from(mem_map: &mut HwMemMap) -> Self { + pub fn build_from(mem_map: &mut HwMemMap) -> PageTrackingResult { // Determine how many pages we'll need for the page map. let total_pages = mem_map .regions() @@ -536,7 +536,8 @@ impl PageMap { let page_map_region = mem_map .regions() .find(|r| r.region_type() == HwMemRegionType::Available && r.size() >= page_map_size) - .expect("No free space for PageMap"); + .ok_or(PageTrackingError::PageMapNoSpace)?; + let page_map_base = page_map_region.base(); // Safe to create pages from this memory as `HwMemMap` guarantees that this range is @@ -554,11 +555,10 @@ impl PageMap { RawAddr::from(page_map_base), page_map_size, ) - .expect("Failed to reserve page map"); - + .map_err(PageTrackingError::PageMapReserveRegion)?; let mut page_map = Self::new(struct_pages); page_map.populate_from(mem_map); - page_map + Ok(page_map) } /// Constructs an empty `PageMap` from an existing vector of `PageInfo` structs. diff --git a/page-tracking/src/page_tracker.rs b/page-tracking/src/page_tracker.rs index 29e1a7b0..7e154ef2 100644 --- a/page-tracking/src/page_tracker.rs +++ b/page-tracking/src/page_tracker.rs @@ -7,7 +7,7 @@ use sync::Mutex; use crate::collections::{RawPageVec, StaticPageRef}; use crate::page_info::{PageInfo, PageMap, PageState}; -use crate::{HwMemMap, PageList, TlbVersion}; +use crate::{hw_mem_map, HwMemMap, PageList, TlbVersion}; /// Errors related to managing physical page information. #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -63,6 +63,10 @@ pub enum Error { PageNotBlockable, /// Attempt to unblock, promote, demote or remove a page that is not blocked. PageNotBlocked, + /// Failed to reserve region for page map + PageMapReserveRegion(hw_mem_map::Error), + /// No memory available for page map + PageMapNoSpace, } /// Holds the result of page tracking operations. @@ -163,7 +167,7 @@ impl PageTracker { .unwrap() .build() }; - let hyp_mem = HypPageAlloc::new(&mut hw_map); + let hyp_mem = HypPageAlloc::new(&mut hw_map).unwrap(); let (page_tracker, host_pages) = PageTracker::from(hyp_mem, PageSize::Size4k as u64); // Leak the backing ram so it doesn't get freed std::mem::forget(backing_mem); @@ -655,14 +659,14 @@ pub struct HypPageAlloc { impl HypPageAlloc { /// Creates a new `HypPageAlloc`. The memory map passed in contains information about what /// physical memory can be used by the machine. - pub fn new(mem_map: &mut HwMemMap) -> Self { + pub fn new(mem_map: &mut HwMemMap) -> Result { let first_page = mem_map.regions().next().unwrap().base(); let mut hyp_pages = Self { next_page: None, - pages: PageMap::build_from(mem_map), + pages: PageMap::build_from(mem_map)?, }; hyp_pages.next_page = hyp_pages.next_free_page(first_page); - hyp_pages + Ok(hyp_pages) } /// Takes ownership of the remaining free pages, cleaning them and linking them together. Returns @@ -848,7 +852,7 @@ mod tests { .unwrap() .build() }; - let hyp_mem = HypPageAlloc::new(&mut hw_map); + let hyp_mem = HypPageAlloc::new(&mut hw_map).unwrap(); // Leak the backing ram so it doesn't get freed std::mem::forget(backing_mem); hyp_mem diff --git a/riscv-page-tables/src/test_stubs.rs b/riscv-page-tables/src/test_stubs.rs index ef3fc411..f8a7159e 100644 --- a/riscv-page-tables/src/test_stubs.rs +++ b/riscv-page-tables/src/test_stubs.rs @@ -35,7 +35,7 @@ pub fn stub_sys_memory() -> StubState { .unwrap() .build() }; - let mut hyp_mem = HypPageAlloc::new(&mut hw_map); + let mut hyp_mem = HypPageAlloc::new(&mut hw_map).unwrap(); let root_pages = hyp_mem.take_pages_for_host_state_with_alignment(4, Sv48x4::TOP_LEVEL_ALIGN); let pte_pages = hyp_mem.take_pages_for_host_state(3); let (page_tracker, host_pages) = PageTracker::from(hyp_mem, MEM_ALIGN as u64); diff --git a/src/main.rs b/src/main.rs index 087dd033..67d6d49a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -367,6 +367,8 @@ enum Error { CpuMissingFeature(RequiredCpuFeature), /// Problem generating CPU topology CpuTopologyGeneration(drivers::cpu::Error), + // Error creating hypervisor allocator + CreateHypervisorAllocator(PageTrackingError), /// Creating hypervisor map failed CreateHypervisorMap(hyp_map::Error), /// Creating (per CPU) SMP state @@ -398,6 +400,9 @@ impl Display for Error { BuildMemoryMap(e) => write!(f, "Failed to build memory map: {:?}", e), CpuMissingFeature(feature) => write!(f, "Missing required CPU feature: {:?}", feature), CpuTopologyGeneration(e) => write!(f, "Failed to generate CPU topology: {}", e), + CreateHypervisorAllocator(e) => { + write!(f, "Failed to create hypervisor page allocator: {:?}", e) + } CreateHypervisorMap(e) => write!(f, "Cannot create Hypervisor map: {:?}", e), CreateSmpState(e) => write!(f, "Error during (per CPU) SMP setup: {}", e), FdtCreation(e) => write!(f, "Failed to construct device-tree: {}", e), @@ -537,7 +542,7 @@ fn primary_init(hart_id: u64, fdt_addr: u64) -> Result { // Create an allocator for the remaining pages. Anything that's left over will be mapped // into the host VM. - let mut hyp_mem = HypPageAlloc::new(&mut mem_map); + let mut hyp_mem = HypPageAlloc::new(&mut mem_map).map_err(Error::CreateHypervisorAllocator)?; // NOTE: Do not modify the hardware memory map from here on. let mem_map = mem_map; // Remove mutability.