Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use core::ops::Range and core::ops::RangeInclusive instead of custom range structs #517

Closed
wants to merge 46 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
a9c3dc8
fix indentation in doc comments
Freax13 May 24, 2024
a98580e
fix warnings in tests
Freax13 May 24, 2024
9a062df
Merge pull request #488 from Freax13/fix_indentation
phil-opp May 24, 2024
3eaf06f
add private const variants for PhysAddr functions
Freax13 Jun 9, 2024
c5bc9fc
constify PhysFrame functions
Freax13 Jun 9, 2024
24691eb
Merge pull request #489 from rust-osdev/feature/const-phys-frame
phil-opp Jun 10, 2024
b0843da
Ensure that Page actually implements Hash
Wasabi375 Jul 4, 2024
2d3bd56
Merge pull request #490 from Wasabi375/zst_hash
Freax13 Jul 4, 2024
3fec974
don't use label starting with `1`
Freax13 Jul 14, 2024
1d8a69c
Merge pull request #492 from rust-osdev/fix/nightly-2024-07-14
phil-opp Jul 22, 2024
ae65fb6
Add size and len for PageRange, PhysFrameRange etc
Wasabi375 Jul 14, 2024
a59bf9f
Merge pull request #491 from Wasabi375/ranges
Freax13 Jul 22, 2024
b349961
fix warning in integration test
Freax13 Jul 31, 2024
df502ff
Merge pull request #495 from rust-osdev/fix-unsafe-warning
phil-opp Jul 31, 2024
9dca072
remove #![feature(asm_const)]
Freax13 Aug 15, 2024
7b47163
Merge pull request #496 from rust-osdev/fix/nightyly-2024-08-15
Freax13 Aug 15, 2024
d3e28e9
Remove stabilized `const_mut_refs` feature
phil-opp Oct 7, 2024
eec5d25
Break long doc paragraph
phil-opp Oct 7, 2024
1829dc1
Elide explicit lifetimes when possible
phil-opp Oct 7, 2024
8adb26d
Merge pull request #501 from rust-osdev/remove-const_mut_refs-feature
Freax13 Oct 8, 2024
323d46c
Merge pull request #502 from rust-osdev/fix-clippy-warnings
Freax13 Oct 8, 2024
0b5476e
gate HandlerFunc behind target_arch = "x86{_64}"
Freax13 Oct 21, 2024
4bd1973
fix field order for INVPCID descriptor
Freax13 Nov 3, 2024
f85f015
Merge pull request #508 from rust-osdev/fix/pcid-order
Freax13 Nov 10, 2024
e045300
fix CI job for building on MSRV
Freax13 Nov 12, 2024
def4212
only make append & push const on Rust 1.83+
Freax13 Nov 12, 2024
3fc9106
Merge pull request #510 from rust-osdev/fix/ci-msrv
Freax13 Nov 13, 2024
7525088
Merge pull request #507 from rust-osdev/fix/gate-handlers
Freax13 Nov 15, 2024
199d614
fix typo in "InvPicdCommand"
Freax13 Nov 10, 2024
3943178
Merge pull request #509 from rust-osdev/fix/inv-picd-command
Freax13 Nov 15, 2024
6e0652f
TryFrom implementation for ExceptionVector
mrjbom Oct 20, 2024
08e0172
Merge pull request #506 from mrjbom/TryFrom_for_ExceptionVector
Freax13 Nov 16, 2024
87d1eb1
More precise comments in TaskStateSegment
mrjbom Oct 19, 2024
7011547
More precise comments in TaskStateSegment
mrjbom Oct 21, 2024
a9187de
More precise comments in TaskStateSegment
mrjbom Oct 21, 2024
6d94a46
More precise comments in TaskStateSegment
mrjbom Oct 21, 2024
dc222cb
Merge pull request #504 from mrjbom/master
Freax13 Nov 16, 2024
f9c352b
Minor clarification
mrjbom Oct 19, 2024
e016a4c
Merge pull request #503 from mrjbom/mrjbom-gdt-patch-1
Freax13 Nov 16, 2024
b9e3d25
fix signature of Step::steps_between implementations
Freax13 Nov 24, 2024
3d65714
actually test with slice instead of array
Freax13 Nov 24, 2024
1e5b5a1
fix tests on 32-bit platforms
Freax13 Nov 24, 2024
8fb0668
run tests on a 32-bit platform
Freax13 Nov 24, 2024
b4b6663
fix Page Step impl on 32-bit platforms
Freax13 Nov 24, 2024
13f1450
Use core::ops::Range where possible
ChocolateLoverRaj Nov 28, 2024
2f0d9de
Add iter_pages() for use without Step trait
ChocolateLoverRaj Nov 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ jobs:
- nightly
- 1.59
runs-on: ubuntu-latest
env:
# rustup prioritizes environment variables over rust-toolchain.toml files.
RUSTUP_TOOLCHAIN: ${{ matrix.rust }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
Expand Down Expand Up @@ -53,7 +56,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
with:
targets: x86_64-unknown-linux-musl, i686-unknown-linux-gnu, thumbv7em-none-eabihf
targets: x86_64-unknown-linux-musl, i686-unknown-linux-musl, thumbv7em-none-eabihf

- run: cargo build

Expand All @@ -69,9 +72,12 @@ jobs:

- name: "Build on non x86_64 platforms"
run: |
cargo build --target i686-unknown-linux-gnu --no-default-features --features nightly
cargo build --target i686-unknown-linux-musl --no-default-features --features nightly
cargo build --target thumbv7em-none-eabihf --no-default-features --features nightly

- run: cargo test --target i686-unknown-linux-musl --no-default-features --features nightly
if: runner.os == 'Linux'

bootloader-test:
name: "Bootloader Integration Test"

Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ rustversion = "1.0.5"
[features]
default = ["nightly", "instructions"]
instructions = []
nightly = [ "const_fn", "step_trait", "abi_x86_interrupt", "asm_const" ]
nightly = ["const_fn", "step_trait", "abi_x86_interrupt", "asm_const"]
abi_x86_interrupt = []
# deprecated, no longer needed
const_fn = []
asm_const = []
step_trait = []
Expand Down
4 changes: 4 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Unreleased

## New Features

- [add `size` and `len` for `PageRange`, `PhysFrameRange`, `PageRangeInclusive` and `PhysFrameRangeInclusive`](https://github.com/rust-osdev/x86_64/pull/491)

# 0.15.1 – 2024-03-19

## New Features
Expand Down
150 changes: 111 additions & 39 deletions src/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,25 +240,43 @@ impl VirtAddr {
}

// FIXME: Move this into the `Step` impl, once `Step` is stabilized.
#[cfg(feature = "step_trait")]
pub(crate) fn steps_between_impl(start: &Self, end: &Self) -> (usize, Option<usize>) {
if let Some(steps) = Self::steps_between_u64(start, end) {
let steps = usize::try_from(steps).ok();
(steps.unwrap_or(usize::MAX), steps)
} else {
(0, None)
}
}

/// An implementation of steps_between that returns u64. Note that this
/// function always returns the exact bound, so it doesn't need to return a
/// lower and upper bound like steps_between does.
#[cfg(any(feature = "instructions", feature = "step_trait"))]
pub(crate) fn steps_between_impl(start: &Self, end: &Self) -> Option<usize> {
pub(crate) fn steps_between_u64(start: &Self, end: &Self) -> Option<u64> {
let mut steps = end.0.checked_sub(start.0)?;

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

usize::try_from(steps).ok()
Some(steps)
}

// FIXME: Move this into the `Step` impl, once `Step` is stabilized.
#[inline]
pub(crate) fn forward_checked_impl(start: Self, count: usize) -> Option<Self> {
let offset = u64::try_from(count).ok()?;
if offset > ADDRESS_SPACE_SIZE {
Self::forward_checked_u64(start, u64::try_from(count).ok()?)
}

/// An implementation of forward_checked that takes u64 instead of usize.
#[inline]
pub(crate) fn forward_checked_u64(start: Self, count: u64) -> Option<Self> {
if count > ADDRESS_SPACE_SIZE {
return None;
}

let mut addr = start.0.checked_add(offset)?;
let mut addr = start.0.checked_add(count)?;

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

Some(unsafe { Self::new_unsafe(addr) })
}

/// An implementation of backward_checked that takes u64 instead of usize.
#[cfg(feature = "step_trait")]
#[inline]
pub(crate) fn backward_checked_u64(start: Self, count: u64) -> Option<Self> {
if count > ADDRESS_SPACE_SIZE {
return None;
}

let mut addr = start.0.checked_sub(count)?;

match addr.get_bits(47..) {
0x1fffe => {
// Jump the gap by sign extending the 47th bit.
addr.set_bits(47.., 0);
}
0x1fffd => {
// Address underflow
return None;
}
_ => {}
}

Some(unsafe { Self::new_unsafe(addr) })
}
}

impl fmt::Debug for VirtAddr {
Expand Down Expand Up @@ -360,7 +403,7 @@ impl Sub<VirtAddr> for VirtAddr {
#[cfg(feature = "step_trait")]
impl Step for VirtAddr {
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
Self::steps_between_impl(start, end)
}

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

#[inline]
fn backward_checked(start: Self, count: usize) -> Option<Self> {
let offset = u64::try_from(count).ok()?;
if offset > ADDRESS_SPACE_SIZE {
return None;
}

let mut addr = start.0.checked_sub(offset)?;

match addr.get_bits(47..) {
0x1fffe => {
// Jump the gap by sign extending the 47th bit.
addr.set_bits(47.., 0);
}
0x1fffd => {
// Address underflow
return None;
}
_ => {}
}

Some(unsafe { Self::new_unsafe(addr) })
Self::backward_checked_u64(start, u64::try_from(count).ok()?)
}
}

Expand Down Expand Up @@ -495,7 +519,15 @@ impl PhysAddr {
where
U: Into<u64>,
{
PhysAddr(align_down(self.0, align.into()))
self.align_down_u64(align.into())
}

/// Aligns the physical address downwards to the given alignment.
///
/// See the `align_down` function for more information.
#[inline]
pub(crate) const fn align_down_u64(self, align: u64) -> Self {
PhysAddr(align_down(self.0, align))
}

/// Checks whether the physical address has the demanded alignment.
Expand All @@ -504,7 +536,13 @@ impl PhysAddr {
where
U: Into<u64>,
{
self.align_down(align) == self
self.is_aligned_u64(align.into())
}

/// Checks whether the physical address has the demanded alignment.
#[inline]
pub(crate) const fn is_aligned_u64(self, align: u64) -> bool {
self.align_down_u64(align).as_u64() == self.as_u64()
}
}

Expand Down Expand Up @@ -650,22 +688,27 @@ mod tests {
Step::forward_checked(VirtAddr(0xffff_ffff_ffff_ffff), 1),
None
);
#[cfg(target_pointer_width = "64")]
assert_eq!(
Step::forward(VirtAddr(0x7fff_ffff_ffff), 0x1234_5678_9abd),
VirtAddr(0xffff_9234_5678_9abc)
);
#[cfg(target_pointer_width = "64")]
assert_eq!(
Step::forward(VirtAddr(0x7fff_ffff_ffff), 0x8000_0000_0000),
VirtAddr(0xffff_ffff_ffff_ffff)
);
#[cfg(target_pointer_width = "64")]
assert_eq!(
Step::forward(VirtAddr(0x7fff_ffff_ff00), 0x8000_0000_00ff),
VirtAddr(0xffff_ffff_ffff_ffff)
);
#[cfg(target_pointer_width = "64")]
assert_eq!(
Step::forward_checked(VirtAddr(0x7fff_ffff_ff00), 0x8000_0000_0100),
None
);
#[cfg(target_pointer_width = "64")]
assert_eq!(
Step::forward_checked(VirtAddr(0x7fff_ffff_ffff), 0x8000_0000_0001),
None
Expand All @@ -686,18 +729,22 @@ mod tests {
Step::backward(VirtAddr(0xffff_8000_0000_0001), 1),
VirtAddr(0xffff_8000_0000_0000)
);
#[cfg(target_pointer_width = "64")]
assert_eq!(
Step::backward(VirtAddr(0xffff_9234_5678_9abc), 0x1234_5678_9abd),
VirtAddr(0x7fff_ffff_ffff)
);
#[cfg(target_pointer_width = "64")]
assert_eq!(
Step::backward(VirtAddr(0xffff_8000_0000_0000), 0x8000_0000_0000),
VirtAddr(0)
);
#[cfg(target_pointer_width = "64")]
assert_eq!(
Step::backward(VirtAddr(0xffff_8000_0000_0000), 0x7fff_ffff_ff01),
VirtAddr(0xff)
);
#[cfg(target_pointer_width = "64")]
assert_eq!(
Step::backward_checked(VirtAddr(0xffff_8000_0000_0000), 0x8000_0000_0001),
None
Expand All @@ -707,43 +754,64 @@ 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)
);
// Make sure that we handle `steps > u32::MAX` correctly on 32-bit
// targets. On 64-bit targets, `0x1_0000_0000` fits into `usize`, so we
// can return exact lower and upper bounds. On 32-bit targets,
// `0x1_0000_0000` doesn't fit into `usize`, so we only return an lower
// bound of `usize::MAX` and don't return an upper bound.
#[cfg(target_pointer_width = "64")]
assert_eq!(
Step::steps_between(&VirtAddr(0), &VirtAddr(0x1_0000_0000)),
(0x1_0000_0000, Some(0x1_0000_0000))
);
#[cfg(not(target_pointer_width = "64"))]
assert_eq!(
Step::steps_between(&VirtAddr(0), &VirtAddr(0x1_0000_0000)),
(usize::MAX, None)
);
}

Expand Down Expand Up @@ -795,10 +863,14 @@ mod tests {
}

#[test]
#[cfg(target_pointer_width = "64")]
fn test_from_ptr_array() {
let slice = &[1, 2, 3, 4, 5];
// Make sure that from_ptr(slice) is the address of the first element
assert_eq!(VirtAddr::from_ptr(slice), VirtAddr::from_ptr(&slice[0]));
assert_eq!(
VirtAddr::from_ptr(slice.as_slice()),
VirtAddr::from_ptr(&slice[0])
);
}
}

Expand Down Expand Up @@ -937,7 +1009,7 @@ mod proofs {
};

// ...then `steps_between` succeeds as well.
assert!(Step::steps_between(&start, &end) == Some(count));
assert!(Step::steps_between(&start, &end) == (count, Some(count)));
}

// This harness proves that for all inputs for which `steps_between`
Expand All @@ -954,7 +1026,7 @@ mod proofs {
};

// If `steps_between` succeeds...
let Some(count) = Step::steps_between(&start, &end) else {
let Some(count) = Step::steps_between(&start, &end).1 else {
return;
};

Expand Down
7 changes: 5 additions & 2 deletions src/instructions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ pub fn nop() {
}
}

/// Emits a '[magic breakpoint](https://wiki.osdev.org/Bochs#Magic_Breakpoint)' instruction for the [Bochs](http://bochs.sourceforge.net/) CPU
/// emulator. Make sure to set `magic_break: enabled=1` in your `.bochsrc` file.
/// Emits a '[magic breakpoint](https://wiki.osdev.org/Bochs#Magic_Breakpoint)'
/// instruction for the [Bochs](http://bochs.sourceforge.net/) CPU
/// emulator.
///
/// Make sure to set `magic_break: enabled=1` in your `.bochsrc` file.
#[inline]
pub fn bochs_breakpoint() {
unsafe {
Expand Down
4 changes: 2 additions & 2 deletions src/instructions/segmentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ impl Segment for CS {
unsafe {
asm!(
"push {sel}",
"lea {tmp}, [1f + rip]",
"lea {tmp}, [55f + rip]",
"push {tmp}",
"retfq",
"1:",
"55:",
sel = in(reg) u64::from(sel.0),
tmp = lateout(reg) _,
options(preserves_flags),
Expand Down
Loading