Skip to content

Commit 51d602c

Browse files
authored
Merge pull request #513 from rust-osdev/fix/step-nightly-breakage
fix signature of Step::steps_between implementations
2 parents e016a4c + b4b6663 commit 51d602c

File tree

5 files changed

+231
-51
lines changed

5 files changed

+231
-51
lines changed

.github/workflows/build.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
- uses: actions/checkout@v4
5757
- uses: dtolnay/rust-toolchain@nightly
5858
with:
59-
targets: x86_64-unknown-linux-musl, i686-unknown-linux-gnu, thumbv7em-none-eabihf
59+
targets: x86_64-unknown-linux-musl, i686-unknown-linux-musl, thumbv7em-none-eabihf
6060

6161
- run: cargo build
6262

@@ -72,9 +72,12 @@ jobs:
7272

7373
- name: "Build on non x86_64 platforms"
7474
run: |
75-
cargo build --target i686-unknown-linux-gnu --no-default-features --features nightly
75+
cargo build --target i686-unknown-linux-musl --no-default-features --features nightly
7676
cargo build --target thumbv7em-none-eabihf --no-default-features --features nightly
7777
78+
- run: cargo test --target i686-unknown-linux-musl --no-default-features --features nightly
79+
if: runner.os == 'Linux'
80+
7881
bootloader-test:
7982
name: "Bootloader Integration Test"
8083

src/addr.rs

Lines changed: 95 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -240,25 +240,43 @@ impl VirtAddr {
240240
}
241241

242242
// FIXME: Move this into the `Step` impl, once `Step` is stabilized.
243+
#[cfg(feature = "step_trait")]
244+
pub(crate) fn steps_between_impl(start: &Self, end: &Self) -> (usize, Option<usize>) {
245+
if let Some(steps) = Self::steps_between_u64(start, end) {
246+
let steps = usize::try_from(steps).ok();
247+
(steps.unwrap_or(usize::MAX), steps)
248+
} else {
249+
(0, None)
250+
}
251+
}
252+
253+
/// An implementation of steps_between that returns u64. Note that this
254+
/// function always returns the exact bound, so it doesn't need to return a
255+
/// lower and upper bound like steps_between does.
243256
#[cfg(any(feature = "instructions", feature = "step_trait"))]
244-
pub(crate) fn steps_between_impl(start: &Self, end: &Self) -> Option<usize> {
257+
pub(crate) fn steps_between_u64(start: &Self, end: &Self) -> Option<u64> {
245258
let mut steps = end.0.checked_sub(start.0)?;
246259

247260
// Mask away extra bits that appear while jumping the gap.
248261
steps &= 0xffff_ffff_ffff;
249262

250-
usize::try_from(steps).ok()
263+
Some(steps)
251264
}
252265

253266
// FIXME: Move this into the `Step` impl, once `Step` is stabilized.
254267
#[inline]
255268
pub(crate) fn forward_checked_impl(start: Self, count: usize) -> Option<Self> {
256-
let offset = u64::try_from(count).ok()?;
257-
if offset > ADDRESS_SPACE_SIZE {
269+
Self::forward_checked_u64(start, u64::try_from(count).ok()?)
270+
}
271+
272+
/// An implementation of forward_checked that takes u64 instead of usize.
273+
#[inline]
274+
pub(crate) fn forward_checked_u64(start: Self, count: u64) -> Option<Self> {
275+
if count > ADDRESS_SPACE_SIZE {
258276
return None;
259277
}
260278

261-
let mut addr = start.0.checked_add(offset)?;
279+
let mut addr = start.0.checked_add(count)?;
262280

263281
match addr.get_bits(47..) {
264282
0x1 => {
@@ -274,6 +292,31 @@ impl VirtAddr {
274292

275293
Some(unsafe { Self::new_unsafe(addr) })
276294
}
295+
296+
/// An implementation of backward_checked that takes u64 instead of usize.
297+
#[cfg(feature = "step_trait")]
298+
#[inline]
299+
pub(crate) fn backward_checked_u64(start: Self, count: u64) -> Option<Self> {
300+
if count > ADDRESS_SPACE_SIZE {
301+
return None;
302+
}
303+
304+
let mut addr = start.0.checked_sub(count)?;
305+
306+
match addr.get_bits(47..) {
307+
0x1fffe => {
308+
// Jump the gap by sign extending the 47th bit.
309+
addr.set_bits(47.., 0);
310+
}
311+
0x1fffd => {
312+
// Address underflow
313+
return None;
314+
}
315+
_ => {}
316+
}
317+
318+
Some(unsafe { Self::new_unsafe(addr) })
319+
}
277320
}
278321

279322
impl fmt::Debug for VirtAddr {
@@ -360,7 +403,7 @@ impl Sub<VirtAddr> for VirtAddr {
360403
#[cfg(feature = "step_trait")]
361404
impl Step for VirtAddr {
362405
#[inline]
363-
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
406+
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
364407
Self::steps_between_impl(start, end)
365408
}
366409

@@ -371,26 +414,7 @@ impl Step for VirtAddr {
371414

372415
#[inline]
373416
fn backward_checked(start: Self, count: usize) -> Option<Self> {
374-
let offset = u64::try_from(count).ok()?;
375-
if offset > ADDRESS_SPACE_SIZE {
376-
return None;
377-
}
378-
379-
let mut addr = start.0.checked_sub(offset)?;
380-
381-
match addr.get_bits(47..) {
382-
0x1fffe => {
383-
// Jump the gap by sign extending the 47th bit.
384-
addr.set_bits(47.., 0);
385-
}
386-
0x1fffd => {
387-
// Address underflow
388-
return None;
389-
}
390-
_ => {}
391-
}
392-
393-
Some(unsafe { Self::new_unsafe(addr) })
417+
Self::backward_checked_u64(start, u64::try_from(count).ok()?)
394418
}
395419
}
396420

@@ -664,22 +688,27 @@ mod tests {
664688
Step::forward_checked(VirtAddr(0xffff_ffff_ffff_ffff), 1),
665689
None
666690
);
691+
#[cfg(target_pointer_width = "64")]
667692
assert_eq!(
668693
Step::forward(VirtAddr(0x7fff_ffff_ffff), 0x1234_5678_9abd),
669694
VirtAddr(0xffff_9234_5678_9abc)
670695
);
696+
#[cfg(target_pointer_width = "64")]
671697
assert_eq!(
672698
Step::forward(VirtAddr(0x7fff_ffff_ffff), 0x8000_0000_0000),
673699
VirtAddr(0xffff_ffff_ffff_ffff)
674700
);
701+
#[cfg(target_pointer_width = "64")]
675702
assert_eq!(
676703
Step::forward(VirtAddr(0x7fff_ffff_ff00), 0x8000_0000_00ff),
677704
VirtAddr(0xffff_ffff_ffff_ffff)
678705
);
706+
#[cfg(target_pointer_width = "64")]
679707
assert_eq!(
680708
Step::forward_checked(VirtAddr(0x7fff_ffff_ff00), 0x8000_0000_0100),
681709
None
682710
);
711+
#[cfg(target_pointer_width = "64")]
683712
assert_eq!(
684713
Step::forward_checked(VirtAddr(0x7fff_ffff_ffff), 0x8000_0000_0001),
685714
None
@@ -700,18 +729,22 @@ mod tests {
700729
Step::backward(VirtAddr(0xffff_8000_0000_0001), 1),
701730
VirtAddr(0xffff_8000_0000_0000)
702731
);
732+
#[cfg(target_pointer_width = "64")]
703733
assert_eq!(
704734
Step::backward(VirtAddr(0xffff_9234_5678_9abc), 0x1234_5678_9abd),
705735
VirtAddr(0x7fff_ffff_ffff)
706736
);
737+
#[cfg(target_pointer_width = "64")]
707738
assert_eq!(
708739
Step::backward(VirtAddr(0xffff_8000_0000_0000), 0x8000_0000_0000),
709740
VirtAddr(0)
710741
);
742+
#[cfg(target_pointer_width = "64")]
711743
assert_eq!(
712744
Step::backward(VirtAddr(0xffff_8000_0000_0000), 0x7fff_ffff_ff01),
713745
VirtAddr(0xff)
714746
);
747+
#[cfg(target_pointer_width = "64")]
715748
assert_eq!(
716749
Step::backward_checked(VirtAddr(0xffff_8000_0000_0000), 0x8000_0000_0001),
717750
None
@@ -721,43 +754,64 @@ mod tests {
721754
#[test]
722755
#[cfg(feature = "step_trait")]
723756
fn virtaddr_steps_between() {
724-
assert_eq!(Step::steps_between(&VirtAddr(0), &VirtAddr(0)), Some(0));
725-
assert_eq!(Step::steps_between(&VirtAddr(0), &VirtAddr(1)), Some(1));
726-
assert_eq!(Step::steps_between(&VirtAddr(1), &VirtAddr(0)), None);
757+
assert_eq!(
758+
Step::steps_between(&VirtAddr(0), &VirtAddr(0)),
759+
(0, Some(0))
760+
);
761+
assert_eq!(
762+
Step::steps_between(&VirtAddr(0), &VirtAddr(1)),
763+
(1, Some(1))
764+
);
765+
assert_eq!(Step::steps_between(&VirtAddr(1), &VirtAddr(0)), (0, None));
727766
assert_eq!(
728767
Step::steps_between(
729768
&VirtAddr(0x7fff_ffff_ffff),
730769
&VirtAddr(0xffff_8000_0000_0000)
731770
),
732-
Some(1)
771+
(1, Some(1))
733772
);
734773
assert_eq!(
735774
Step::steps_between(
736775
&VirtAddr(0xffff_8000_0000_0000),
737776
&VirtAddr(0x7fff_ffff_ffff)
738777
),
739-
None
778+
(0, None)
740779
);
741780
assert_eq!(
742781
Step::steps_between(
743782
&VirtAddr(0xffff_8000_0000_0000),
744783
&VirtAddr(0xffff_8000_0000_0000)
745784
),
746-
Some(0)
785+
(0, Some(0))
747786
);
748787
assert_eq!(
749788
Step::steps_between(
750789
&VirtAddr(0xffff_8000_0000_0000),
751790
&VirtAddr(0xffff_8000_0000_0001)
752791
),
753-
Some(1)
792+
(1, Some(1))
754793
);
755794
assert_eq!(
756795
Step::steps_between(
757796
&VirtAddr(0xffff_8000_0000_0001),
758797
&VirtAddr(0xffff_8000_0000_0000)
759798
),
760-
None
799+
(0, None)
800+
);
801+
// Make sure that we handle `steps > u32::MAX` correctly on 32-bit
802+
// targets. On 64-bit targets, `0x1_0000_0000` fits into `usize`, so we
803+
// can return exact lower and upper bounds. On 32-bit targets,
804+
// `0x1_0000_0000` doesn't fit into `usize`, so we only return an lower
805+
// bound of `usize::MAX` and don't return an upper bound.
806+
#[cfg(target_pointer_width = "64")]
807+
assert_eq!(
808+
Step::steps_between(&VirtAddr(0), &VirtAddr(0x1_0000_0000)),
809+
(0x1_0000_0000, Some(0x1_0000_0000))
810+
);
811+
#[cfg(not(target_pointer_width = "64"))]
812+
assert_eq!(
813+
Step::steps_between(&VirtAddr(0), &VirtAddr(0x1_0000_0000)),
814+
(usize::MAX, None)
761815
);
762816
}
763817

@@ -809,10 +863,14 @@ mod tests {
809863
}
810864

811865
#[test]
866+
#[cfg(target_pointer_width = "64")]
812867
fn test_from_ptr_array() {
813868
let slice = &[1, 2, 3, 4, 5];
814869
// Make sure that from_ptr(slice) is the address of the first element
815-
assert_eq!(VirtAddr::from_ptr(slice), VirtAddr::from_ptr(&slice[0]));
870+
assert_eq!(
871+
VirtAddr::from_ptr(slice.as_slice()),
872+
VirtAddr::from_ptr(&slice[0])
873+
);
816874
}
817875
}
818876

@@ -951,7 +1009,7 @@ mod proofs {
9511009
};
9521010

9531011
// ...then `steps_between` succeeds as well.
954-
assert!(Step::steps_between(&start, &end) == Some(count));
1012+
assert!(Step::steps_between(&start, &end) == (count, Some(count)));
9551013
}
9561014

9571015
// This harness proves that for all inputs for which `steps_between`
@@ -968,7 +1026,7 @@ mod proofs {
9681026
};
9691027

9701028
// If `steps_between` succeeds...
971-
let Some(count) = Step::steps_between(&start, &end) else {
1029+
let Some(count) = Step::steps_between(&start, &end).1 else {
9721030
return;
9731031
};
9741032

src/instructions/tlb.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,14 +315,14 @@ where
315315
if let Some(mut pages) = self.page_range {
316316
while !pages.is_empty() {
317317
// Calculate out how many pages we still need to flush.
318-
let count = Page::<S>::steps_between_impl(&pages.start, &pages.end).unwrap();
318+
let count = Page::<S>::steps_between_impl(&pages.start, &pages.end).0;
319319

320320
// Make sure that we never jump the gap in the address space when flushing.
321321
let second_half_start =
322322
Page::<S>::containing_address(VirtAddr::new(0xffff_8000_0000_0000));
323323
let count = if pages.start < second_half_start {
324324
let count_to_second_half =
325-
Page::steps_between_impl(&pages.start, &second_half_start).unwrap();
325+
Page::steps_between_impl(&pages.start, &second_half_start).0;
326326
cmp::min(count, count_to_second_half)
327327
} else {
328328
count

0 commit comments

Comments
 (0)