use nodit::{Interval, NoditSet, interval::{iu, ii}, InclusiveInterval}; use crate::{memory::paging::{ManagedL4PageTable, Page, PageSize}, x86_64_consts::HIGHER_HALF_START}; use core::num::NonZero; use x86_64::VirtAddr; #[derive(Debug)] pub struct VirtualMemory { #[allow(unused)] pub(super) set: NoditSet>, #[allow(unused)] pub(super) l4: ManagedL4PageTable } impl VirtualMemory { /// Returns the start page of the allocated range of pages. /// Pages are guarenteed not to be mapped. pub fn allocate_contiguous_pages(&mut self, page_size: PageSize, n_pages: NonZero) -> Option { let interval = self .set .gaps_trimmed(&iu(HIGHER_HALF_START)) .find_map(|gap| { let aligned_start = gap.start().next_multiple_of(page_size.byte_len_u64()); let interval = ii( aligned_start, aligned_start + (n_pages.get() * page_size.byte_len_u64() - 1) ); if gap.contains_interval(&interval) { Some(interval) } else { None } })?; self.set .insert_merge_touching(interval) .expect("no overlap"); Some(Page::new(VirtAddr::new(*interval.start()), page_size).expect("should be aligned")) } pub fn l4_mut(&mut self) -> &mut ManagedL4PageTable { &mut self.l4 } }