os/mm/memory_space/
mapping_area.rs

1use alloc::collections::btree_map::BTreeMap;
2use core::cmp::min;
3
4use crate::arch::mm::{paddr_to_vaddr, vaddr_to_paddr};
5use crate::config::PAGE_SIZE;
6use crate::mm::address::{Paddr, PageNum, Ppn, UsizeConvert, Vpn, VpnRange};
7use crate::mm::frame_allocator::{TrackedFrames, alloc_frame};
8use crate::mm::memory_space::MmapFile;
9use crate::mm::page_table::{
10    self, ActivePageTableInner, PageSize, PageTableInner, UniversalPTEFlag,
11};
12use crate::uapi::mm::MapFlags;
13use crate::{pr_err, pr_warn};
14
15/// 映射策略类型
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum MapType {
18    /// 直接映射(虚拟地址 = 物理地址 + VIRTUAL_BASE)
19    Direct,
20    /// 帧映射(从帧分配器分配)
21    Framed,
22}
23
24/// 内存区域的类型
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum AreaType {
27    KernelText,   // 内核代码段
28    KernelRodata, // 内核只读数据段
29    KernelData,   // 内核数据段
30    KernelStack,  // 内核栈
31    KernelBss,    // 内核 BSS 段
32    KernelHeap,   // 内核堆
33    KernelMmio,   // 内核内存映射 I/O
34    UserText,     // 用户代码段
35    UserRodata,   // 用户只读数据段
36    UserData,     // 用户数据段
37    UserBss,      // 用户 BSS 段
38    UserStack,    // 用户栈
39    UserHeap,     // 用户堆
40    UserMmap,     // 用户 mmap 匿名映射
41}
42
43/// 内存空间中的一个内存映射区域
44#[derive(Debug)]
45pub struct MappingArea {
46    /// 此映射区域的虚拟页号范围
47    ///
48    /// 现已移除大页映射,不用在意
49    /// ~~ 注意!~~
50    ///
51    /// ~~ 创建后不要更改它,~~
52    /// ~~ 不要用它来映射或解除映射页~~
53    vpn_range: VpnRange,
54
55    /// 此映射区域的类型
56    area_type: AreaType,
57
58    /// 映射策略类型
59    map_type: MapType,
60
61    /// 此映射区域的权限(使用 UniversalPTEFlag 以提高性能)
62    permission: UniversalPTEFlag,
63
64    /// 用于帧映射区域的跟踪帧
65    frames: BTreeMap<Vpn, TrackedFrames>,
66
67    /// 文件映射信息(如果是文件映射)
68    file: Option<MmapFile>,
69}
70
71impl MappingArea {
72    pub fn vpn_range(&self) -> VpnRange {
73        self.vpn_range
74    }
75
76    pub fn permission(&self) -> UniversalPTEFlag {
77        self.permission.clone()
78    }
79
80    pub fn set_permission(&mut self, perm: UniversalPTEFlag) {
81        self.permission = perm;
82    }
83
84    pub fn map_type(&self) -> MapType {
85        self.map_type
86    }
87
88    pub fn area_type(&self) -> AreaType {
89        self.area_type
90    }
91
92    /// 获取虚拟页号(VPN)对应的物理页号(PPN)(如果已映射)
93    pub fn get_ppn(&self, vpn: Vpn) -> Option<crate::mm::address::Ppn> {
94        self.frames.get(&vpn).map(|tracked| match tracked {
95            TrackedFrames::Single(frame) => frame.ppn(),
96            TrackedFrames::Multiple(frames) => frames.first().map(|f| f.ppn()).unwrap(),
97            TrackedFrames::Contiguous(_) => {
98                // 当前简化的 4K-only 实现不支持连续帧
99                panic!("当前实现不支持连续帧");
100            }
101        })
102    }
103
104    pub fn new(
105        vpn_range: VpnRange,
106        area_type: AreaType,
107        map_type: MapType,
108        permission: UniversalPTEFlag,
109        file: Option<MmapFile>,
110    ) -> Self {
111        MappingArea {
112            vpn_range,
113            area_type,
114            map_type,
115            permission,
116            frames: BTreeMap::new(),
117            file,
118        }
119    }
120
121    /// 映射单个虚拟页到物理页
122    pub fn map_one(
123        &mut self,
124        page_table: &mut ActivePageTableInner,
125        vpn: Vpn,
126    ) -> Result<(), page_table::PagingError> {
127        let ppn = match self.map_type {
128            MapType::Direct => {
129                // 对于直接映射,VPN 等于 PPN + 偏移量
130                let vaddr = vpn.start_addr();
131                let paddr = unsafe { vaddr_to_paddr(vaddr.as_usize()) };
132                Ppn::from_addr_floor(Paddr::from_usize(paddr))
133            }
134            MapType::Framed => {
135                // 分配一个新的帧
136                let frame = alloc_frame().ok_or(page_table::PagingError::FrameAllocFailed)?;
137                let ppn = frame.ppn();
138                self.frames.insert(vpn, TrackedFrames::Single(frame));
139                ppn
140            }
141        };
142
143        page_table.map(vpn, ppn, PageSize::Size4K, self.permission.clone())?;
144        Ok(())
145    }
146
147    /// 映射此映射区域中的所有页
148    pub fn map(
149        &mut self,
150        page_table: &mut ActivePageTableInner,
151    ) -> Result<(), page_table::PagingError> {
152        for vpn in self.vpn_range {
153            self.map_one(page_table, vpn)?;
154        }
155        Ok(())
156    }
157
158    /// 解除映射单个虚拟页
159    pub fn unmap_one(
160        &mut self,
161        page_table: &mut ActivePageTableInner,
162        vpn: Vpn,
163    ) -> Result<(), page_table::PagingError> {
164        page_table.unmap(vpn)?;
165
166        // 对于帧映射,移除帧跟踪器
167        if self.map_type == MapType::Framed {
168            self.frames.remove(&vpn);
169        }
170        Ok(())
171    }
172
173    /// 解除映射此映射区域中的所有页
174    pub fn unmap(
175        &mut self,
176        page_table: &mut ActivePageTableInner,
177    ) -> Result<(), page_table::PagingError> {
178        for vpn in self.vpn_range {
179            self.unmap_one(page_table, vpn)?;
180        }
181        Ok(())
182    }
183
184    /// 复制数据到已映射的区域
185    pub fn copy_data(&self, page_table: &mut ActivePageTableInner, data: &[u8], offset: usize) {
186        let mut copied = 0;
187        let total_len = data.len();
188
189        for (i, vpn) in self.vpn_range.iter().enumerate() {
190            if copied >= total_len {
191                break;
192            }
193
194            // 获取此 VPN 对应的物理地址
195            let vaddr = vpn.start_addr();
196            let paddr = page_table.translate(vaddr).expect("无法转换虚拟地址");
197            let paddr = if i == 0 {
198                paddr.as_usize().checked_add(offset).unwrap()
199            } else {
200                paddr.as_usize()
201            };
202
203            let page_capacity = if i == 0 {
204                crate::config::PAGE_SIZE - offset
205            } else {
206                crate::config::PAGE_SIZE
207            };
208
209            // 计算此页需要复制多少数据
210            let remaining = total_len - copied;
211            let to_copy = min(remaining, page_capacity);
212
213            // 复制数据到物理页
214            unsafe {
215                let dst_va = paddr_to_vaddr(paddr);
216                let dst = dst_va as *mut u8;
217                let src = data.as_ptr().add(copied);
218                core::ptr::copy_nonoverlapping(src, dst, to_copy);
219            }
220
221            copied += to_copy;
222        }
223    }
224
225    /// 克隆元数据,但不克隆帧
226    /// 用于写时复制(COW)的 fork
227    pub fn clone_metadata(&self) -> Self {
228        MappingArea {
229            vpn_range: self.vpn_range,
230            area_type: self.area_type,
231            map_type: self.map_type,
232            permission: self.permission.clone(),
233            frames: BTreeMap::new(), // 不克隆帧
234            // fork 时复制文件映射信息(MAP_SHARED 和 MAP_PRIVATE 都需要)
235            file: self.file.as_ref().map(|f| MmapFile {
236                file: f.file.clone(),
237                offset: f.offset,
238                len: f.len,
239                prot: f.prot,
240                flags: f.flags,
241            }),
242        }
243    }
244
245    /// 克隆映射区域及其数据
246    /// 仅支持帧映射区域
247    pub fn clone_with_data(
248        &self,
249        page_table: &mut ActivePageTableInner,
250    ) -> Result<Self, page_table::PagingError> {
251        let mut new_area = self.clone_metadata();
252        if self.map_type != MapType::Framed {
253            return Err(page_table::PagingError::UnsupportedMapType);
254        }
255
256        // 遍历原 area 的 frames BTreeMap
257        for (vpn, tracked_frames) in &self.frames {
258            match tracked_frames {
259                TrackedFrames::Single(frame) => {
260                    // 复制单个 4K 页
261                    let new_frame =
262                        alloc_frame().ok_or(page_table::PagingError::FrameAllocFailed)?;
263
264                    let new_ppn = new_frame.ppn();
265                    let src_ppn = frame.ppn();
266
267                    // 复制数据到新帧
268                    unsafe {
269                        let src_va = paddr_to_vaddr(src_ppn.start_addr().as_usize());
270                        let dst_va = paddr_to_vaddr(new_ppn.start_addr().as_usize());
271
272                        core::ptr::copy_nonoverlapping(
273                            src_va as *const u8,
274                            dst_va as *mut u8,
275                            crate::config::PAGE_SIZE,
276                        );
277                    }
278
279                    // 建立页表映射
280                    page_table.map(*vpn, new_ppn, PageSize::Size4K, self.permission.clone())?;
281
282                    new_area
283                        .frames
284                        .insert(*vpn, TrackedFrames::Single(new_frame));
285                }
286                TrackedFrames::Multiple(frames) => {
287                    // 复制多个不连续的页
288                    let mut new_frames = alloc::vec::Vec::new();
289
290                    for frame in frames.iter() {
291                        let new_frame =
292                            alloc_frame().ok_or(page_table::PagingError::FrameAllocFailed)?;
293                        let new_ppn = new_frame.ppn();
294                        let src_ppn = frame.ppn();
295
296                        // 复制数据到新帧
297                        unsafe {
298                            let src_va = paddr_to_vaddr(src_ppn.start_addr().as_usize());
299                            let dst_va = paddr_to_vaddr(new_ppn.start_addr().as_usize());
300
301                            core::ptr::copy_nonoverlapping(
302                                src_va as *const u8,
303                                dst_va as *mut u8,
304                                crate::config::PAGE_SIZE,
305                            );
306                        }
307
308                        // 建立页表映射
309                        page_table.map(*vpn, new_ppn, PageSize::Size4K, self.permission.clone())?;
310
311                        new_frames.push(new_frame);
312                    }
313
314                    new_area
315                        .frames
316                        .insert(*vpn, TrackedFrames::Multiple(new_frames));
317                }
318                // TODO(暂时注释): 大页克隆逻辑
319                //
320                // TrackedFrames::Contiguous(frame_range) => {
321                //    // 复制连续页(大页)
322                //    let num_pages = frame_range.len();
323                //    let new_frame_range = crate::mm::frame_allocator::alloc_contig_frames_aligned(
324                //        num_pages,
325                //        num_pages,
326                //    ).ok_or(page_table::PagingError::FrameAllocFailed)?;
327                //
328                //    let src_ppn = frame_range.start_ppn();
329                //    let new_ppn = new_frame_range.start_ppn();
330                //    let total_size = num_pages * crate::config::PAGE_SIZE;
331                //
332                //    // 复制数据到新帧
333                //    unsafe {
334                //        let src_va = paddr_to_vaddr(src_ppn.start_addr().as_usize());
335                //        let dst_va = paddr_to_vaddr(new_ppn.start_addr().as_usize());
336                //
337                //        core::ptr::copy_nonoverlapping(
338                //            src_va as *const u8,
339                //            dst_va as *mut u8,
340                //            total_size
341                //        );
342                //    }
343                //
344                //    // 建立页表映射 (根据页大小确定 PageSize)
345                //    let page_size = match num_pages {
346                //        262144 => PageSize::Size1G,  // 1GB = 262144 * 4KB
347                //        512 => PageSize::Size2M,     // 2MB = 512 * 4KB
348                //        _ => PageSize::Size4K,       // 其他情况使用 4K
349                //    };
350                //    page_table.map(*vpn, new_ppn, page_size, self.permission)?;
351                //
352                //    new_area.frames.insert(*vpn, TrackedFrames::Contiguous(new_frame_range));
353                // }
354                TrackedFrames::Contiguous(_) => {
355                    // 当前不支持大页克隆(已暂时禁用大页功能)
356                    return Err(page_table::PagingError::HugePageSplitNotImplemented);
357                }
358            }
359        }
360
361        Ok(new_area)
362    }
363
364    /// 拆分区域为两部分:[start, split_vpn) 和 [split_vpn, end)
365    ///
366    /// # 参数
367    /// - `page_table`: 页表的可变引用
368    /// - `split_vpn`: 拆分点(必须在区域范围内,且不等于边界)
369    ///
370    /// # 返回值
371    /// - `Ok((left, right))`: 成功,返回拆分后的两个区域
372    /// - `Err(PagingError)`: 拆分失败
373    ///
374    /// # 注意
375    /// - 原区域会被消耗(moved)
376    /// - 调用者负责将拆分后的区域插入到 areas 列表中
377    /// - 只支持 Framed 映射类型
378    pub fn split_at(
379        mut self,
380        page_table: &mut ActivePageTableInner,
381        split_vpn: Vpn,
382    ) -> Result<(Self, Self), page_table::PagingError> {
383        // 验证拆分点
384        if !self.vpn_range.contains(split_vpn) {
385            return Err(page_table::PagingError::InvalidAddress);
386        }
387
388        if split_vpn == self.vpn_range.start() || split_vpn == self.vpn_range.end() {
389            return Err(page_table::PagingError::InvalidAddress);
390        }
391
392        // 只支持 Framed 映射
393        if self.map_type != MapType::Framed {
394            return Err(page_table::PagingError::UnsupportedMapType);
395        }
396
397        // 创建左右两个区域的元数据
398        let left_range = VpnRange::new(self.vpn_range.start(), split_vpn);
399        let right_range = VpnRange::new(split_vpn, self.vpn_range.end());
400
401        // 计算分割点相对于起始的页数
402        let left_pages = split_vpn.as_usize() - self.vpn_range.start().as_usize();
403
404        // 如果有文件映射,需要分割文件映射信息
405        let left_file = self.file.as_ref().map(|f| MmapFile {
406            file: f.file.clone(),
407            offset: f.offset,            // 左半部分保持原有偏移量
408            len: left_pages * PAGE_SIZE, // 长度调整为左半部分的大小
409            prot: f.prot,
410            flags: f.flags,
411        });
412
413        let right_file = self.file.as_ref().map(|f| MmapFile {
414            file: f.file.clone(),
415            offset: f.offset + left_pages * PAGE_SIZE, // 偏移量向后移动
416            len: f.len - left_pages * PAGE_SIZE,       // 剩余长度
417            prot: f.prot,
418            flags: f.flags,
419        });
420
421        let mut left_area = MappingArea::new(
422            left_range,
423            self.area_type,
424            self.map_type,
425            self.permission.clone(),
426            left_file,
427        );
428
429        let mut right_area = MappingArea::new(
430            right_range,
431            self.area_type,
432            self.map_type,
433            self.permission.clone(),
434            right_file,
435        );
436
437        // 分配帧:遍历原区域的 frames,根据 VPN 分配到左右区域 - 手动迭代并清空
438        let vpns: alloc::vec::Vec<Vpn> = self.frames.keys().copied().collect();
439        for vpn in vpns {
440            if let Some(tracked_frames) = self.frames.remove(&vpn) {
441                if vpn < split_vpn {
442                    left_area.frames.insert(vpn, tracked_frames);
443                } else {
444                    right_area.frames.insert(vpn, tracked_frames);
445                }
446            }
447        }
448
449        // 重新建立页表映射
450        // 注意:原区域的页表映射仍然存在,我们不需要重新映射
451        // 只需要确保 frames 的所有权转移正确
452
453        Ok((left_area, right_area))
454    }
455
456    /// 部分修改权限:修改 [start_vpn, end_vpn) 范围的权限
457    ///
458    /// # 参数
459    /// - `page_table`: 页表的可变引用
460    /// - `start_vpn`: 起始 VPN(包含)
461    /// - `end_vpn`: 结束 VPN(不包含)
462    /// - `new_perm`: 新的权限标志
463    ///
464    /// # 返回值
465    /// - `Ok(alloc::vec::Vec<Self>)`: 成功,返回修改后的区域列表
466    ///   - 如果整个区域都在范围内:返回包含1个区域的向量(权限已修改)
467    ///   - 如果部分在范围内:返回包含2-3个区域的向量(分割后的区域)
468    ///
469    /// # 注意
470    /// - 原区域会被消耗(moved)
471    /// - 调用者负责将返回的区域插入到 areas 列表中
472    /// - 只支持 Framed 映射类型
473    pub fn partial_change_permission(
474        mut self,
475        page_table: &mut ActivePageTableInner,
476        start_vpn: Vpn,
477        end_vpn: Vpn,
478        new_perm: UniversalPTEFlag,
479    ) -> Result<alloc::vec::Vec<Self>, page_table::PagingError> {
480        let area_start = self.vpn_range.start();
481        let area_end = self.vpn_range.end();
482
483        // 计算需要修改权限的实际范围
484        let change_start = core::cmp::max(start_vpn, area_start);
485        let change_end = core::cmp::min(end_vpn, area_end);
486
487        if change_start >= change_end {
488            // 没有重叠,返回原区域
489            return Ok(alloc::vec![self]);
490        }
491
492        // 只支持 Framed 映射
493        if self.map_type != MapType::Framed {
494            return Err(page_table::PagingError::UnsupportedMapType);
495        }
496
497        // 修改页表中的权限
498        for vpn in VpnRange::new(change_start, change_end) {
499            page_table.update_flags(vpn, new_perm)?;
500        }
501
502        // 根据修改范围决定如何分割区域
503        if change_start == area_start && change_end == area_end {
504            // 情况 1: 整个区域都需要修改权限
505            self.permission = new_perm;
506            return Ok(alloc::vec![self]);
507        } else if change_start == area_start {
508            // 情况 2: 修改了前半部分
509            // 分割为: [area_start, change_end) 新权限 + [change_end, area_end) 旧权限
510            let left_range = VpnRange::new(area_start, change_end);
511            let right_range = VpnRange::new(change_end, area_end);
512
513            let left_pages = change_end.as_usize() - area_start.as_usize();
514
515            let left_file = self.file.as_ref().map(|f| MmapFile {
516                file: f.file.clone(),
517                offset: f.offset,
518                len: left_pages * PAGE_SIZE,
519                prot: f.prot,
520                flags: f.flags,
521            });
522
523            let right_file = self.file.as_ref().map(|f| MmapFile {
524                file: f.file.clone(),
525                offset: f.offset + left_pages * PAGE_SIZE,
526                len: f.len - left_pages * PAGE_SIZE,
527                prot: f.prot,
528                flags: f.flags,
529            });
530
531            let mut left_area = MappingArea::new(
532                left_range,
533                self.area_type,
534                self.map_type,
535                new_perm, // 新权限
536                left_file,
537            );
538
539            let mut right_area = MappingArea::new(
540                right_range,
541                self.area_type,
542                self.map_type,
543                self.permission.clone(), // 旧权限
544                right_file,
545            );
546
547            // 分配 frames
548            let vpns: alloc::vec::Vec<Vpn> = self.frames.keys().copied().collect();
549            for vpn in vpns {
550                if let Some(tracked_frames) = self.frames.remove(&vpn) {
551                    if vpn < change_end {
552                        left_area.frames.insert(vpn, tracked_frames);
553                    } else {
554                        right_area.frames.insert(vpn, tracked_frames);
555                    }
556                }
557            }
558
559            return Ok(alloc::vec![left_area, right_area]);
560        } else if change_end == area_end {
561            // 情况 3: 修改了后半部分
562            // 分割为: [area_start, change_start) 旧权限 + [change_start, area_end) 新权限
563            let left_range = VpnRange::new(area_start, change_start);
564            let right_range = VpnRange::new(change_start, area_end);
565
566            let left_pages = change_start.as_usize() - area_start.as_usize();
567
568            let left_file = self.file.as_ref().map(|f| MmapFile {
569                file: f.file.clone(),
570                offset: f.offset,
571                len: left_pages * PAGE_SIZE,
572                prot: f.prot,
573                flags: f.flags,
574            });
575
576            let right_file = self.file.as_ref().map(|f| MmapFile {
577                file: f.file.clone(),
578                offset: f.offset + left_pages * PAGE_SIZE,
579                len: f.len - left_pages * PAGE_SIZE,
580                prot: f.prot,
581                flags: f.flags,
582            });
583
584            let mut left_area = MappingArea::new(
585                left_range,
586                self.area_type,
587                self.map_type,
588                self.permission.clone(), // 旧权限
589                left_file,
590            );
591
592            let mut right_area = MappingArea::new(
593                right_range,
594                self.area_type,
595                self.map_type,
596                new_perm, // 新权限
597                right_file,
598            );
599
600            // 分配 frames
601            let vpns: alloc::vec::Vec<Vpn> = self.frames.keys().copied().collect();
602            for vpn in vpns {
603                if let Some(tracked_frames) = self.frames.remove(&vpn) {
604                    if vpn < change_start {
605                        left_area.frames.insert(vpn, tracked_frames);
606                    } else {
607                        right_area.frames.insert(vpn, tracked_frames);
608                    }
609                }
610            }
611
612            return Ok(alloc::vec![left_area, right_area]);
613        } else {
614            // 情况 4: 修改了中间部分,需要分割为三个区域
615            // [area_start, change_start) 旧权限 + [change_start, change_end) 新权限 + [change_end, area_end) 旧权限
616            let left_range = VpnRange::new(area_start, change_start);
617            let middle_range = VpnRange::new(change_start, change_end);
618            let right_range = VpnRange::new(change_end, area_end);
619
620            let left_pages = change_start.as_usize() - area_start.as_usize();
621            let middle_pages = change_end.as_usize() - change_start.as_usize();
622
623            let left_file = self.file.as_ref().map(|f| MmapFile {
624                file: f.file.clone(),
625                offset: f.offset,
626                len: left_pages * PAGE_SIZE,
627                prot: f.prot,
628                flags: f.flags,
629            });
630
631            let middle_file = self.file.as_ref().map(|f| MmapFile {
632                file: f.file.clone(),
633                offset: f.offset + left_pages * PAGE_SIZE,
634                len: middle_pages * PAGE_SIZE,
635                prot: f.prot,
636                flags: f.flags,
637            });
638
639            let right_file = self.file.as_ref().map(|f| MmapFile {
640                file: f.file.clone(),
641                offset: f.offset + (left_pages + middle_pages) * PAGE_SIZE,
642                len: f.len - (left_pages + middle_pages) * PAGE_SIZE,
643                prot: f.prot,
644                flags: f.flags,
645            });
646
647            let mut left_area = MappingArea::new(
648                left_range,
649                self.area_type,
650                self.map_type,
651                self.permission.clone(), // 旧权限
652                left_file,
653            );
654
655            let mut middle_area = MappingArea::new(
656                middle_range,
657                self.area_type,
658                self.map_type,
659                new_perm, // 新权限
660                middle_file,
661            );
662
663            let mut right_area = MappingArea::new(
664                right_range,
665                self.area_type,
666                self.map_type,
667                self.permission.clone(), // 旧权限
668                right_file,
669            );
670
671            // 分配 frames
672            let vpns: alloc::vec::Vec<Vpn> = self.frames.keys().copied().collect();
673            for vpn in vpns {
674                if let Some(tracked_frames) = self.frames.remove(&vpn) {
675                    if vpn < change_start {
676                        left_area.frames.insert(vpn, tracked_frames);
677                    } else if vpn < change_end {
678                        middle_area.frames.insert(vpn, tracked_frames);
679                    } else {
680                        right_area.frames.insert(vpn, tracked_frames);
681                    }
682                }
683            }
684
685            return Ok(alloc::vec![left_area, middle_area, right_area]);
686        }
687    }
688
689    /// 部分解除映射:解除 [start_vpn, end_vpn) 范围的映射
690    ///
691    /// # 参数
692    /// - `page_table`: 页表的可变引用
693    /// - `start_vpn`: 起始 VPN(包含)
694    /// - `end_vpn`: 结束 VPN(不包含)
695    ///
696    /// # 返回值
697    /// - `Ok(Option<(Self, Option<Self>)>)`: 成功
698    ///   - `None`: 整个区域被解除映射
699    ///   - `Some((left, None))`: 只剩左侧部分
700    ///   - `Some((left, Some(right)))`: 中间被解除映射,剩下左右两部分
701    ///
702    /// # 注意
703    /// - 原区域会被消耗(moved)
704    pub fn partial_unmap(
705        mut self,
706        page_table: &mut ActivePageTableInner,
707        start_vpn: Vpn,
708        end_vpn: Vpn,
709    ) -> Result<Option<(Self, Option<Self>)>, page_table::PagingError> {
710        let area_start = self.vpn_range.start();
711        let area_end = self.vpn_range.end();
712
713        // 计算需要解除映射的实际范围
714        let unmap_start = core::cmp::max(start_vpn, area_start);
715        let unmap_end = core::cmp::min(end_vpn, area_end);
716
717        if unmap_start >= unmap_end {
718            // 没有重叠,返回原区域
719            return Ok(Some((self, None)));
720        }
721
722        // 解除映射指定范围内的页
723        for vpn in VpnRange::new(unmap_start, unmap_end) {
724            self.unmap_one(page_table, vpn)?;
725        }
726
727        // 根据解除映射的位置,决定返回什么
728        if unmap_start == area_start && unmap_end == area_end {
729            // 情况 1: 整个区域被解除映射
730            return Ok(None);
731        } else if unmap_start == area_start {
732            // 情况 2: 解除映射了前半部分,保留 [unmap_end, area_end)
733            self.vpn_range = VpnRange::new(unmap_end, area_end);
734            return Ok(Some((self, None)));
735        } else if unmap_end == area_end {
736            // 情况 3: 解除映射了后半部分,保留 [area_start, unmap_start)
737            self.vpn_range = VpnRange::new(area_start, unmap_start);
738            return Ok(Some((self, None)));
739        } else {
740            // 情况 4: 解除映射了中间部分,需要拆分为两个区域
741            // 保留 [area_start, unmap_start) 和 [unmap_end, area_end)
742
743            let left_range = VpnRange::new(area_start, unmap_start);
744            let right_range = VpnRange::new(unmap_end, area_end);
745
746            // 计算左右部分的文件映射信息
747            let left_pages = unmap_start.as_usize() - area_start.as_usize();
748            let middle_pages = unmap_end.as_usize() - unmap_start.as_usize();
749
750            let left_file = self.file.as_ref().map(|f| MmapFile {
751                file: f.file.clone(),
752                offset: f.offset, // 左半部分保持原有偏移量
753                len: left_pages * PAGE_SIZE,
754                prot: f.prot,
755                flags: f.flags,
756            });
757
758            let right_file = self.file.as_ref().map(|f| MmapFile {
759                file: f.file.clone(),
760                offset: f.offset + (left_pages + middle_pages) * PAGE_SIZE, // 跳过左半部分和中间被 unmap 的部分
761                len: f.len - (left_pages + middle_pages) * PAGE_SIZE,
762                prot: f.prot,
763                flags: f.flags,
764            });
765
766            let mut left_area = MappingArea::new(
767                left_range,
768                self.area_type,
769                self.map_type,
770                self.permission.clone(),
771                left_file,
772            );
773
774            let mut right_area = MappingArea::new(
775                right_range,
776                self.area_type,
777                self.map_type,
778                self.permission.clone(),
779                right_file,
780            );
781
782            // 分配 frames - 手动迭代并清空
783            let vpns: alloc::vec::Vec<Vpn> = self.frames.keys().copied().collect();
784            for vpn in vpns {
785                if let Some(tracked_frames) = self.frames.remove(&vpn) {
786                    if vpn < unmap_start {
787                        left_area.frames.insert(vpn, tracked_frames);
788                    } else if vpn >= unmap_end {
789                        right_area.frames.insert(vpn, tracked_frames);
790                    }
791                    // unmap_start <= vpn < unmap_end 的 frames 已经在 unmap_one 中释放
792                }
793            }
794
795            return Ok(Some((left_area, Some(right_area))));
796        }
797    }
798
799    /// 从文件加载数据到已分配的物理页中
800    ///
801    /// # 错误
802    /// - 文件读取失败
803    /// - 页面未分配
804    pub fn load_from_file(&mut self) -> Result<(), page_table::PagingError> {
805        if let Some(ref mmap_file) = self.file {
806            let inode = mmap_file
807                .file
808                .inode()
809                .map_err(|_| page_table::PagingError::InvalidAddress)?;
810            let start_vpn = self.vpn_range.start();
811
812            for (vpn, tracked_frame) in &self.frames {
813                // 计算文件偏移量
814                let page_offset = vpn.as_usize() - start_vpn.as_usize();
815                let file_offset = mmap_file.offset + page_offset * PAGE_SIZE;
816
817                // 获取物理页并通过内核直接映射访问
818                let ppn = match tracked_frame {
819                    TrackedFrames::Single(frame) => frame.ppn(),
820                    TrackedFrames::Multiple(frames) => frames.first().map(|f| f.ppn()).unwrap(),
821                    TrackedFrames::Contiguous(_) => {
822                        panic!("当前实现不支持连续帧");
823                    }
824                };
825
826                let paddr = ppn.start_addr();
827                let kernel_vaddr = paddr_to_vaddr(paddr.as_usize());
828                let buffer =
829                    unsafe { core::slice::from_raw_parts_mut(kernel_vaddr as *mut u8, PAGE_SIZE) };
830
831                // 计算实际读取长度(处理文件末尾)
832                let read_len = min(
833                    PAGE_SIZE,
834                    mmap_file.len.saturating_sub(page_offset * PAGE_SIZE),
835                );
836
837                if read_len == 0 {
838                    continue; // 超出文件末尾,页面保持清零状态
839                }
840
841                // 从文件读取数据
842                let actual_read = inode
843                    .read_at(file_offset, &mut buffer[..read_len])
844                    .map_err(|_| page_table::PagingError::InvalidAddress)?;
845
846                // 部分读取时记录警告(剩余部分保持为零)
847                if actual_read < read_len {
848                    pr_warn!(
849                        "Partial read at offset {}: expected {}, got {}",
850                        file_offset,
851                        read_len,
852                        actual_read
853                    );
854                }
855
856                // buffer[actual_read..] 保持为零(新分配的物理帧默认清零)
857            }
858        }
859        Ok(())
860    }
861
862    /// 将脏页写回文件
863    ///
864    /// # 参数
865    /// - `page_table`: 页表引用,用于检查和清除 Dirty 位
866    ///
867    /// # 错误
868    /// - 文件写入失败
869    /// - 部分写入
870    pub fn sync_file(
871        &self,
872        page_table: &mut ActivePageTableInner,
873    ) -> Result<(), page_table::PagingError> {
874        if let Some(ref mmap_file) = self.file {
875            // 只有 MAP_SHARED 映射才需要写回
876            if !mmap_file.flags.contains(MapFlags::SHARED) {
877                return Ok(());
878            }
879
880            let inode = mmap_file
881                .file
882                .inode()
883                .map_err(|_| page_table::PagingError::InvalidAddress)?;
884            let start_vpn = self.vpn_range.start();
885
886            for (vpn, tracked_frame) in &self.frames {
887                // 获取页表项的标志位,检查 Dirty 位
888                let (_, _, flags) = match page_table.walk(*vpn) {
889                    Ok(result) => result,
890                    Err(_) => continue, // 页面未映射,跳过
891                };
892
893                if !flags.contains(UniversalPTEFlag::DIRTY) {
894                    continue; // 未被修改,跳过
895                }
896
897                // 计算文件偏移量
898                let page_offset = vpn.as_usize() - start_vpn.as_usize();
899                let file_offset = mmap_file.offset + page_offset * PAGE_SIZE;
900
901                // 获取物理页内容
902                let ppn = match tracked_frame {
903                    TrackedFrames::Single(frame) => frame.ppn(),
904                    TrackedFrames::Multiple(frames) => frames.first().map(|f| f.ppn()).unwrap(),
905                    TrackedFrames::Contiguous(_) => {
906                        panic!("当前实现不支持连续帧");
907                    }
908                };
909
910                let paddr = ppn.start_addr();
911                let kernel_vaddr = paddr_to_vaddr(paddr.as_usize());
912                let buffer =
913                    unsafe { core::slice::from_raw_parts(kernel_vaddr as *const u8, PAGE_SIZE) };
914
915                // 计算实际写入长度(处理文件末尾)
916                let write_len = min(
917                    PAGE_SIZE,
918                    mmap_file.len.saturating_sub(page_offset * PAGE_SIZE),
919                );
920
921                if write_len == 0 {
922                    continue; // 超出文件范围
923                }
924
925                // 写回文件
926                let actual_written = inode
927                    .write_at(file_offset, &buffer[..write_len])
928                    .map_err(|_| page_table::PagingError::InvalidAddress)?;
929
930                // 检查是否完全写入
931                if actual_written != write_len {
932                    pr_err!(
933                        "Partial write at offset {}: expected {}, got {}",
934                        file_offset,
935                        write_len,
936                        actual_written
937                    );
938                    return Err(page_table::PagingError::InvalidAddress);
939                }
940
941                // 清除 Dirty 位
942                page_table.update_flags(*vpn, flags & !UniversalPTEFlag::DIRTY)?;
943            }
944        }
945        Ok(())
946    }
947}
948
949// TODO(暂时注释): 大页映射实现,包含贪心算法选择1GB/2MB/4K页
950//
951// /// 大页映射实现
952// ///
953// /// 推荐使用场景:
954// /// * 映射内核物理内存区域
955// /// * 映射内核代码和只读数据段
956// /// * Mmap 大型文件
957// /// * 进程间的共享内存区域
958// /// * 不经常分配和释放的大内存区域
959// ///
960// /// 不推荐使用场景:
961// /// * 在用户空间中使用
962// /// * 经常分配和释放的小内存区域
963// ///
964// /// TODO: 实现将大页拆分为小页的功能(如果需要,例如用于 COW)
965// impl MappingArea {
966//     /// 使用贪心算法映射为大页
967//     pub fn map_with_huge_page(&mut self, page_table: &mut ActivePageTableInner) -> Result<(), page_table::PagingError> {
968//         let start_va = self.vpn_range.start().start_addr();
969//         let end_va = self.vpn_range.end().start_addr();
970//         let mut current_va = start_va;
971//
972//         while current_va < end_va {
973//             let remaining = end_va.as_usize() - current_va.as_usize();
974//             let current_vpn = Vpn::from_addr_floor(current_va);
975//
976//             // 贪心算法:优先尝试大页
977//
978//             // 尝试 1GB 页
979//             if remaining >= PageSize::Size1G as usize
980//                 && current_va.as_usize() % (PageSize::Size1G as usize) == 0
981//             {
982//                 let ppn = self.allocate_for_huge_page(
983//                     current_vpn,
984//                     262144,  // 1GB = 262144 pages
985//                 )?;
986//
987//                 page_table.map(
988//                     current_vpn,
989//                     ppn,
990//                     PageSize::Size1G,
991//                     self.permission,
992//                 )?;
993//
994//                 current_va = current_va + PageSize::Size1G as usize;
995//             }
996//             // 尝试 2MB 页
997//             else if remaining >= PageSize::Size2M as usize
998//                 && current_va.as_usize() % (PageSize::Size2M as usize) == 0
999//             {
1000//                 let ppn = self.allocate_for_huge_page(
1001//                     current_vpn,
1002//                     512,  // 2MB = 512 pages
1003//                 )?;
1004//
1005//                 page_table.map(
1006//                     current_vpn,
1007//                     ppn,
1008//                     PageSize::Size2M,
1009//                     self.permission,
1010//                 )?;
1011//
1012//                 current_va = current_va + PageSize::Size2M as usize;
1013//             }
1014//             // 使用 4KB 页
1015//             else {
1016//                 let ppn = self.allocate_for_small_page(current_vpn)?;
1017//
1018//                 page_table.map(
1019//                     current_vpn,
1020//                     ppn,
1021//                     PageSize::Size4K,
1022//                     self.permission,
1023//                 )?;
1024//
1025//                 current_va = current_va + PageSize::Size4K as usize;
1026//             }
1027//         }
1028//
1029//         Ok(())
1030//     }
1031//
1032//     fn allocate_for_huge_page(&mut self, vpn: Vpn, num_pages: usize) -> Result<Ppn, page_table::PagingError> {
1033//         match self.map_type {
1034//             MapType::Direct => {
1035//                 // 恒等映射:PPN = VPN
1036//                 Ok(Ppn::from_usize(vpn.as_usize()))
1037//             }
1038//             MapType::Framed => {
1039//                 // 使用对齐分配
1040//                 let frame_range = crate::mm::frame_allocator::alloc_contig_frames_aligned(
1041//                     num_pages,
1042//                     num_pages,  // 对齐要求 = 页数
1043//                 ).ok_or(page_table::PagingError::InvalidAddress)?;
1044//
1045//                 let ppn = frame_range.start_ppn();
1046//
1047//                 // 存储到 frames(使用 Contiguous 变体)
1048//                 self.frames.insert(vpn, TrackedFrames::Contiguous(frame_range));
1049//
1050//                 Ok(ppn)
1051//             }
1052//         }
1053//     }
1054//
1055//     fn allocate_for_small_page(&mut self, vpn: Vpn) -> Result<Ppn, page_table::PagingError> {
1056//         match self.map_type {
1057//             MapType::Direct => {
1058//                 Ok(Ppn::from_usize(vpn.as_usize()))
1059//             }
1060//             MapType::Framed => {
1061//                 let frame = crate::mm::frame_allocator::alloc_frame()
1062//                     .ok_or(page_table::PagingError::InvalidAddress)?;
1063//                 let ppn = frame.ppn();
1064//                 self.frames.insert(vpn, TrackedFrames::Single(frame));
1065//                 Ok(ppn)
1066//             }
1067//         }
1068//     }
1069// }
1070
1071/// 动态扩展和收缩
1072impl MappingArea {
1073    // TODO(暂时注释): 支持大页的扩展方法
1074    //
1075    // /// 通过在末尾添加页来扩展区域
1076    // ///
1077    // /// 如果对齐和大小允许,支持大页分配
1078    // /// 返回新的结束 VPN
1079    // pub fn extend(
1080    //    &mut self,
1081    //    page_table: &mut ActivePageTableInner,
1082    //    count: usize,
1083    // ) -> Result<Vpn, page_table::PagingError> {
1084    //    let old_end = self.vpn_range.end();
1085    //    let new_end = Vpn::from_usize(old_end.as_usize() + count);
1086    //
1087    //    let start_va = old_end.start_addr();
1088    //    let end_va = new_end.start_addr();
1089    //    let mut current_va = start_va;
1090    //
1091    //    // 使用贪心算法映射新页(支持大页)
1092    //    while current_va < end_va {
1093    //        let remaining = end_va.as_usize() - current_va.as_usize();
1094    //        let current_vpn = Vpn::from_addr_floor(current_va);
1095    //
1096    //        // 尝试 1GB 页
1097    //        if remaining >= PageSize::Size1G as usize
1098    //            && current_va.as_usize() % (PageSize::Size1G as usize) == 0
1099    //        {
1100    //            let ppn = self.allocate_for_huge_page(current_vpn, 262144)?;
1101    //            page_table.map(current_vpn, ppn, PageSize::Size1G, self.permission)?;
1102    //            current_va = current_va + PageSize::Size1G as usize;
1103    //        }
1104    //        // 尝试 2MB 页
1105    //        else if remaining >= PageSize::Size2M as usize
1106    //            && current_va.as_usize() % (PageSize::Size2M as usize) == 0
1107    //        {
1108    //            let ppn = self.allocate_for_huge_page(current_vpn, 512)?;
1109    //            page_table.map(current_vpn, ppn, PageSize::Size2M, self.permission)?;
1110    //            current_va = current_va + PageSize::Size2M as usize;
1111    //        }
1112    //        // 使用 4KB 页
1113    //        else {
1114    //            let ppn = self.allocate_for_small_page(current_vpn)?;
1115    //            page_table.map(current_vpn, ppn, PageSize::Size4K, self.permission)?;
1116    //            current_va = current_va + PageSize::Size4K as usize;
1117    //        }
1118    //    }
1119    //
1120    //    // 更新范围
1121    //    self.vpn_range = VpnRange::new(self.vpn_range.start(), new_end);
1122    //
1123    //    Ok(new_end)
1124    // }
1125
1126    /// 通过在末尾添加页来扩展区域(仅限 4K 页)
1127    ///
1128    /// 返回新的结束 VPN
1129    pub fn extend(
1130        &mut self,
1131        page_table: &mut ActivePageTableInner,
1132        count: usize,
1133    ) -> Result<Vpn, page_table::PagingError> {
1134        let old_end = self.vpn_range.end();
1135        let new_end = Vpn::from_usize(old_end.as_usize() + count);
1136
1137        // 仅使用 4K 页映射每个新页
1138        for i in 0..count {
1139            let vpn = Vpn::from_usize(old_end.as_usize() + i);
1140            self.map_one(page_table, vpn)?;
1141        }
1142
1143        // 更新范围
1144        self.vpn_range = VpnRange::new(self.vpn_range.start(), new_end);
1145
1146        Ok(new_end)
1147    }
1148
1149    // TODO(暂时注释): 支持大页的收缩方法
1150    //
1151    // /// 通过从末尾移除页来收缩区域
1152    // ///
1153    // /// 处理大页边界:
1154    // /// - 如果移除整个大页:直接解除映射
1155    // /// - 如果部分移除一个大页:当前返回错误
1156    // ///  (TODO: 如果需要,实现大页拆分)
1157    // ///
1158    // /// 返回新的结束 VPN
1159    // pub fn shrink(
1160    //    &mut self,
1161    //    page_table: &mut ActivePageTableInner,
1162    //    count: usize,
1163    // ) -> Result<Vpn, page_table::PagingError> {
1164    //    if count > self.vpn_range.len() {
1165    //        return Err(page_table::PagingError::ShrinkBelowStart);
1166    //    }
1167    //
1168    //    let old_end = self.vpn_range.end();
1169    //    let new_end = Vpn::from_usize(old_end.as_usize() - count);
1170    //
1171    //    // 收集需要移除的 VPN 范围
1172    //    let remove_range = VpnRange::new(new_end, old_end);
1173    //
1174    //    // 检查并移除帧
1175    //    // 需要从后向前遍历,以便正确处理大页
1176    //    let mut vpns_to_remove: alloc::vec::Vec<Vpn> = remove_range.into_iter().collect();
1177    //    vpns_to_remove.sort_by(|a, b| b.cmp(a)); // 降序排列
1178    //
1179    //    let mut i = 0;
1180    //    while i < vpns_to_remove.len() {
1181    //        let vpn = vpns_to_remove[i];
1182    //
1183    //        // 检查这个 VPN 是否有对应的帧记录
1184    //        if let Some(tracked_frames) = self.frames.get(&vpn) {
1185    //            match tracked_frames {
1186    //                TrackedFrames::Single(_) => {
1187    //                    // 单个 4K 页,直接取消映射
1188    //                    page_table.unmap(vpn)?;
1189    //                    self.frames.remove(&vpn);
1190    //                    i += 1;
1191    //                }
1192    //                TrackedFrames::Multiple(_) => {
1193    //                    // 多个不连续页,直接取消映射
1194    //                    page_table.unmap(vpn)?;
1195    //                    self.frames.remove(&vpn);
1196    //                    i += 1;
1197    //                }
1198    //                TrackedFrames::Contiguous(frame_range) => {
1199    //                    // 连续页(大页)
1200    //                    let num_pages = frame_range.len();
1201    //
1202    //                    // 检查是否要移除整个大页
1203    //                    let huge_page_vpns: alloc::vec::Vec<Vpn> = (vpn.as_usize()..vpn.as_usize() + num_pages)
1204    //                        .map(|v| Vpn::from_usize(v))
1205    //                        .collect();
1206    //
1207    //                    let all_in_remove = huge_page_vpns.iter()
1208    //                        .all(|v| remove_range.contains(*v));
1209    //
1210    //                    if all_in_remove {
1211    //                        // 整个大页都要移除,直接取消映射
1212    //                        page_table.unmap(vpn)?;
1213    //                        self.frames.remove(&vpn);
1214    //                        i += num_pages;
1215    //                    } else {
1216    //                        // 部分移除大页:目前不支持,需要实现大页拆分
1217    //                        return Err(page_table::PagingError::HugePageSplitNotImplemented);
1218    //                    }
1219    //                }
1220    //            }
1221    //        } else {
1222    //            // 没有帧记录(可能是恒等映射),只需取消映射
1223    //            page_table.unmap(vpn)?;
1224    //            i += 1;
1225    //        }
1226    //    }
1227    //
1228    //    // 更新范围
1229    //    self.vpn_range = VpnRange::new(self.vpn_range.start(), new_end);
1230    //
1231    //    Ok(new_end)
1232    // }
1233
1234    /// 通过从末尾移除页来收缩区域(仅限 4K 页)
1235    ///
1236    /// 返回新的结束 VPN
1237    pub fn shrink(
1238        &mut self,
1239        page_table: &mut ActivePageTableInner,
1240        count: usize,
1241    ) -> Result<Vpn, page_table::PagingError> {
1242        if count > self.vpn_range.len() {
1243            return Err(page_table::PagingError::ShrinkBelowStart);
1244        }
1245
1246        let old_end = self.vpn_range.end();
1247        let new_end = Vpn::from_usize(old_end.as_usize() - count);
1248
1249        // 解除映射 [new_end, old_end) 范围内的页
1250        // 对于 4K 页,解除映射顺序不影响正确性
1251        for i in 0..count {
1252            let vpn = Vpn::from_usize(new_end.as_usize() + i);
1253            self.unmap_one(page_table, vpn)?;
1254        }
1255
1256        // 更新范围
1257        self.vpn_range = VpnRange::new(self.vpn_range.start(), new_end);
1258
1259        Ok(new_end)
1260    }
1261}