page_table_generic/
lib.rs1#![no_std]
2
3use core::fmt::Debug;
4
5mod def;
6pub mod frame;
7mod map;
8mod table;
9mod walk;
10
11pub use def::*;
12pub use frame::{DetachedPageTableFrame, Frame};
13pub use map::*;
14pub use table::*;
15pub use walk::*;
16
17pub type PagingResult<T = ()> = Result<T, PagingError>;
18
19pub type PteConfigOf<T> = <<T as TableMeta>::P as PageTableEntry>::PteConfig;
21
22pub trait FrameAllocator: Clone + Sync + Send + 'static {
23 fn alloc_frame(&self) -> Option<PhysAddr>;
24
25 fn dealloc_frame(&self, frame: PhysAddr);
26
27 fn phys_to_virt(&self, paddr: PhysAddr) -> *mut u8;
28
29 fn alloc_frames(&self, frames: usize, _align: usize) -> Option<PhysAddr> {
30 if frames == 1 {
31 self.alloc_frame()
32 } else {
33 None
34 }
35 }
36
37 fn dealloc_frames(&self, start: PhysAddr, frames: usize, frame_size: usize) {
38 if frames == 1 {
39 self.dealloc_frame(start);
40 return;
41 }
42 for i in 0..frames {
48 let Some(offset) = i.checked_mul(frame_size) else {
49 break;
50 };
51 let Some(address) = start.as_usize().checked_add(offset) else {
52 break;
53 };
54 self.dealloc_frame(PhysAddr::from_usize(address));
55 }
56 }
57}
58
59pub trait TableMeta: Sync + Send + Clone + Copy + 'static {
60 type P: PageTableEntry;
61
62 const PAGE_SIZE: usize;
64
65 const LEVEL_BITS: &[usize];
67
68 const MAX_BLOCK_LEVEL: usize;
70
71 const STRICT_ADDRESS_WIDTH: bool = false;
73
74 fn canonicalize_vaddr(vaddr: VirtAddr) -> VirtAddr {
77 vaddr
78 }
79
80 fn flush(vaddr: Option<VirtAddr>);
82}
83
84pub trait PageTableEntry: Debug + Sync + Send + Clone + Copy + Sized + 'static {
85 type PteConfig: Copy;
87
88 fn new_page(paddr: PhysAddr, config: Self::PteConfig, is_huge: bool) -> Self;
90
91 fn new_table(paddr: PhysAddr) -> Self;
93
94 fn paddr(&self, is_dir: bool) -> PhysAddr;
99
100 fn config(&self, is_dir: bool) -> Self::PteConfig;
102
103 fn present(&self) -> bool;
107
108 fn huge(&self, is_dir: bool) -> bool;
114
115 fn unused(&self) -> bool;
120
121 fn clear(&mut self);
123}
124
125pub trait PageTableOp: Send + 'static {
126 type PteConfig: Copy;
127
128 fn addr(&self) -> PhysAddr;
129 fn map(&mut self, config: &MapConfig<Self::PteConfig>) -> PagingResult;
130 fn unmap(&mut self, virt_start: VirtAddr, size: usize) -> Result<(), PagingError>;
131}
132
133impl<T: TableMeta, A: FrameAllocator> PageTableOp for PageTable<T, A> {
134 type PteConfig = PteConfigOf<T>;
135
136 fn addr(&self) -> PhysAddr {
137 self.root_paddr()
138 }
139
140 fn map(&mut self, config: &MapConfig<Self::PteConfig>) -> PagingResult {
141 PageTableRef::map(self, config)
142 }
143
144 fn unmap(&mut self, virt_start: VirtAddr, size: usize) -> PagingResult {
145 PageTableRef::unmap(self, virt_start, size)
146 }
147}
148
149impl<T: TableMeta, A: FrameAllocator> PageTableOp for PageTableRef<T, A> {
150 type PteConfig = PteConfigOf<T>;
151
152 fn addr(&self) -> PhysAddr {
153 self.root_paddr()
154 }
155
156 fn map(&mut self, config: &MapConfig<Self::PteConfig>) -> PagingResult {
157 self.map(config)
158 }
159
160 fn unmap(&mut self, virt_start: VirtAddr, size: usize) -> Result<(), PagingError> {
161 self.unmap(virt_start, size)
162 }
163}