Skip to content
This repository was archived by the owner on Apr 24, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "libsys"
version = "0.3.1"
version = "0.3.2"
edition = "2024"

[dependencies]
Expand Down
19 changes: 11 additions & 8 deletions src/constants/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ pub use x86_64::*;
#[cfg(not(test))]
static PAGING_DEPTH: spin::Once<NonZero<u32>> = spin::Once::new();

pub fn get_paging_depth() -> NonZero<u32> {
cfg_select! {
// Safety: Value is non-zero.
test => { unsafe { NonZero::new_unchecked(4) } }
_ => { *PAGING_DEPTH.get().expect("paging depth has not been set") }
}
}

/// Sets the current paging depth.
///
/// # Safety
Expand All @@ -33,3 +25,14 @@ pub fn get_paging_depth() -> NonZero<u32> {
pub unsafe fn set_paging_depth(paging_depth: NonZero<u32>) {
PAGING_DEPTH.call_once(|| paging_depth);
}

pub fn get_paging_depth() -> NonZero<u32> {
cfg_select! {
test => {
// Safety: Value is non-zero.
unsafe { NonZero::new_unchecked(4) }
}

_ => { *PAGING_DEPTH.get().expect("paging depth has not been set") }
}
}
37 changes: 21 additions & 16 deletions src/constants/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,65 @@ use core::num::NonZero;
/// Bit shift required to offset page indexes.
#[must_use]
pub const fn page_bits() -> NonZero<u32> {
NonZero::<u32>::new(12).unwrap()
// Safety: Value is non-zero.
unsafe { NonZero::<u32>::new_unchecked(12) }
}

/// Bit shift required to offset large page indexes.
#[must_use]
pub const fn large_page_bits() -> NonZero<u32> {
page_bits().checked_add(table_index_bits().get()).unwrap()
// Safety: Value is non-zero.
unsafe { NonZero::<u32>::new_unchecked(page_bits().get() + table_index_bits().get()) }
}

/// Bit shift required to offset huge page indexes.
#[must_use]
pub const fn huge_page_bits() -> NonZero<u32> {
large_page_bits()
.checked_add(table_index_bits().get())
.unwrap()
// Safety: Value is non-zero.
unsafe { NonZero::<u32>::new_unchecked(large_page_bits().get() + table_index_bits().get()) }
}

/// The size of a page in bytes.
#[must_use]
pub const fn page_size() -> usize {
1usize.checked_shl(page_bits().get()).unwrap()
1 << page_bits().get()
}

/// The size of a large page in bytes.
#[must_use]
pub const fn large_page_size() -> usize {
1usize.checked_shl(large_page_bits().get()).unwrap()
1 << large_page_bits().get()
}

/// The size of a huge page in bytes.
#[must_use]
pub const fn huge_page_size() -> usize {
1usize.checked_shl(huge_page_bits().get()).unwrap()
1 << huge_page_bits().get()
}

/// Bit-mask of non-index page bytes.
#[must_use]
pub const fn page_mask() -> usize {
page_size().checked_sub(1).unwrap()
page_size() - 1
}

/// Bit-mask of non-index large page bytes.
#[must_use]
pub const fn large_page_mask() -> usize {
large_page_size().checked_sub(1).unwrap()
large_page_size() - 1
}

/// Bit-mask of non-index huge page bytes.
#[must_use]
pub const fn huge_page_mask() -> usize {
huge_page_size().checked_sub(1).unwrap()
huge_page_size() - 1
}

/// Shift (in bits) of a page table index.
#[must_use]
pub const fn table_index_bits() -> NonZero<u32> {
NonZero::<u32>::new(9).unwrap()
// Safety: Value is non-zero.
unsafe { NonZero::<u32>::new_unchecked(9) }
}

/// Size (in bytes) of a page table index.
Expand All @@ -72,25 +74,26 @@ pub const fn table_index_size() -> usize {
/// Bit-mask of a page table index.
#[must_use]
pub const fn table_index_mask() -> usize {
table_index_size().checked_sub(1).unwrap()
table_index_size() - 1
}

/// Number of bits in a canonical physical address.
#[must_use]
pub const fn physical_address_bits() -> NonZero<u32> {
NonZero::<u32>::new(52).unwrap()
// Safety: Value is non-zero.
unsafe { NonZero::<u32>::new_unchecked(52) }
}

/// The maximum physical address size (in bytes).
#[must_use]
pub const fn physical_address_size() -> usize {
1usize.checked_shl(physical_address_bits().get()).unwrap()
1 << physical_address_bits().get()
}

/// Bit-mask of canonical physical bits.
#[must_use]
pub const fn physical_address_mask() -> usize {
physical_address_size().checked_sub(1).unwrap()
physical_address_size() - 1
}

/// Checks if the provided `physical_address` is canonical.
Expand All @@ -116,11 +119,13 @@ pub fn is_virtual_address_canonical(virtual_address: usize) -> bool {
matches!(virtual_address >> sign_extension_check_shift, 0 | 0x1FFFF)
}

/// Truncates all non-canonical physical bits from an address.
#[must_use]
pub fn truncate_physical_address(address: usize) -> usize {
address & physical_address_mask()
}

/// Truncates all non-canonical virtual bits from an address.
#[must_use]
#[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
pub fn truncate_virtual_address(address: usize) -> usize {
Expand Down