Skip to main content

page_table_generic/
map.rs

1use crate::{
2    FrameAllocator, PageTableEntry, PagingError, PagingResult, PhysAddr, PteConfigOf, TableMeta,
3    VirtAddr, frame::Frame,
4};
5
6/// 页表映射配置
7#[repr(C)]
8#[derive(Clone, Copy)]
9pub struct MapConfig<C> {
10    pub vaddr: VirtAddr,
11    pub paddr: PhysAddr,
12    pub size: usize,
13    /// Page Table Entry 配置模板
14    ///
15    /// 所有页表项将使用此配置创建(除了物理地址位)
16    pub pte: C,
17    pub allow_huge: bool,
18    pub flush: bool,
19}
20
21/// 内部映射递归配置
22#[derive(Clone, Copy)]
23pub struct MapRecursiveConfig<C> {
24    pub start_vaddr: VirtAddr,
25    pub start_paddr: PhysAddr,
26    pub end_vaddr: VirtAddr,
27    pub level: usize,
28    pub allow_huge: bool,
29    pub flush: bool,
30    pub pte_template: C,
31}
32
33/// 取消映射配置
34#[derive(Clone, Copy)]
35pub struct UnmapConfig {
36    pub start_vaddr: VirtAddr,
37    pub size: usize,
38    pub flush: bool,
39}
40
41/// 内部取消映射递归配置
42#[derive(Clone, Copy)]
43pub struct UnmapRecursiveConfig {
44    pub start_vaddr: VirtAddr,
45    pub end_vaddr: VirtAddr,
46    pub level: usize,
47    pub flush: bool,
48}
49
50impl<C> core::fmt::Debug for MapConfig<C> {
51    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
52        f.debug_struct("MapConfig")
53            .field("vaddr", &format_args!("{:#x}", self.vaddr.as_usize()))
54            .field("paddr", &format_args!("{:#x}", self.paddr.as_usize()))
55            .field("size", &format_args!("{:#x}", self.size))
56            .field("allow_huge", &self.allow_huge)
57            .field("flush", &self.flush)
58            .finish()
59    }
60}
61
62impl<T, A> Frame<T, A>
63where
64    T: TableMeta,
65    A: FrameAllocator,
66{
67    /// 递归映射的核心实现
68    pub fn map_range_recursive(
69        &mut self,
70        config: MapRecursiveConfig<PteConfigOf<T>>,
71    ) -> PagingResult<()> {
72        let mut vaddr = config.start_vaddr;
73        let mut paddr = config.start_paddr;
74
75        while vaddr < config.end_vaddr {
76            let index = Self::virt_to_index(vaddr, config.level);
77            let level_size = Self::level_size(config.level);
78            let remaining_size = config.end_vaddr - vaddr;
79
80            // 检查是否可以使用大页映射
81            if config.allow_huge
82                && config.level > 1
83                && config.level <= T::MAX_BLOCK_LEVEL
84                && level_size <= remaining_size
85                && vaddr.as_usize().is_multiple_of(level_size)
86                && paddr.as_usize().is_multiple_of(level_size)
87            {
88                // 创建大页映射
89                let entries = self.as_slice_mut();
90                let pte_ref = &mut entries[index];
91                if !pte_ref.unused() {
92                    return Err(PagingError::mapping_conflict(vaddr, paddr));
93                }
94                *pte_ref = T::P::new_page(paddr, config.pte_template, true);
95
96                // 如果需要刷新TLB,立即执行
97                if config.flush {
98                    T::flush(Some(vaddr));
99                }
100
101                vaddr += level_size;
102                paddr += level_size;
103                continue;
104            }
105
106            // 如果到达页表级别,进行普通页映射
107            if config.level == 1 {
108                // 创建普通页面映射
109                let entries = self.as_slice_mut();
110                let pte_ref = &mut entries[index];
111                if !pte_ref.unused() {
112                    return Err(PagingError::mapping_conflict(vaddr, paddr));
113                }
114
115                *pte_ref = T::P::new_page(paddr, config.pte_template, false);
116
117                // 如果需要刷新TLB,立即执行
118                if config.flush {
119                    T::flush(Some(vaddr));
120                }
121
122                vaddr += T::PAGE_SIZE;
123                paddr += T::PAGE_SIZE;
124                continue;
125            }
126
127            // 检查当前页表项状态并决定如何处理
128            let allocator = self.allocator.clone();
129            let current_pte = self.as_slice()[index];
130
131            let child_frame = if !current_pte.unused() {
132                if current_pte.huge(true) {
133                    return Err(PagingError::mapping_conflict(
134                        vaddr,
135                        current_pte.paddr(true),
136                    ));
137                }
138                if !current_pte.present() {
139                    return Err(PagingError::hierarchy_error(
140                        "Non-present intermediate entry is not a leaf",
141                    ));
142                }
143
144                // 子页表已存在,获取它
145                Frame::from_paddr(current_pte.paddr(true), allocator)
146            } else {
147                // 需要创建新的子页表
148                let new_frame = Frame::<T, A>::new(allocator)?;
149                let new_frame_paddr = new_frame.paddr;
150
151                // 链接子页表 - 子页表指针必须是 NON_BLOCK(不是大页)
152                let entries = self.as_slice_mut();
153                let pte_ref = &mut entries[index];
154                *pte_ref = T::P::new_table(new_frame_paddr);
155
156                new_frame
157            };
158
159            // 计算当前页表条目对应的范围结束地址
160            // 使用 saturating 操作防止溢出,同时确保不超过地址空间最大值
161            let current_entry_end = (vaddr.as_usize() / level_size)
162                .saturating_add(1)
163                .saturating_mul(level_size);
164            let next_level_vaddr =
165                VirtAddr::from_usize(current_entry_end.min(config.end_vaddr.as_usize()));
166            let mut child_frame = child_frame;
167            let child_config = MapRecursiveConfig {
168                start_vaddr: vaddr,
169                start_paddr: paddr,
170                end_vaddr: next_level_vaddr,
171                level: config.level - 1,
172                allow_huge: config.allow_huge,
173                flush: config.flush,
174                pte_template: config.pte_template,
175            };
176            child_frame.map_range_recursive(child_config)?;
177
178            // 计算本轮映射的虚拟地址范围
179            let mapped_size = next_level_vaddr - vaddr;
180            vaddr = next_level_vaddr;
181            paddr += mapped_size;
182        }
183
184        Ok(())
185    }
186
187    /// 递归取消映射的核心实现
188    ///
189    /// 返回值:bool 表示此帧是否为空(所有页表项都无效),可以回收
190    pub fn unmap_range_recursive(&mut self, config: UnmapRecursiveConfig) -> PagingResult<bool> {
191        let mut vaddr = config.start_vaddr;
192        let mut can_reclaim = true;
193        let allocator = self.allocator.clone();
194
195        while vaddr < config.end_vaddr {
196            let index = Self::virt_to_index(vaddr, config.level);
197            let level_size = Self::level_size(config.level);
198            let remaining_size = config.end_vaddr - vaddr;
199
200            let entries = self.as_slice_mut();
201            let pte_ref = &mut entries[index];
202
203            // An invalid leaf can still retain its physical address. Treat it
204            // as occupied state and clear it instead of skipping it.
205            if pte_ref.unused() {
206                vaddr += level_size.min(remaining_size);
207                continue;
208            }
209
210            if !pte_ref.present() {
211                pte_ref.clear();
212                if config.flush {
213                    T::flush(Some(vaddr));
214                }
215                vaddr += level_size.min(remaining_size);
216                continue;
217            }
218
219            // 如果是叶子级别或者是大页,直接清除
220            let is_huge = pte_ref.huge(config.level > 1);
221            if config.level == 1 || is_huge {
222                // 清除页表项
223                pte_ref.clear();
224
225                // 刷新TLB
226                if config.flush {
227                    T::flush(Some(vaddr));
228                }
229
230                vaddr += if is_huge { level_size } else { T::PAGE_SIZE };
231                continue;
232            }
233
234            // 中间级别:递归处理子页表
235            // 需要在修改pte_ref之前获取所需信息
236            let child_paddr = pte_ref.paddr(true);
237
238            // 计算当前页表条目对应的范围结束地址
239            let current_entry_end = ((vaddr.as_usize() / level_size) + 1) * level_size;
240            let next_level_vaddr =
241                VirtAddr::from_usize(current_entry_end.min(config.end_vaddr.as_usize()));
242
243            {
244                let mut child_frame: Frame<T, A> =
245                    Frame::from_paddr(child_paddr, allocator.clone());
246                let child_config = UnmapRecursiveConfig {
247                    start_vaddr: vaddr,
248                    end_vaddr: next_level_vaddr,
249                    level: config.level - 1,
250                    flush: config.flush,
251                };
252
253                // 递归取消子页表映射
254                let child_can_reclaim = child_frame.unmap_range_recursive(child_config)?;
255
256                if child_can_reclaim {
257                    // 子页表完全为空,可以回收
258                    // 清除指向子页表的PTE
259                    pte_ref.clear();
260                    allocator.dealloc_frame(child_paddr);
261                } else {
262                    // 子页表仍有有效映射,不能回收
263                    can_reclaim = false;
264                }
265            }
266
267            vaddr = next_level_vaddr;
268        }
269
270        // 检查此帧是否完全为空
271        if can_reclaim {
272            can_reclaim = self.is_frame_empty();
273        }
274
275        Ok(can_reclaim)
276    }
277
278    /// 检查页表帧是否全为空(所有页表项都未使用)
279    fn is_frame_empty(&self) -> bool {
280        let entries = self.as_slice();
281        for pte in entries {
282            if !pte.unused() {
283                return false;
284            }
285        }
286        true
287    }
288}