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.2.1"
version = "0.3.0"
edition = "2024"

[dependencies]
Expand Down
6 changes: 3 additions & 3 deletions src/address/frame.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
address::{Address, AddressKind, NonCanonicalError, Physical},
constants::{is_physical_address_canonical, page_mask, page_shift, truncate_physical_address},
constants::{is_physical_address_canonical, page_bits, page_mask, truncate_physical_address},
};

pub struct Frame;
Expand Down Expand Up @@ -78,7 +78,7 @@ impl Address<Frame> {
///
/// - [`NonCanonicalError`] if `index` would create a non-canonical address.
pub fn from_index(index: usize) -> Result<Self, NonCanonicalError> {
let physical_address = index << page_shift().get();
let physical_address = index << page_bits().get();

if is_physical_address_canonical(physical_address) {
Ok(Self(physical_address))
Expand All @@ -90,7 +90,7 @@ impl Address<Frame> {
/// Gets the index of the frame this address points to.
#[must_use]
pub fn index(&self) -> usize {
self.0 >> page_shift().get()
self.0 >> page_bits().get()
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/address/page.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
address::{Address, AddressKind, NonCanonicalError, Virtual},
constants::{
is_virtual_address_canonical, page_mask, page_shift, page_size, truncate_virtual_address,
is_virtual_address_canonical, page_bits, page_mask, page_size, truncate_virtual_address,
},
};

Expand Down Expand Up @@ -80,7 +80,7 @@ impl Address<Page> {
///
/// - [`NonCanonicalError`] if `index` would create a non-canonical address.
pub fn from_index(index: usize) -> Result<Self, NonCanonicalError> {
let virtual_address = index << page_shift().get();
let virtual_address = index << page_bits().get();

if is_virtual_address_canonical(virtual_address) {
Ok(Self(virtual_address))
Expand All @@ -92,7 +92,7 @@ impl Address<Page> {
/// Gets the index of the page this address points to.
#[must_use]
pub fn index(&self) -> usize {
self.0 >> page_shift().get()
self.0 >> page_bits().get()
}
}

Expand Down
74 changes: 42 additions & 32 deletions src/constants/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,40 @@ use core::num::NonZero;

/// Bit shift required to offset page indexes.
#[must_use]
pub const fn page_shift() -> NonZero<u32> {
pub const fn page_bits() -> NonZero<u32> {
NonZero::<u32>::new(12).unwrap()
}

/// Bit shift required to offset mega page indexes.
/// Bit shift required to offset large page indexes.
#[must_use]
pub const fn mega_page_shift() -> NonZero<u32> {
page_shift().checked_add(table_index_shift().get()).unwrap()
pub const fn large_page_bits() -> NonZero<u32> {
page_bits().checked_add(table_index_bits().get()).unwrap()
}

/// Bit shift required to offset giga page indexes.
/// Bit shift required to offset huge page indexes.
#[must_use]
pub const fn giga_page_shift() -> NonZero<u32> {
mega_page_shift()
.checked_add(table_index_shift().get())
pub const fn huge_page_bits() -> NonZero<u32> {
large_page_bits()
.checked_add(table_index_bits().get())
.unwrap()
}

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

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

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

/// Bit-mask of non-index page bytes.
Expand All @@ -45,28 +45,28 @@ pub const fn page_mask() -> usize {
page_size().checked_sub(1).unwrap()
}

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

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

/// Shift (in bits) of a page table index.
#[must_use]
pub const fn table_index_shift() -> NonZero<u32> {
pub const fn table_index_bits() -> NonZero<u32> {
NonZero::<u32>::new(9).unwrap()
}

/// Size (in bytes) of a page table index.
#[must_use]
pub const fn table_index_size() -> usize {
1 << table_index_shift().get()
1 << table_index_bits().get()
}

/// Bit-mask of a page table index.
Expand All @@ -75,11 +75,24 @@ pub const fn table_index_mask() -> usize {
table_index_size().checked_sub(1).unwrap()
}

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

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

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

/// Checks if the provided `physical_address` is canonical.
#[must_use]
pub const fn is_physical_address_canonical(physical_address: usize) -> bool {
Expand All @@ -88,20 +101,17 @@ pub const fn is_physical_address_canonical(physical_address: usize) -> bool {

/// Bit-shift to reach non-canonical bits of a virtual address.
#[must_use]
pub fn virtual_address_noncanonical_shift() -> NonZero<u32> {
let table_indexes_shift = table_index_shift().checked_mul(get_paging_depth()).unwrap();
let total_shift = table_indexes_shift.checked_add(page_shift().get()).unwrap();
pub fn virtual_address_bits() -> NonZero<u32> {
let table_indexes_shift = table_index_bits().checked_mul(get_paging_depth()).unwrap();
let total_shift = table_indexes_shift.checked_add(page_bits().get()).unwrap();

NonZero::<u32>::new(total_shift.get()).unwrap()
}

/// Checks whether a provided address has only the canonical virtual bits.
#[must_use]
pub fn is_virtual_address_canonical(virtual_address: usize) -> bool {
let sign_extension_check_shift = virtual_address_noncanonical_shift()
.get()
.checked_sub(1)
.unwrap();
let sign_extension_check_shift = virtual_address_bits().get().checked_sub(1).unwrap();

matches!(virtual_address >> sign_extension_check_shift, 0 | 0x1FFFF)
}
Expand All @@ -114,6 +124,6 @@ pub fn truncate_physical_address(address: usize) -> usize {
#[must_use]
#[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
pub fn truncate_virtual_address(address: usize) -> usize {
let sign_extension_shift = usize::BITS - virtual_address_noncanonical_shift().get();
let sign_extension_shift = usize::BITS - virtual_address_bits().get();
(((address << sign_extension_shift) as isize) >> sign_extension_shift) as usize
}