diff --git a/src/virtual_memory.rs b/src/virtual_memory.rs index 014e5e6..c14876c 100644 --- a/src/virtual_memory.rs +++ b/src/virtual_memory.rs @@ -32,6 +32,7 @@ pub struct AddressSpace { pub alloc_force_user: bool, pub mapper: OffsetPageTable<'static>, bytes_allocated: AtomicUsize, + bump_base: Page, } impl fmt::Debug for AddressSpace { @@ -196,6 +197,7 @@ pub static KERNEL_SPACE: Lazy = Lazy::new(|| { } let mut kernel_space = AddressSpace::new_with_addr(table); kernel_space.is_kernel = true; + kernel_space.bump_base = KERNEL_PAGE_RANGE.start; let l4_virt = VirtAddr::from_ptr(ptr::from_ref(kernel_space.mapper.level_4_table())); #[expect( clippy::unwrap_used, @@ -251,6 +253,7 @@ impl AddressSpace { alloc_force_user: false, is_kernel: false, bytes_allocated: AtomicUsize::new(0), + bump_base: USER_PAGE_RANGE.start, } } @@ -379,6 +382,9 @@ impl AddressSpace { PhysFrame::from_start_address_unchecked(PhysAddr::new(0x000F_FFFF_FFFF_F000)) }; self.check_request_valid(page, num_pages)?; + if self.bump_base < page + u64(num_pages) { + self.bump_base = page + u64(num_pages); + } #[expect( clippy::arithmetic_side_effects, reason = "This is the maximum physical frame, so there is no way the subtraction can underflow" @@ -455,6 +461,9 @@ impl AddressSpace { flags: PageTableFlags, ) -> Result<*mut u8, PagingError> { self.check_request_valid(page, num_pages)?; + if self.bump_base < page + u64(num_pages) { + self.bump_base = page + u64(num_pages); + } #[expect( clippy::arithmetic_side_effects, reason = "check_request_valid guarentees this won't overflow" @@ -544,7 +553,8 @@ impl AddressSpace { num_pages: usize, flags: PageTableFlags, ) -> Result<*mut u8, PagingError> { - unsafe { self.map_to(self.find_free_pages(num_pages)?, phys_frame, num_pages, flags) } + let start_page = self.find_free_pages(num_pages)?; + unsafe { self.map_to(start_page, phys_frame, num_pages, flags) } } /// Maps new virtual pages to new physical memory and returns the starting address. @@ -555,9 +565,10 @@ impl AddressSpace { num_pages: usize, flags: PageTableFlags, ) -> Result<*mut u8, PagingError> { + let start_page = self.find_free_pages(num_pages)?; // SAFETY: &mut aliasing is prevented by using free physical frames, and uninitialized // values are prevented by using free virtual pages. - let ptr = unsafe { self.map(self.find_free_pages(num_pages)?, num_pages, flags)? }; + let ptr = unsafe { self.map(start_page, num_pages, flags)? }; self.record_alloc(num_pages * 4096); Ok(ptr) } @@ -571,10 +582,10 @@ impl AddressSpace { num_pages: usize, flags: PageTableFlags, ) -> Result<(*mut u8, u64), PagingError> { + let start_page = self.find_free_pages(num_pages)?; // SAFETY: &mut aliasing is prevented by using free physical frames, and uninitialized // values are prevented by using free virtual pages. - let ptr = - unsafe { self.map_cont_phys(self.find_free_pages(num_pages)?, num_pages, flags)? }; + let ptr = unsafe { self.map_cont_phys(start_page, num_pages, flags)? }; self.record_alloc(num_pages * 4096); Ok(ptr) } @@ -602,6 +613,9 @@ impl AddressSpace { flags: PageTableFlags, ) -> Result<*mut u8, PagingError> { self.check_request_valid(page, num_pages)?; + if self.bump_base < page + u64(num_pages) { + self.bump_base = page + u64(num_pages); + } assert!(!self.alloc_force_user); #[expect( clippy::arithmetic_side_effects, @@ -733,33 +747,41 @@ impl AddressSpace { } /// Finds a range of free pages and returns the starting page - fn find_free_pages(&self, num_pages: usize) -> Result { - if num_pages == 0 { - return Err(PagingError::PageAllocationFailed); - } - let mut remaining_pages = num_pages; - let range = if self.is_kernel { KERNEL_PAGE_RANGE } else { USER_PAGE_RANGE }; - for page in range { - if self.translate_addr(page.start_address()).is_none() { - #[expect( - clippy::arithmetic_side_effects, - reason = "remaining_pages can never be 0 here, thus this can't underflow" - )] - { - remaining_pages -= 1; - } - if remaining_pages == 0 { + fn find_free_pages(&mut self, num_pages: usize) -> Result { + if self.is_kernel { + if num_pages == 0 { + return Err(PagingError::PageAllocationFailed); + } + let mut remaining_pages = num_pages; + let range = if self.is_kernel { KERNEL_PAGE_RANGE } else { USER_PAGE_RANGE }; + for page in range { + if self.translate_addr(page.start_address()).is_none() { #[expect( clippy::arithmetic_side_effects, - reason = "page is at minimum num_pages - 1, thus this can't underflow" + reason = "remaining_pages can never be 0 here, thus this can't underflow" )] - return Ok(page + 1 - u64(num_pages)); - } - } else { - remaining_pages = num_pages; - }; + { + remaining_pages -= 1; + } + if remaining_pages == 0 { + #[expect( + clippy::arithmetic_side_effects, + reason = "page is at minimum num_pages - 1, thus this can't underflow" + )] + return Ok(page + 1 - u64(num_pages)); + } + } else { + remaining_pages = num_pages; + }; + } + Err(PagingError::PageAllocationFailed) + } else if USER_PAGE_RANGE.end - self.bump_base < u64(num_pages) { + Err(PagingError::PageAllocationFailed) + } else { + let old_base = self.bump_base; + self.bump_base += u64(num_pages); + Ok(old_base) } - Err(PagingError::PageAllocationFailed) } pub fn record_alloc(&self, size: usize) {