ax_page_table_multiarch/
lib.rs1#![cfg_attr(not(test), no_std)]
2#![cfg_attr(doc, feature(doc_cfg))]
3#![doc = include_str!("../README.md")]
4
5#[macro_use]
6extern crate log;
7
8mod arch;
9#[cfg(any(target_pointer_width = "32", doc, docsrs))]
10mod bits32;
11#[cfg(any(target_pointer_width = "64", doc, docsrs))]
12mod bits64;
13
14use core::fmt::Debug;
15
16use arrayvec::ArrayVec;
17use ax_memory_addr::{MemoryAddr, PAGE_SIZE_4K, PhysAddr, VirtAddr};
18#[doc(no_inline)]
19pub use ax_page_table_entry::{GenericPTE, MappingFlags};
20
21#[cfg(any(target_pointer_width = "32", doc, docsrs))]
22pub use self::{
23 arch::*,
24 bits32::{PageTable32, PageTable32Cursor},
25};
26#[cfg(any(target_pointer_width = "64", doc, docsrs))]
27pub use self::{
28 arch::*,
29 bits64::{PageTable64, PageTable64Cursor},
30};
31
32#[derive(Debug, PartialEq, Clone, Copy)]
34pub enum PagingError {
35 NoMemory,
37 NotAligned,
39 NotMapped,
41 AlreadyMapped,
43 MappedToHugePage,
46}
47
48#[cfg(feature = "ax-errno")]
49impl From<PagingError> for ax_errno::AxErrorKind {
50 fn from(value: PagingError) -> Self {
51 match value {
52 PagingError::NoMemory => ax_errno::AxErrorKind::NoMemory,
53 _ => ax_errno::AxErrorKind::InvalidInput,
54 }
55 }
56}
57
58pub type PagingResult<T = ()> = Result<T, PagingError>;
60
61pub trait PagingMetaData: Sync + Send {
64 const LEVELS: usize;
66 const PA_MAX_BITS: usize;
68 const VA_MAX_BITS: usize;
70
71 const PA_MAX_ADDR: usize = (1 << Self::PA_MAX_BITS) - 1;
73
74 type VirtAddr: MemoryAddr;
79 #[inline]
83 fn paddr_is_valid(paddr: usize) -> bool {
84 paddr <= Self::PA_MAX_ADDR }
86
87 #[inline]
89 fn vaddr_is_valid(vaddr: usize) -> bool {
90 let top_mask = usize::MAX << (Self::VA_MAX_BITS - 1);
92 (vaddr & top_mask) == 0 || (vaddr & top_mask) == top_mask
93 }
94
95 fn flush_tlb(vaddr: Option<Self::VirtAddr>);
100}
101
102pub trait PagingHandler: Sized {
105 fn alloc_frame() -> Option<PhysAddr> {
107 Self::alloc_frames(1, PAGE_SIZE_4K)
108 }
109 fn alloc_frames(num: usize, align: usize) -> Option<PhysAddr>;
113 fn dealloc_frame(paddr: PhysAddr) {
115 Self::dealloc_frames(paddr, 1)
116 }
117 fn dealloc_frames(paddr: PhysAddr, num: usize);
120 fn phys_to_virt(paddr: PhysAddr) -> VirtAddr;
125}
126
127#[repr(usize)]
129#[derive(Debug, Copy, Clone, Eq, PartialEq)]
130pub enum PageSize {
131 Size4K = 0x1000,
133 Size1M = 0x10_0000,
135 Size2M = 0x20_0000,
137 Size1G = 0x4000_0000,
139}
140
141impl PageSize {
142 pub const fn is_huge(self) -> bool {
144 matches!(self, Self::Size1G | Self::Size2M | Self::Size1M)
145 }
146
147 pub const fn is_aligned(self, addr_or_size: usize) -> bool {
149 ax_memory_addr::is_aligned(addr_or_size, self as usize)
150 }
151
152 pub const fn align_offset(self, addr: usize) -> usize {
154 ax_memory_addr::align_offset(addr, self as usize)
155 }
156}
157
158impl From<PageSize> for usize {
159 #[inline]
160 fn from(size: PageSize) -> usize {
161 size as usize
162 }
163}
164
165const SMALL_FLUSH_THRESHOLD: usize = 32;
167
168enum TlbFlusher<M: PagingMetaData> {
169 None,
170 Array(ArrayVec<M::VirtAddr, SMALL_FLUSH_THRESHOLD>),
171 Full,
172}