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::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 {
43 self.dealloc_frame(PhysAddr::from_usize(start.as_usize() + i * frame_size));
44 }
45 }
46}
47
48pub trait TableMeta: Sync + Send + Clone + Copy + 'static {
49 type P: PageTableEntry;
50
51 const PAGE_SIZE: usize;
53
54 const LEVEL_BITS: &[usize];
56
57 const MAX_BLOCK_LEVEL: usize;
59
60 const STRICT_ADDRESS_WIDTH: bool = false;
62
63 fn canonicalize_vaddr(vaddr: VirtAddr) -> VirtAddr {
66 vaddr
67 }
68
69 fn flush(vaddr: Option<VirtAddr>);
71}
72
73pub trait PageTableEntry: Debug + Sync + Send + Clone + Copy + Sized + 'static {
74 type PteConfig: Copy;
76
77 fn new_page(paddr: PhysAddr, config: Self::PteConfig, is_huge: bool) -> Self;
79
80 fn new_table(paddr: PhysAddr) -> Self;
82
83 fn paddr(&self, is_dir: bool) -> PhysAddr;
88
89 fn config(&self, is_dir: bool) -> Self::PteConfig;
91
92 fn present(&self) -> bool;
96
97 fn huge(&self, is_dir: bool) -> bool;
99
100 fn unused(&self) -> bool;
105
106 fn clear(&mut self);
108}
109
110pub trait PageTableOp: Send + 'static {
111 type PteConfig: Copy;
112
113 fn addr(&self) -> PhysAddr;
114 fn map(&mut self, config: &MapConfig<Self::PteConfig>) -> PagingResult;
115 fn unmap(&mut self, virt_start: VirtAddr, size: usize) -> Result<(), PagingError>;
116}
117
118impl<T: TableMeta, A: FrameAllocator> PageTableOp for PageTable<T, A> {
119 type PteConfig = PteConfigOf<T>;
120
121 fn addr(&self) -> PhysAddr {
122 self.root_paddr()
123 }
124
125 fn map(&mut self, config: &MapConfig<Self::PteConfig>) -> PagingResult {
126 PageTableRef::map(self, config)
127 }
128
129 fn unmap(&mut self, virt_start: VirtAddr, size: usize) -> PagingResult {
130 PageTableRef::unmap(self, virt_start, size)
131 }
132}
133
134impl<T: TableMeta, A: FrameAllocator> PageTableOp for PageTableRef<T, A> {
135 type PteConfig = PteConfigOf<T>;
136
137 fn addr(&self) -> PhysAddr {
138 self.root_paddr()
139 }
140
141 fn map(&mut self, config: &MapConfig<Self::PteConfig>) -> PagingResult {
142 self.map(config)
143 }
144
145 fn unmap(&mut self, virt_start: VirtAddr, size: usize) -> Result<(), PagingError> {
146 self.unmap(virt_start, size)
147 }
148}