Skip to content

Commit 4823b0c

Browse files
authored
Merge pull request #375 from Freax13/fix-virtaddr-alignup
fix align functions
2 parents 3cae23e + 49b9204 commit 4823b0c

File tree

1 file changed

+50
-5
lines changed

1 file changed

+50
-5
lines changed

src/addr.rs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,17 @@ impl VirtAddr {
158158
/// Aligns the virtual address upwards to the given alignment.
159159
///
160160
/// See the `align_up` function for more information.
161+
///
162+
/// # Panics
163+
///
164+
/// This function panics if the resulting address is higher than
165+
/// `0xffff_ffff_ffff_ffff`.
161166
#[inline]
162167
pub fn align_up<U>(self, align: U) -> Self
163168
where
164169
U: Into<u64>,
165170
{
166-
VirtAddr(align_up(self.0, align.into()))
171+
VirtAddr::new_truncate(align_up(self.0, align.into()))
167172
}
168173

169174
/// Aligns the virtual address downwards to the given alignment.
@@ -174,7 +179,7 @@ impl VirtAddr {
174179
where
175180
U: Into<u64>,
176181
{
177-
VirtAddr(align_down(self.0, align.into()))
182+
VirtAddr::new_truncate(align_down(self.0, align.into()))
178183
}
179184

180185
/// Checks whether the virtual address has the demanded alignment.
@@ -478,12 +483,17 @@ impl PhysAddr {
478483
/// Aligns the physical address upwards to the given alignment.
479484
///
480485
/// See the `align_up` function for more information.
486+
///
487+
/// # Panics
488+
///
489+
/// This function panics if the resulting address has a bit in the range 52
490+
/// to 64 set.
481491
#[inline]
482492
pub fn align_up<U>(self, align: U) -> Self
483493
where
484494
U: Into<u64>,
485495
{
486-
PhysAddr(align_up(self.0, align.into()))
496+
PhysAddr::new(align_up(self.0, align.into()))
487497
}
488498

489499
/// Aligns the physical address downwards to the given alignment.
@@ -637,15 +647,20 @@ pub const fn align_down(addr: u64, align: u64) -> u64 {
637647
///
638648
/// Returns the smallest `x` with alignment `align` so that `x >= addr`.
639649
///
640-
/// Panics if the alignment is not a power of two.
650+
/// Panics if the alignment is not a power of two or if an overflow occurs.
641651
#[inline]
642652
pub const fn align_up(addr: u64, align: u64) -> u64 {
643653
assert!(align.is_power_of_two(), "`align` must be a power of two");
644654
let align_mask = align - 1;
645655
if addr & align_mask == 0 {
646656
addr // already aligned
647657
} else {
648-
(addr | align_mask) + 1
658+
// FIXME: Replace with .expect, once `Option::expect` is const.
659+
if let Some(aligned) = (addr | align_mask).checked_add(1) {
660+
aligned
661+
} else {
662+
panic!("attempt to add with overflow")
663+
}
649664
}
650665
}
651666

@@ -791,4 +806,34 @@ mod tests {
791806
assert_eq!(align_up(0, 2), 0);
792807
assert_eq!(align_up(0, 0x8000_0000_0000_0000), 0);
793808
}
809+
810+
#[test]
811+
fn test_virt_addr_align_up() {
812+
// Make sure the 47th bit is extended.
813+
assert_eq!(
814+
VirtAddr::new(0x7fff_ffff_ffff).align_up(2u64),
815+
VirtAddr::new(0xffff_8000_0000_0000)
816+
);
817+
}
818+
819+
#[test]
820+
fn test_virt_addr_align_down() {
821+
// Make sure the 47th bit is extended.
822+
assert_eq!(
823+
VirtAddr::new(0xffff_8000_0000_0000).align_down(1u64 << 48),
824+
VirtAddr::new(0)
825+
);
826+
}
827+
828+
#[test]
829+
#[should_panic]
830+
fn test_virt_addr_align_up_overflow() {
831+
VirtAddr::new(0xffff_ffff_ffff_ffff).align_up(2u64);
832+
}
833+
834+
#[test]
835+
#[should_panic]
836+
fn test_phys_addr_align_up_overflow() {
837+
PhysAddr::new(0x000f_ffff_ffff_ffff).align_up(2u64);
838+
}
794839
}

0 commit comments

Comments
 (0)