Skip to main content

ax_memory_addr/
lib.rs

1#![cfg_attr(not(test), no_std)]
2#![doc = include_str!("../README.md")]
3
4#[cfg(test)]
5extern crate alloc;
6
7mod addr;
8mod iter;
9mod range;
10
11pub use self::{
12    addr::{MemoryAddr, PhysAddr, VirtAddr},
13    iter::{DynPageIter, PageIter},
14    range::{AddrRange, PhysAddrRange, VirtAddrRange},
15};
16
17/// The size of a 4K page (4096 bytes).
18pub const PAGE_SIZE_4K: usize = 0x1000;
19
20/// The size of a 2M page (2097152 bytes).
21pub const PAGE_SIZE_2M: usize = 0x20_0000;
22
23/// The size of a 1G page (1073741824 bytes).
24pub const PAGE_SIZE_1G: usize = 0x4000_0000;
25
26/// A [`PageIter`] for 4K pages.
27pub type PageIter4K<A> = PageIter<PAGE_SIZE_4K, A>;
28
29/// A [`PageIter`] for 2M pages.
30pub type PageIter2M<A> = PageIter<PAGE_SIZE_2M, A>;
31
32/// A [`PageIter`] for 1G pages.
33pub type PageIter1G<A> = PageIter<PAGE_SIZE_1G, A>;
34
35/// Align address downwards.
36///
37/// Returns the greatest `x` with alignment `align` so that `x <= addr`.
38///
39/// The alignment must be a power of two.
40#[inline]
41pub const fn align_down(addr: usize, align: usize) -> usize {
42    addr & !(align - 1)
43}
44
45/// Align address upwards.
46///
47/// Returns the smallest `x` with alignment `align` so that `x >= addr`.
48///
49/// The alignment must be a power of two.
50#[inline]
51pub const fn align_up(addr: usize, align: usize) -> usize {
52    (addr + align - 1) & !(align - 1)
53}
54
55/// Returns the offset of the address within the alignment.
56///
57/// Equivalent to `addr % align`, but the alignment must be a power of two.
58#[inline]
59pub const fn align_offset(addr: usize, align: usize) -> usize {
60    addr & (align - 1)
61}
62
63/// Checks whether the address has the demanded alignment.
64///
65/// Equivalent to `addr % align == 0`, but the alignment must be a power of two.
66#[inline]
67pub const fn is_aligned(addr: usize, align: usize) -> bool {
68    align_offset(addr, align) == 0
69}
70
71/// Align address downwards to 4096 (bytes).
72#[inline]
73pub const fn align_down_4k(addr: usize) -> usize {
74    align_down(addr, PAGE_SIZE_4K)
75}
76
77/// Align address upwards to 4096 (bytes).
78#[inline]
79pub const fn align_up_4k(addr: usize) -> usize {
80    align_up(addr, PAGE_SIZE_4K)
81}
82
83/// Returns the offset of the address within a 4K-sized page.
84#[inline]
85pub const fn align_offset_4k(addr: usize) -> usize {
86    align_offset(addr, PAGE_SIZE_4K)
87}
88
89/// Checks whether the address is 4K-aligned.
90#[inline]
91pub const fn is_aligned_4k(addr: usize) -> bool {
92    is_aligned(addr, PAGE_SIZE_4K)
93}
94
95#[cfg(test)]
96mod tests {
97    use super::*;
98
99    #[test]
100    fn alignment_keeps_zero_and_exact_page_boundaries() {
101        assert_eq!(align_down(0, 4096), 0);
102        assert_eq!(align_up(0, 4096), 0);
103        assert_eq!(align_down(4096, 4096), 4096);
104        assert_eq!(align_up(4096, 4096), 4096);
105        assert_eq!(align_down(4097, 4096), 4096);
106        assert_eq!(align_up(4097, 4096), 8192);
107    }
108}