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}