Skip to content

Commit

Permalink
Merge pull request #464 from Freax13/enhancement/inline-step-functions
Browse files Browse the repository at this point in the history
miscellaneous improvements
  • Loading branch information
Freax13 authored Mar 4, 2024
2 parents b62d1d9 + a0f6b62 commit 927f3ac
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 16 deletions.
22 changes: 20 additions & 2 deletions src/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,15 @@ impl VirtAddr {
where
U: Into<u64>,
{
VirtAddr::new_truncate(align_down(self.0, align.into()))
self.align_down_u64(align.into())
}

/// Aligns the virtual 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 {
VirtAddr::new_truncate(align_down(self.0, align))
}

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

/// Checks whether the virtual 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()
}

/// Returns the 12-bit page offset of this virtual address.
Expand Down Expand Up @@ -236,6 +250,7 @@ impl VirtAddr {
}

// FIXME: Move this into the `Step` impl, once `Step` is stabilized.
#[inline]
pub(crate) fn forward_checked_impl(start: Self, count: usize) -> Option<Self> {

Check warning on line 254 in src/addr.rs

View workflow job for this annotation

GitHub Actions / Test MSRV and Stable Features (1.59)

associated function is never used: `forward_checked_impl`

Check warning on line 254 in src/addr.rs

View workflow job for this annotation

GitHub Actions / Test MSRV and Stable Features (1.59)

associated function is never used: `forward_checked_impl`
let offset = u64::try_from(count).ok()?;
if offset > ADDRESS_SPACE_SIZE {
Expand Down Expand Up @@ -343,14 +358,17 @@ impl Sub<VirtAddr> for VirtAddr {

#[cfg(feature = "step_trait")]
impl Step for VirtAddr {
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
Self::steps_between_impl(start, end)
}

#[inline]
fn forward_checked(start: Self, count: usize) -> Option<Self> {
Self::forward_checked_impl(start, count)
}

#[inline]
fn backward_checked(start: Self, count: usize) -> Option<Self> {
let offset = u64::try_from(count).ok()?;
if offset > ADDRESS_SPACE_SIZE {
Expand Down
27 changes: 16 additions & 11 deletions src/structures/paging/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ impl<S: PageSize> Page<S> {
///
/// Returns an error if the address is not correctly aligned (i.e. is not a valid page start).
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn from_start_address(address: VirtAddr) -> Result<Self, AddressNotAligned> {
if !address.is_aligned(S::SIZE) {
if !address.is_aligned_u64(S::SIZE) {
return Err(AddressNotAligned);
}
Ok(Page::containing_address(address))
Expand All @@ -100,9 +101,10 @@ impl<S: PageSize> Page<S> {

/// Returns the page that contains the given virtual address.
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn containing_address(address: VirtAddr) -> Self {
Page {
start_address: address.align_down(S::SIZE),
start_address: address.align_down_u64(S::SIZE),
size: PhantomData,
}
}
Expand Down Expand Up @@ -185,47 +187,50 @@ impl<S: NotGiantPageSize> Page<S> {
impl Page<Size1GiB> {
/// Returns the 1GiB memory page with the specified page table indices.
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn from_page_table_indices_1gib(
p4_index: PageTableIndex,
p3_index: PageTableIndex,
) -> Self {
let mut addr = 0;
addr |= u64::from(p4_index) << 39;
addr |= u64::from(p3_index) << 30;
addr |= p4_index.into_u64() << 39;
addr |= p3_index.into_u64() << 30;
Page::containing_address(VirtAddr::new_truncate(addr))
}
}

impl Page<Size2MiB> {
/// Returns the 2MiB memory page with the specified page table indices.
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn from_page_table_indices_2mib(
p4_index: PageTableIndex,
p3_index: PageTableIndex,
p2_index: PageTableIndex,
) -> Self {
let mut addr = 0;
addr |= u64::from(p4_index) << 39;
addr |= u64::from(p3_index) << 30;
addr |= u64::from(p2_index) << 21;
addr |= p4_index.into_u64() << 39;
addr |= p3_index.into_u64() << 30;
addr |= p2_index.into_u64() << 21;
Page::containing_address(VirtAddr::new_truncate(addr))
}
}

impl Page<Size4KiB> {
/// Returns the 4KiB memory page with the specified page table indices.
#[inline]
#[rustversion::attr(since(1.61), const)]
pub fn from_page_table_indices(
p4_index: PageTableIndex,
p3_index: PageTableIndex,
p2_index: PageTableIndex,
p1_index: PageTableIndex,
) -> Self {
let mut addr = 0;
addr |= u64::from(p4_index) << 39;
addr |= u64::from(p3_index) << 30;
addr |= u64::from(p2_index) << 21;
addr |= u64::from(p1_index) << 12;
addr |= p4_index.into_u64() << 39;
addr |= p3_index.into_u64() << 30;
addr |= p2_index.into_u64() << 21;
addr |= p1_index.into_u64() << 12;
Page::containing_address(VirtAddr::new_truncate(addr))
}

Expand Down
33 changes: 30 additions & 3 deletions src/structures/paging/page_table.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Abstractions for page tables and page table entries.
use core::fmt;
#[cfg(feature = "step_trait")]
use core::iter::Step;
use core::ops::{Index, IndexMut};

use super::{PageSize, PhysFrame, Size4KiB};
Expand Down Expand Up @@ -296,8 +298,8 @@ pub struct PageTableIndex(u16);
impl PageTableIndex {
/// Creates a new index from the given `u16`. Panics if the given value is >=512.
#[inline]
pub fn new(index: u16) -> Self {
assert!(usize::from(index) < ENTRY_COUNT);
pub const fn new(index: u16) -> Self {
assert!((index as usize) < ENTRY_COUNT);
Self(index)
}

Expand All @@ -306,6 +308,11 @@ impl PageTableIndex {
pub const fn new_truncate(index: u16) -> Self {
Self(index % ENTRY_COUNT as u16)
}

#[inline]
pub(crate) const fn into_u64(self) -> u64 {
self.0 as u64
}
}

impl From<PageTableIndex> for u16 {
Expand All @@ -325,7 +332,7 @@ impl From<PageTableIndex> for u32 {
impl From<PageTableIndex> for u64 {
#[inline]
fn from(index: PageTableIndex) -> Self {
u64::from(index.0)
index.into_u64()
}
}

Expand All @@ -336,6 +343,26 @@ impl From<PageTableIndex> for usize {
}
}

#[cfg(feature = "step_trait")]
impl Step for PageTableIndex {
#[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
end.0.checked_sub(start.0).map(usize::from)
}

#[inline]
fn forward_checked(start: Self, count: usize) -> Option<Self> {
let idx = usize::from(start).checked_add(count)?;
(idx < ENTRY_COUNT).then(|| Self::new(idx as u16))
}

#[inline]
fn backward_checked(start: Self, count: usize) -> Option<Self> {
let idx = usize::from(start).checked_sub(count)?;
Some(Self::new(idx as u16))
}
}

/// A 12-bit offset into a 4KiB Page.
///
/// This type is returned by the `VirtAddr::page_offset` method.
Expand Down

0 comments on commit 927f3ac

Please sign in to comment.