diff --git a/nucleus/src/arch/aarch64/memory/virt_page.rs b/nucleus/src/arch/aarch64/memory/virt_page.rs index 3d59187..8cfc148 100644 --- a/nucleus/src/arch/aarch64/memory/virt_page.rs +++ b/nucleus/src/arch/aarch64/memory/virt_page.rs @@ -19,12 +19,15 @@ use { /// A virtual memory page. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -#[repr(C)] pub struct Page { start_address: VirtAddr, size: PhantomData, } +enum Error { + NotAligned, +} + impl Page { /// The page size in bytes. pub const SIZE: usize = S::SIZE; @@ -32,11 +35,12 @@ impl Page { /// Returns the page that starts at the given virtual address. /// /// Returns an error if the address is not correctly aligned (i.e. is not a valid page start). - pub fn from_start_address(address: VirtAddr) -> Result { + pub fn from_start_address(address: VirtAddr) -> Result { if !address.is_aligned(S::SIZE) { - return Err(()); + Err(Error::NotAligned) + } else { + Ok(Page::containing_address(address)) } - Ok(Page::containing_address(address)) } /// Returns the page that contains the given virtual address. @@ -141,6 +145,7 @@ impl fmt::Debug for Page { impl Add for Page { type Output = Self; + // @todo should I add pages or just bytes here? fn add(self, rhs: u64) -> Self::Output { Page::containing_address(self.start_address() + rhs * u64::from(S::SIZE)) } @@ -154,6 +159,7 @@ impl AddAssign for Page { impl Sub for Page { type Output = Self; + // @todo should I sub pages or just bytes here? fn sub(self, rhs: u64) -> Self::Output { Page::containing_address(self.start_address() - rhs * u64::from(S::SIZE)) } @@ -174,7 +180,6 @@ impl Sub for Page { /// A range of pages with exclusive upper bound. #[derive(Clone, Copy, PartialEq, Eq)] -#[repr(C)] pub struct PageRange { /// The start of the range, inclusive. pub start: Page, @@ -197,7 +202,7 @@ impl Iterator for PageRange { type Item = Page; fn next(&mut self) -> Option { - if self.start < self.end { + if !self.is_empty() { let page = self.start.clone(); self.start += 1; Some(page) @@ -209,9 +214,11 @@ impl Iterator for PageRange { impl PageRange { /// Converts the range of 2MiB pages to a range of 4KiB pages. - pub fn as_4kib_page_range(self) -> PageRange { + // @todo what about range of 1GiB pages? + pub fn as_4kib_page_range(&self) -> PageRange { PageRange { start: Page::containing_address(self.start.start_address()), + // @fixme end is calculated incorrectly, add test end: Page::containing_address(self.end.start_address()), } } @@ -228,7 +235,6 @@ impl fmt::Debug for PageRange { /// A range of pages with inclusive upper bound. #[derive(Clone, Copy, PartialEq, Eq)] -#[repr(C)] pub struct PageRangeInclusive { /// The start of the range, inclusive. pub start: Page, @@ -247,7 +253,7 @@ impl Iterator for PageRangeInclusive { type Item = Page; fn next(&mut self) -> Option { - if self.start <= self.end { + if !self.is_empty() { let page = self.start.clone(); self.start += 1; Some(page) @@ -297,4 +303,19 @@ mod tests { } assert_eq!(range_inclusive.next(), None); } + + #[test_case] + fn test_page_range_conversion() { + let page_size = Size2MiB::SIZE; + let number = 10; + + let start_addr = VirtAddr::new(0xdeadbeaf); + let start: Page = Page::containing_address(start_addr); + let end = start.clone() + number; + + let range = Page::range(start.clone(), end.clone()).as_4kib_page_range(); + + // 10 2MiB pages is 512 4KiB pages + aseert_eq!(range.num_pages(), 512); + } }