diff --git a/src/addr.rs b/src/addr.rs index 8070369b..b262b82e 100644 --- a/src/addr.rs +++ b/src/addr.rs @@ -226,15 +226,20 @@ impl VirtAddr { } // FIXME: Move this into the `Step` impl, once `Step` is stabilized. - pub(crate) fn steps_between_impl(start: &Self, end: &Self) -> Option { - let mut steps = end.0.checked_sub(start.0)?; + pub(crate) fn steps_between_impl(start: &Self, end: &Self) -> (usize, Option) { + let mut steps = if let Some(steps) = end.0.checked_sub(start.0) { + steps + } else { + return (0, None); + }; // Check if we jumped the gap. if end.0.get_bit(47) && !start.0.get_bit(47) { steps = steps.checked_sub(0xffff_0000_0000_0000).unwrap(); } - usize::try_from(steps).ok() + let steps = usize::try_from(steps).ok(); + (steps.unwrap_or(usize::MAX), steps) } // FIXME: Move this into the `Step` impl, once `Step` is stabilized. @@ -379,7 +384,7 @@ impl Sub for VirtAddr { #[cfg(feature = "step_trait")] impl Step for VirtAddr { - fn steps_between(start: &Self, end: &Self) -> Option { + fn steps_between(start: &Self, end: &Self) -> (usize, Option) { Self::steps_between_impl(start, end) } @@ -758,43 +763,49 @@ mod tests { #[test] #[cfg(feature = "step_trait")] fn virtaddr_steps_between() { - assert_eq!(Step::steps_between(&VirtAddr(0), &VirtAddr(0)), Some(0)); - assert_eq!(Step::steps_between(&VirtAddr(0), &VirtAddr(1)), Some(1)); - assert_eq!(Step::steps_between(&VirtAddr(1), &VirtAddr(0)), None); + assert_eq!( + Step::steps_between(&VirtAddr(0), &VirtAddr(0)), + (0, Some(0)) + ); + assert_eq!( + Step::steps_between(&VirtAddr(0), &VirtAddr(1)), + (1, Some(1)) + ); + assert_eq!(Step::steps_between(&VirtAddr(1), &VirtAddr(0)), (0, None)); assert_eq!( Step::steps_between( &VirtAddr(0x7fff_ffff_ffff), &VirtAddr(0xffff_8000_0000_0000) ), - Some(1) + (1, Some(1)) ); assert_eq!( Step::steps_between( &VirtAddr(0xffff_8000_0000_0000), &VirtAddr(0x7fff_ffff_ffff) ), - None + (0, None) ); assert_eq!( Step::steps_between( &VirtAddr(0xffff_8000_0000_0000), &VirtAddr(0xffff_8000_0000_0000) ), - Some(0) + (0, Some(0)) ); assert_eq!( Step::steps_between( &VirtAddr(0xffff_8000_0000_0000), &VirtAddr(0xffff_8000_0000_0001) ), - Some(1) + (1, Some(1)) ); assert_eq!( Step::steps_between( &VirtAddr(0xffff_8000_0000_0001), &VirtAddr(0xffff_8000_0000_0000) ), - None + (0, None) ); } diff --git a/src/instructions/tlb.rs b/src/instructions/tlb.rs index 7f5fd48a..1cc16ec7 100644 --- a/src/instructions/tlb.rs +++ b/src/instructions/tlb.rs @@ -298,14 +298,14 @@ where if let Some(mut pages) = self.page_range { while !pages.is_empty() { // Calculate out how many pages we still need to flush. - let count = Page::::steps_between_impl(&pages.start, &pages.end).unwrap(); + let count = Page::::steps_between_impl(&pages.start, &pages.end).0; // Make sure that we never jump the gap in the address space when flushing. let second_half_start = Page::::containing_address(VirtAddr::new(0xffff_8000_0000_0000)); let count = if pages.start < second_half_start { let count_to_second_half = - Page::steps_between_impl(&pages.start, &second_half_start).unwrap(); + Page::steps_between_impl(&pages.start, &second_half_start).0; cmp::min(count, count_to_second_half) } else { count diff --git a/src/structures/paging/page.rs b/src/structures/paging/page.rs index 10414139..145a02f2 100644 --- a/src/structures/paging/page.rs +++ b/src/structures/paging/page.rs @@ -150,9 +150,11 @@ impl Page { } // FIXME: Move this into the `Step` impl, once `Step` is stabilized. - pub(crate) fn steps_between_impl(start: &Self, end: &Self) -> Option { - VirtAddr::steps_between_impl(&start.start_address, &end.start_address) - .map(|steps| steps / S::SIZE as usize) + pub(crate) fn steps_between_impl(start: &Self, end: &Self) -> (usize, Option) { + let (lower, upper) = VirtAddr::steps_between_impl(&start.start_address, &end.start_address); + let lower = lower / S::SIZE as usize; + let upper = upper.map(|steps| steps / S::SIZE as usize); + (lower, upper) } // FIXME: Move this into the `Step` impl, once `Step` is stabilized. @@ -279,7 +281,7 @@ impl Sub for Page { #[cfg(feature = "step_trait")] impl Step for Page { - fn steps_between(start: &Self, end: &Self) -> Option { + fn steps_between(start: &Self, end: &Self) -> (usize, Option) { Self::steps_between_impl(start, end) }