xref: /DragonOS/kernel/src/mm/ucontext.rs (revision 7b0ef10895108a0de5ff5ef3d2f93f40cf2e33a5)
1 // 进程的用户空间内存管理
2 
3 use core::{
4     cmp,
5     hash::Hasher,
6     intrinsics::unlikely,
7     ops::Add,
8     sync::atomic::{compiler_fence, Ordering},
9 };
10 
11 use alloc::{
12     collections::BTreeMap,
13     sync::{Arc, Weak},
14     vec::Vec,
15 };
16 use hashbrown::HashSet;
17 use ida::IdAllocator;
18 use system_error::SystemError;
19 
20 use crate::{
21     arch::{mm::PageMapper, CurrentIrqArch, MMArch},
22     exception::InterruptArch,
23     filesystem::vfs::file::File,
24     libs::{
25         align::page_align_up,
26         rwlock::RwLock,
27         spinlock::{SpinLock, SpinLockGuard},
28     },
29     mm::page::page_manager_lock_irqsave,
30     process::ProcessManager,
31     syscall::user_access::{UserBufferReader, UserBufferWriter},
32 };
33 
34 use super::{
35     allocator::page_frame::{
36         deallocate_page_frames, PageFrameCount, PhysPageFrame, VirtPageFrame, VirtPageFrameIter,
37     },
38     page::{EntryFlags, Flusher, InactiveFlusher, Page, PageFlushAll},
39     syscall::{MadvFlags, MapFlags, MremapFlags, ProtFlags},
40     MemoryManagementArch, PageTableKind, VirtAddr, VirtRegion, VmFlags,
41 };
42 
43 /// MMAP_MIN_ADDR的默认值
44 /// 以下内容来自linux-5.19:
45 ///  This is the portion of low virtual memory which should be protected
46 //   from userspace allocation.  Keeping a user from writing to low pages
47 //   can help reduce the impact of kernel NULL pointer bugs.
48 //   For most ia64, ppc64 and x86 users with lots of address space
49 //   a value of 65536 is reasonable and should cause no problems.
50 //   On arm and other archs it should not be higher than 32768.
51 //   Programs which use vm86 functionality or have some need to map
52 //   this low address space will need CAP_SYS_RAWIO or disable this
53 //   protection by setting the value to 0.
54 pub const DEFAULT_MMAP_MIN_ADDR: usize = 65536;
55 
56 /// LockedVMA的id分配器
57 static LOCKEDVMA_ID_ALLOCATOR: SpinLock<IdAllocator> =
58     SpinLock::new(IdAllocator::new(0, usize::MAX).unwrap());
59 
60 #[derive(Debug)]
61 pub struct AddressSpace {
62     inner: RwLock<InnerAddressSpace>,
63 }
64 
65 impl AddressSpace {
66     pub fn new(create_stack: bool) -> Result<Arc<Self>, SystemError> {
67         let inner = InnerAddressSpace::new(create_stack)?;
68         let result = Self {
69             inner: RwLock::new(inner),
70         };
71         return Ok(Arc::new(result));
72     }
73 
74     /// 从pcb中获取当前进程的地址空间结构体的Arc指针
75     pub fn current() -> Result<Arc<AddressSpace>, SystemError> {
76         let vm = ProcessManager::current_pcb()
77             .basic()
78             .user_vm()
79             .expect("Current process has no address space");
80 
81         return Ok(vm);
82     }
83 
84     /// 判断某个地址空间是否为当前进程的地址空间
85     pub fn is_current(self: &Arc<Self>) -> bool {
86         let current = Self::current();
87         if let Ok(current) = current {
88             return Arc::ptr_eq(&current, self);
89         }
90         return false;
91     }
92 }
93 
94 impl core::ops::Deref for AddressSpace {
95     type Target = RwLock<InnerAddressSpace>;
96 
97     fn deref(&self) -> &Self::Target {
98         &self.inner
99     }
100 }
101 
102 impl core::ops::DerefMut for AddressSpace {
103     fn deref_mut(&mut self) -> &mut Self::Target {
104         &mut self.inner
105     }
106 }
107 
108 /// @brief 用户地址空间结构体(每个进程都有一个)
109 #[derive(Debug)]
110 pub struct InnerAddressSpace {
111     pub user_mapper: UserMapper,
112     pub mappings: UserMappings,
113     pub mmap_min: VirtAddr,
114     /// 用户栈信息结构体
115     pub user_stack: Option<UserStack>,
116 
117     pub elf_brk_start: VirtAddr,
118     pub elf_brk: VirtAddr,
119 
120     /// 当前进程的堆空间的起始地址
121     pub brk_start: VirtAddr,
122     /// 当前进程的堆空间的结束地址(不包含)
123     pub brk: VirtAddr,
124 
125     pub start_code: VirtAddr,
126     pub end_code: VirtAddr,
127     pub start_data: VirtAddr,
128     pub end_data: VirtAddr,
129 }
130 
131 impl InnerAddressSpace {
132     pub fn new(create_stack: bool) -> Result<Self, SystemError> {
133         let mut result = Self {
134             user_mapper: MMArch::setup_new_usermapper()?,
135             mappings: UserMappings::new(),
136             mmap_min: VirtAddr(DEFAULT_MMAP_MIN_ADDR),
137             elf_brk_start: VirtAddr::new(0),
138             elf_brk: VirtAddr::new(0),
139             brk_start: MMArch::USER_BRK_START,
140             brk: MMArch::USER_BRK_START,
141             user_stack: None,
142             start_code: VirtAddr(0),
143             end_code: VirtAddr(0),
144             start_data: VirtAddr(0),
145             end_data: VirtAddr(0),
146         };
147         if create_stack {
148             // debug!("to create user stack.");
149             result.new_user_stack(UserStack::DEFAULT_USER_STACK_SIZE)?;
150         }
151 
152         return Ok(result);
153     }
154 
155     /// 尝试克隆当前进程的地址空间,包括这些映射都会被克隆
156     ///
157     /// # Returns
158     ///
159     /// 返回克隆后的,新的地址空间的Arc指针
160     #[inline(never)]
161     pub fn try_clone(&mut self) -> Result<Arc<AddressSpace>, SystemError> {
162         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
163         let new_addr_space = AddressSpace::new(false)?;
164         let mut new_guard = new_addr_space.write();
165         unsafe {
166             new_guard
167                 .user_mapper
168                 .clone_from(&mut self.user_mapper, MMArch::PAGE_FAULT_ENABLED)
169         };
170 
171         // 拷贝用户栈的结构体信息,但是不拷贝用户栈的内容(因为后面VMA的拷贝会拷贝用户栈的内容)
172         unsafe {
173             new_guard.user_stack = Some(self.user_stack.as_ref().unwrap().clone_info_only());
174         }
175         let _current_stack_size = self.user_stack.as_ref().unwrap().stack_size();
176 
177         // 拷贝空洞
178         new_guard.mappings.vm_holes = self.mappings.vm_holes.clone();
179 
180         for vma in self.mappings.vmas.iter() {
181             // TODO: 增加对VMA是否为文件映射的判断,如果是的话,就跳过
182 
183             let vma_guard: SpinLockGuard<'_, VMA> = vma.lock_irqsave();
184 
185             // 仅拷贝VMA信息并添加反向映射,因为UserMapper克隆时已经分配了新的物理页
186             let new_vma = LockedVMA::new(vma_guard.clone_info_only());
187             new_guard.mappings.vmas.insert(new_vma.clone());
188             // debug!("new vma: {:x?}", new_vma);
189             let new_vma_guard = new_vma.lock_irqsave();
190             let new_mapper = &new_guard.user_mapper.utable;
191             let mut page_manager_guard = page_manager_lock_irqsave();
192             for page in new_vma_guard.pages().map(|p| p.virt_address()) {
193                 if let Some((paddr, _)) = new_mapper.translate(page) {
194                     let page = page_manager_guard.get_unwrap(&paddr);
195                     page.write_irqsave().insert_vma(new_vma.clone());
196                 }
197             }
198 
199             drop(page_manager_guard);
200             drop(vma_guard);
201             drop(new_vma_guard);
202         }
203         drop(new_guard);
204         drop(irq_guard);
205         return Ok(new_addr_space);
206     }
207 
208     /// 拓展用户栈
209     /// ## 参数
210     ///
211     /// - `bytes`: 拓展大小
212     #[allow(dead_code)]
213     pub fn extend_stack(&mut self, mut bytes: usize) -> Result<(), SystemError> {
214         // debug!("extend user stack");
215         let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC;
216         let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_GROWSDOWN;
217         let stack = self.user_stack.as_mut().unwrap();
218 
219         bytes = page_align_up(bytes);
220         stack.mapped_size += bytes;
221         let len = stack.stack_bottom - stack.mapped_size;
222         self.map_anonymous(len, bytes, prot_flags, map_flags, false, false)?;
223         return Ok(());
224     }
225 
226     /// 判断当前的地址空间是否是当前进程的地址空间
227     #[inline]
228     pub fn is_current(&self) -> bool {
229         return self.user_mapper.utable.is_current();
230     }
231 
232     /// 进行匿名页映射
233     ///
234     /// ## 参数
235     ///
236     /// - `start_vaddr`:映射的起始地址
237     /// - `len`:映射的长度
238     /// - `prot_flags`:保护标志
239     /// - `map_flags`:映射标志
240     /// - `round_to_min`:是否将`start_vaddr`对齐到`mmap_min`,如果为`true`,则当`start_vaddr`不为0时,会对齐到`mmap_min`,否则仅向下对齐到页边界
241     /// - `allocate_at_once`:是否立即分配物理空间
242     ///
243     /// ## 返回
244     ///
245     /// 返回映射的起始虚拟页帧
246     pub fn map_anonymous(
247         &mut self,
248         start_vaddr: VirtAddr,
249         len: usize,
250         prot_flags: ProtFlags,
251         map_flags: MapFlags,
252         round_to_min: bool,
253         allocate_at_once: bool,
254     ) -> Result<VirtPageFrame, SystemError> {
255         let allocate_at_once = if MMArch::PAGE_FAULT_ENABLED {
256             allocate_at_once
257         } else {
258             true
259         };
260         // 用于对齐hint的函数
261         let round_hint_to_min = |hint: VirtAddr| {
262             // 先把hint向下对齐到页边界
263             let addr = hint.data() & (!MMArch::PAGE_OFFSET_MASK);
264             // debug!("map_anonymous: hint = {:?}, addr = {addr:#x}", hint);
265             // 如果hint不是0,且hint小于DEFAULT_MMAP_MIN_ADDR,则对齐到DEFAULT_MMAP_MIN_ADDR
266             if (addr != 0) && round_to_min && (addr < DEFAULT_MMAP_MIN_ADDR) {
267                 Some(VirtAddr::new(page_align_up(DEFAULT_MMAP_MIN_ADDR)))
268             } else if addr == 0 {
269                 None
270             } else {
271                 Some(VirtAddr::new(addr))
272             }
273         };
274         // debug!("map_anonymous: start_vaddr = {:?}", start_vaddr);
275         // debug!("map_anonymous: len(no align) = {}", len);
276 
277         let len = page_align_up(len);
278 
279         // debug!("map_anonymous: len = {}", len);
280 
281         let start_page: VirtPageFrame = self.mmap(
282             round_hint_to_min(start_vaddr),
283             PageFrameCount::from_bytes(len).unwrap(),
284             prot_flags,
285             map_flags,
286             move |page, count, vm_flags, flags, mapper, flusher| {
287                 if allocate_at_once {
288                     VMA::zeroed(page, count, vm_flags, flags, mapper, flusher, None, None)
289                 } else {
290                     Ok(LockedVMA::new(VMA::new(
291                         VirtRegion::new(page.virt_address(), count.data() * MMArch::PAGE_SIZE),
292                         vm_flags,
293                         flags,
294                         None,
295                         None,
296                         false,
297                     )))
298                 }
299             },
300         )?;
301 
302         return Ok(start_page);
303     }
304 
305     /// 进行文件页映射
306     ///
307     /// ## 参数
308     ///
309     /// - `start_vaddr`:映射的起始地址
310     /// - `len`:映射的长度
311     /// - `prot_flags`:保护标志
312     /// - `map_flags`:映射标志
313     /// - `fd`:文件描述符
314     /// - `offset`:映射偏移量
315     /// - `round_to_min`:是否将`start_vaddr`对齐到`mmap_min`,如果为`true`,则当`start_vaddr`不为0时,会对齐到`mmap_min`,否则仅向下对齐到页边界
316     /// - `allocate_at_once`:是否立即分配物理空间
317     ///
318     /// ## 返回
319     ///
320     /// 返回映射的起始虚拟页帧
321     #[allow(clippy::too_many_arguments)]
322     pub fn file_mapping(
323         &mut self,
324         start_vaddr: VirtAddr,
325         len: usize,
326         prot_flags: ProtFlags,
327         map_flags: MapFlags,
328         fd: i32,
329         offset: usize,
330         round_to_min: bool,
331         allocate_at_once: bool,
332     ) -> Result<VirtPageFrame, SystemError> {
333         let allocate_at_once = if MMArch::PAGE_FAULT_ENABLED {
334             allocate_at_once
335         } else {
336             true
337         };
338         // 用于对齐hint的函数
339         let round_hint_to_min = |hint: VirtAddr| {
340             // 先把hint向下对齐到页边界
341             let addr = hint.data() & (!MMArch::PAGE_OFFSET_MASK);
342             // debug!("map_anonymous: hint = {:?}, addr = {addr:#x}", hint);
343             // 如果hint不是0,且hint小于DEFAULT_MMAP_MIN_ADDR,则对齐到DEFAULT_MMAP_MIN_ADDR
344             if (addr != 0) && round_to_min && (addr < DEFAULT_MMAP_MIN_ADDR) {
345                 Some(VirtAddr::new(page_align_up(DEFAULT_MMAP_MIN_ADDR)))
346             } else if addr == 0 {
347                 None
348             } else {
349                 Some(VirtAddr::new(addr))
350             }
351         };
352         // debug!("map_anonymous: start_vaddr = {:?}", start_vaddr);
353         // debug!("map_anonymous: len(no align) = {}", len);
354 
355         let len = page_align_up(len);
356 
357         // debug!("map_anonymous: len = {}", len);
358 
359         let binding = ProcessManager::current_pcb().fd_table();
360         let fd_table_guard = binding.read();
361 
362         let file = fd_table_guard.get_file_by_fd(fd);
363         if file.is_none() {
364             return Err(SystemError::EBADF);
365         }
366         // drop guard 以避免无法调度的问题
367         drop(fd_table_guard);
368 
369         // offset需要4K对齐
370         if !offset & (MMArch::PAGE_SIZE - 1) == 0 {
371             return Err(SystemError::EINVAL);
372         }
373         let pgoff = offset >> MMArch::PAGE_SHIFT;
374 
375         let start_page: VirtPageFrame = self.mmap(
376             round_hint_to_min(start_vaddr),
377             PageFrameCount::from_bytes(len).unwrap(),
378             prot_flags,
379             map_flags,
380             |page, count, vm_flags, flags, mapper, flusher| {
381                 if allocate_at_once {
382                     VMA::zeroed(
383                         page,
384                         count,
385                         vm_flags,
386                         flags,
387                         mapper,
388                         flusher,
389                         file.clone(),
390                         Some(pgoff),
391                     )
392                 } else {
393                     Ok(LockedVMA::new(VMA::new(
394                         VirtRegion::new(page.virt_address(), count.data() * MMArch::PAGE_SIZE),
395                         vm_flags,
396                         flags,
397                         file.clone(),
398                         Some(pgoff),
399                         false,
400                     )))
401                 }
402             },
403         )?;
404         // todo!(impl mmap for other file)
405         // https://github.com/DragonOS-Community/DragonOS/pull/912#discussion_r1765334272
406         let file = file.unwrap();
407         let _ = file.inode().mmap(start_vaddr.data(), len, offset);
408         return Ok(start_page);
409     }
410 
411     /// 向进程的地址空间映射页面
412     ///
413     /// # 参数
414     ///
415     /// - `addr`:映射的起始地址,如果为`None`,则由内核自动分配
416     /// - `page_count`:映射的页面数量
417     /// - `prot_flags`:保护标志
418     /// - `map_flags`:映射标志
419     /// - `map_func`:映射函数,用于创建VMA
420     ///
421     /// # Returns
422     ///
423     /// 返回映射的起始虚拟页帧
424     ///
425     /// # Errors
426     ///
427     /// - `EINVAL`:参数错误
428     pub fn mmap<
429         F: FnOnce(
430             VirtPageFrame,
431             PageFrameCount,
432             VmFlags,
433             EntryFlags<MMArch>,
434             &mut PageMapper,
435             &mut dyn Flusher<MMArch>,
436         ) -> Result<Arc<LockedVMA>, SystemError>,
437     >(
438         &mut self,
439         addr: Option<VirtAddr>,
440         page_count: PageFrameCount,
441         prot_flags: ProtFlags,
442         map_flags: MapFlags,
443         map_func: F,
444     ) -> Result<VirtPageFrame, SystemError> {
445         if page_count == PageFrameCount::new(0) {
446             return Err(SystemError::EINVAL);
447         }
448         // debug!("mmap: addr: {addr:?}, page_count: {page_count:?}, prot_flags: {prot_flags:?}, map_flags: {map_flags:?}");
449 
450         // 找到未使用的区域
451         let region = match addr {
452             Some(vaddr) => {
453                 self.mappings
454                     .find_free_at(self.mmap_min, vaddr, page_count.bytes(), map_flags)?
455             }
456             None => self
457                 .mappings
458                 .find_free(self.mmap_min, page_count.bytes())
459                 .ok_or(SystemError::ENOMEM)?,
460         };
461 
462         let page = VirtPageFrame::new(region.start());
463 
464         let vm_flags = VmFlags::from(prot_flags)
465             | VmFlags::from(map_flags)
466             | VmFlags::VM_MAYREAD
467             | VmFlags::VM_MAYWRITE
468             | VmFlags::VM_MAYEXEC;
469 
470         // debug!("mmap: page: {:?}, region={region:?}", page.virt_address());
471 
472         compiler_fence(Ordering::SeqCst);
473         let (mut active, mut inactive);
474         let flusher = if self.is_current() {
475             active = PageFlushAll::new();
476             &mut active as &mut dyn Flusher<MMArch>
477         } else {
478             inactive = InactiveFlusher::new();
479             &mut inactive as &mut dyn Flusher<MMArch>
480         };
481         compiler_fence(Ordering::SeqCst);
482         // 映射页面,并将VMA插入到地址空间的VMA列表中
483         self.mappings.insert_vma(map_func(
484             page,
485             page_count,
486             vm_flags,
487             EntryFlags::from_prot_flags(prot_flags, true),
488             &mut self.user_mapper.utable,
489             flusher,
490         )?);
491 
492         return Ok(page);
493     }
494 
495     /// 重映射内存区域
496     ///
497     /// # 参数
498     ///
499     /// - `old_vaddr`:原映射的起始地址
500     /// - `old_len`:原映射的长度
501     /// - `new_len`:重新映射的长度
502     /// - `mremap_flags`:重映射标志
503     /// - `new_vaddr`:重新映射的起始地址
504     /// - `vm_flags`:旧内存区域标志
505     ///
506     /// # Returns
507     ///
508     /// 返回重映射的起始虚拟页帧地址
509     ///
510     /// # Errors
511     ///
512     /// - `EINVAL`:参数错误
513     pub fn mremap(
514         &mut self,
515         old_vaddr: VirtAddr,
516         old_len: usize,
517         new_len: usize,
518         mremap_flags: MremapFlags,
519         new_vaddr: VirtAddr,
520         vm_flags: VmFlags,
521     ) -> Result<VirtAddr, SystemError> {
522         // 检查新内存地址是否对齐
523         if !new_vaddr.check_aligned(MMArch::PAGE_SIZE) {
524             return Err(SystemError::EINVAL);
525         }
526 
527         // 检查新、旧内存区域是否冲突
528         let old_region = VirtRegion::new(old_vaddr, old_len);
529         let new_region = VirtRegion::new(new_vaddr, new_len);
530         if old_region.collide(&new_region) {
531             return Err(SystemError::EINVAL);
532         }
533 
534         // 初始化映射标志
535         let mut map_flags: MapFlags = vm_flags.into();
536         // 初始化内存区域保护标志
537         let prot_flags: ProtFlags = vm_flags.into();
538 
539         // 取消新内存区域的原映射
540         if mremap_flags.contains(MremapFlags::MREMAP_FIXED) {
541             map_flags |= MapFlags::MAP_FIXED;
542             let start_page = VirtPageFrame::new(new_vaddr);
543             let page_count = PageFrameCount::from_bytes(new_len).unwrap();
544             self.munmap(start_page, page_count)?;
545         }
546 
547         // 获取映射后的新内存页面
548         let new_page = self.map_anonymous(new_vaddr, new_len, prot_flags, map_flags, true, true)?;
549         let new_page_vaddr = new_page.virt_address();
550 
551         // 拷贝旧内存区域内容到新内存区域
552         let old_buffer_reader =
553             UserBufferReader::new(old_vaddr.data() as *const u8, old_len, true)?;
554         let old_buf: &[u8] = old_buffer_reader.read_from_user(0)?;
555         let mut new_buffer_writer =
556             UserBufferWriter::new(new_page_vaddr.data() as *mut u8, new_len, true)?;
557         let new_buf: &mut [u8] = new_buffer_writer.buffer(0)?;
558         let len = old_buf.len().min(new_buf.len());
559         new_buf[..len].copy_from_slice(&old_buf[..len]);
560 
561         return Ok(new_page_vaddr);
562     }
563 
564     /// 取消进程的地址空间中的映射
565     ///
566     /// # 参数
567     ///
568     /// - `start_page`:起始页帧
569     /// - `page_count`:取消映射的页帧数量
570     ///
571     /// # Errors
572     ///
573     /// - `EINVAL`:参数错误
574     /// - `ENOMEM`:内存不足
575     pub fn munmap(
576         &mut self,
577         start_page: VirtPageFrame,
578         page_count: PageFrameCount,
579     ) -> Result<(), SystemError> {
580         let to_unmap = VirtRegion::new(start_page.virt_address(), page_count.bytes());
581         let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new();
582 
583         let regions: Vec<Arc<LockedVMA>> = self.mappings.conflicts(to_unmap).collect::<Vec<_>>();
584 
585         for r in regions {
586             let r = r.lock_irqsave().region;
587             let r = self.mappings.remove_vma(&r).unwrap();
588             let intersection = r.lock_irqsave().region().intersect(&to_unmap).unwrap();
589             let split_result = r.extract(intersection, &self.user_mapper.utable).unwrap();
590 
591             // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑
592 
593             if let Some(before) = split_result.prev {
594                 // 如果前面有VMA,则需要将前面的VMA重新插入到地址空间的VMA列表中
595                 self.mappings.insert_vma(before);
596             }
597 
598             if let Some(after) = split_result.after {
599                 // 如果后面有VMA,则需要将后面的VMA重新插入到地址空间的VMA列表中
600                 self.mappings.insert_vma(after);
601             }
602 
603             r.unmap(&mut self.user_mapper.utable, &mut flusher);
604         }
605 
606         // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑
607 
608         return Ok(());
609     }
610 
611     pub fn mprotect(
612         &mut self,
613         start_page: VirtPageFrame,
614         page_count: PageFrameCount,
615         prot_flags: ProtFlags,
616     ) -> Result<(), SystemError> {
617         // debug!(
618         //     "mprotect: start_page: {:?}, page_count: {:?}, prot_flags:{prot_flags:?}",
619         //     start_page,
620         //     page_count
621         // );
622         let (mut active, mut inactive);
623         let flusher = if self.is_current() {
624             active = PageFlushAll::new();
625             &mut active as &mut dyn Flusher<MMArch>
626         } else {
627             inactive = InactiveFlusher::new();
628             &mut inactive as &mut dyn Flusher<MMArch>
629         };
630 
631         let mapper = &mut self.user_mapper.utable;
632         let region = VirtRegion::new(start_page.virt_address(), page_count.bytes());
633         // debug!("mprotect: region: {:?}", region);
634 
635         let regions = self.mappings.conflicts(region).collect::<Vec<_>>();
636         // debug!("mprotect: regions: {:?}", regions);
637 
638         for r in regions {
639             // debug!("mprotect: r: {:?}", r);
640             let r = *r.lock_irqsave().region();
641             let r = self.mappings.remove_vma(&r).unwrap();
642 
643             let intersection = r.lock_irqsave().region().intersect(&region).unwrap();
644             let split_result = r
645                 .extract(intersection, mapper)
646                 .expect("Failed to extract VMA");
647 
648             if let Some(before) = split_result.prev {
649                 self.mappings.insert_vma(before);
650             }
651             if let Some(after) = split_result.after {
652                 self.mappings.insert_vma(after);
653             }
654 
655             let mut r_guard = r.lock_irqsave();
656             // 如果VMA的保护标志不允许指定的修改,则返回错误
657             if !r_guard.can_have_flags(prot_flags) {
658                 drop(r_guard);
659                 self.mappings.insert_vma(r.clone());
660                 return Err(SystemError::EACCES);
661             }
662             r_guard.set_vm_flags(VmFlags::from(prot_flags));
663 
664             let new_flags: EntryFlags<MMArch> = r_guard
665                 .flags()
666                 .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
667                 .set_write(prot_flags.contains(ProtFlags::PROT_WRITE));
668 
669             r_guard.remap(new_flags, mapper, &mut *flusher)?;
670             drop(r_guard);
671             self.mappings.insert_vma(r);
672         }
673 
674         return Ok(());
675     }
676 
677     pub fn madvise(
678         &mut self,
679         start_page: VirtPageFrame,
680         page_count: PageFrameCount,
681         behavior: MadvFlags,
682     ) -> Result<(), SystemError> {
683         let (mut active, mut inactive);
684         let flusher = if self.is_current() {
685             active = PageFlushAll::new();
686             &mut active as &mut dyn Flusher<MMArch>
687         } else {
688             inactive = InactiveFlusher::new();
689             &mut inactive as &mut dyn Flusher<MMArch>
690         };
691 
692         let mapper = &mut self.user_mapper.utable;
693 
694         let region = VirtRegion::new(start_page.virt_address(), page_count.bytes());
695         let regions = self.mappings.conflicts(region).collect::<Vec<_>>();
696 
697         for r in regions {
698             let r = *r.lock_irqsave().region();
699             let r = self.mappings.remove_vma(&r).unwrap();
700 
701             let intersection = r.lock_irqsave().region().intersect(&region).unwrap();
702             let split_result = r
703                 .extract(intersection, mapper)
704                 .expect("Failed to extract VMA");
705 
706             if let Some(before) = split_result.prev {
707                 self.mappings.insert_vma(before);
708             }
709             if let Some(after) = split_result.after {
710                 self.mappings.insert_vma(after);
711             }
712             r.do_madvise(behavior, mapper, &mut *flusher)?;
713             self.mappings.insert_vma(r);
714         }
715         Ok(())
716     }
717 
718     /// 创建新的用户栈
719     ///
720     /// ## 参数
721     ///
722     /// - `size`:栈的大小
723     pub fn new_user_stack(&mut self, size: usize) -> Result<(), SystemError> {
724         assert!(self.user_stack.is_none(), "User stack already exists");
725         let stack = UserStack::new(self, None, size)?;
726         self.user_stack = Some(stack);
727         return Ok(());
728     }
729 
730     #[inline(always)]
731     pub fn user_stack_mut(&mut self) -> Option<&mut UserStack> {
732         return self.user_stack.as_mut();
733     }
734 
735     /// 取消用户空间内的所有映射
736     pub unsafe fn unmap_all(&mut self) {
737         let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new();
738         for vma in self.mappings.iter_vmas() {
739             if vma.mapped() {
740                 vma.unmap(&mut self.user_mapper.utable, &mut flusher);
741             }
742         }
743     }
744 
745     /// 设置进程的堆的内存空间
746     ///
747     /// ## 参数
748     ///
749     /// - `new_brk`:新的堆的结束地址。需要满足页对齐要求,并且是用户空间地址,且大于等于当前的堆的起始地址
750     ///
751     /// ## 返回值
752     ///
753     /// 返回旧的堆的结束地址
754     pub unsafe fn set_brk(&mut self, new_brk: VirtAddr) -> Result<VirtAddr, SystemError> {
755         assert!(new_brk.check_aligned(MMArch::PAGE_SIZE));
756 
757         if !new_brk.check_user() || new_brk < self.brk_start {
758             return Err(SystemError::EFAULT);
759         }
760 
761         let old_brk = self.brk;
762 
763         if new_brk > self.brk {
764             let len = new_brk - self.brk;
765             let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC;
766             let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED;
767             self.map_anonymous(old_brk, len, prot_flags, map_flags, true, false)?;
768 
769             self.brk = new_brk;
770             return Ok(old_brk);
771         } else {
772             let unmap_len = self.brk - new_brk;
773             let unmap_start = new_brk;
774             if unmap_len == 0 {
775                 return Ok(old_brk);
776             }
777             self.munmap(
778                 VirtPageFrame::new(unmap_start),
779                 PageFrameCount::from_bytes(unmap_len).unwrap(),
780             )?;
781             self.brk = new_brk;
782             return Ok(old_brk);
783         }
784     }
785 
786     pub unsafe fn sbrk(&mut self, incr: isize) -> Result<VirtAddr, SystemError> {
787         if incr == 0 {
788             return Ok(self.brk);
789         }
790 
791         let new_brk = if incr > 0 {
792             self.brk + incr as usize
793         } else {
794             self.brk - incr.unsigned_abs()
795         };
796 
797         let new_brk = VirtAddr::new(page_align_up(new_brk.data()));
798 
799         return self.set_brk(new_brk);
800     }
801 }
802 
803 impl Drop for InnerAddressSpace {
804     fn drop(&mut self) {
805         unsafe {
806             self.unmap_all();
807         }
808     }
809 }
810 
811 #[derive(Debug, Hash)]
812 pub struct UserMapper {
813     pub utable: PageMapper,
814 }
815 
816 impl UserMapper {
817     pub fn new(utable: PageMapper) -> Self {
818         return Self { utable };
819     }
820 
821     /// 拷贝用户空间映射
822     /// ## 参数
823     ///
824     /// - `umapper`: 要拷贝的用户空间
825     /// - `copy_on_write`: 是否写时复制
826     pub unsafe fn clone_from(&mut self, umapper: &mut Self, copy_on_write: bool) {
827         self.utable
828             .clone_user_mapping(&mut umapper.utable, copy_on_write);
829     }
830 }
831 
832 impl Drop for UserMapper {
833     fn drop(&mut self) {
834         if self.utable.is_current() {
835             // 如果当前要被销毁的用户空间的页表是当前进程的页表,那么就切换回初始内核页表
836             unsafe { MMArch::set_table(PageTableKind::User, MMArch::initial_page_table()) }
837         }
838         // 释放用户空间顶层页表占用的页帧
839         // 请注意,在释放这个页帧之前,用户页表应该已经被完全释放,否则会产生内存泄露
840         unsafe {
841             deallocate_page_frames(
842                 PhysPageFrame::new(self.utable.table().phys()),
843                 PageFrameCount::new(1),
844                 &mut page_manager_lock_irqsave(),
845             )
846         };
847     }
848 }
849 
850 /// 用户空间映射信息
851 #[derive(Debug)]
852 pub struct UserMappings {
853     /// 当前用户空间的虚拟内存区域
854     vmas: HashSet<Arc<LockedVMA>>,
855     /// 当前用户空间的VMA空洞
856     vm_holes: BTreeMap<VirtAddr, usize>,
857 }
858 
859 impl UserMappings {
860     pub fn new() -> Self {
861         return Self {
862             vmas: HashSet::new(),
863             vm_holes: core::iter::once((VirtAddr::new(0), MMArch::USER_END_VADDR.data()))
864                 .collect::<BTreeMap<_, _>>(),
865         };
866     }
867 
868     /// 判断当前进程的VMA内,是否有包含指定的虚拟地址的VMA。
869     ///
870     /// 如果有,返回包含指定虚拟地址的VMA的Arc指针,否则返回None。
871     #[allow(dead_code)]
872     pub fn contains(&self, vaddr: VirtAddr) -> Option<Arc<LockedVMA>> {
873         for v in self.vmas.iter() {
874             let guard = v.lock_irqsave();
875             if guard.region.contains(vaddr) {
876                 return Some(v.clone());
877             }
878         }
879         return None;
880     }
881 
882     /// 向下寻找距离虚拟地址最近的VMA
883     /// ## 参数
884     ///
885     /// - `vaddr`: 虚拟地址
886     ///
887     /// ## 返回值
888     /// - Some(Arc<LockedVMA>): 虚拟地址所在的或最近的下一个VMA
889     /// - None: 未找到VMA
890     #[allow(dead_code)]
891     pub fn find_nearest(&self, vaddr: VirtAddr) -> Option<Arc<LockedVMA>> {
892         let mut nearest: Option<Arc<LockedVMA>> = None;
893         for v in self.vmas.iter() {
894             let guard = v.lock_irqsave();
895             if guard.region.contains(vaddr) {
896                 return Some(v.clone());
897             }
898             if guard.region.start >= vaddr
899                 && if let Some(ref nearest) = nearest {
900                     guard.region.start < nearest.lock_irqsave().region.start
901                 } else {
902                     true
903                 }
904             {
905                 nearest = Some(v.clone());
906             }
907         }
908         return nearest;
909     }
910 
911     /// 获取当前进程的地址空间中,与给定虚拟地址范围有重叠的VMA的迭代器。
912     pub fn conflicts(&self, request: VirtRegion) -> impl Iterator<Item = Arc<LockedVMA>> + '_ {
913         let r = self
914             .vmas
915             .iter()
916             .filter(move |v| v.lock_irqsave().region.intersect(&request).is_some())
917             .cloned();
918         return r;
919     }
920 
921     /// 在当前进程的地址空间中,寻找第一个符合条件的空闲的虚拟内存范围。
922     ///
923     /// @param min_vaddr 最小的起始地址
924     /// @param size 请求的大小
925     ///
926     /// @return 如果找到了,返回虚拟内存范围,否则返回None
927     pub fn find_free(&self, min_vaddr: VirtAddr, size: usize) -> Option<VirtRegion> {
928         let _vaddr = min_vaddr;
929         let mut iter = self
930             .vm_holes
931             .iter()
932             .skip_while(|(hole_vaddr, hole_size)| hole_vaddr.add(**hole_size) <= min_vaddr);
933 
934         let (hole_vaddr, size) = iter.find(|(hole_vaddr, hole_size)| {
935             // 计算当前空洞的可用大小
936             let available_size: usize =
937                 if hole_vaddr <= &&min_vaddr && min_vaddr <= hole_vaddr.add(**hole_size) {
938                     **hole_size - (min_vaddr - **hole_vaddr)
939                 } else {
940                     **hole_size
941                 };
942 
943             size <= available_size
944         })?;
945 
946         // 创建一个新的虚拟内存范围。
947         let region = VirtRegion::new(cmp::max(*hole_vaddr, min_vaddr), *size);
948 
949         return Some(region);
950     }
951 
952     pub fn find_free_at(
953         &self,
954         min_vaddr: VirtAddr,
955         vaddr: VirtAddr,
956         size: usize,
957         flags: MapFlags,
958     ) -> Result<VirtRegion, SystemError> {
959         // 如果没有指定地址,那么就在当前进程的地址空间中寻找一个空闲的虚拟内存范围。
960         if vaddr == VirtAddr::new(0) {
961             return self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM);
962         }
963 
964         // 如果指定了地址,那么就检查指定的地址是否可用。
965 
966         let requested = VirtRegion::new(vaddr, size);
967 
968         if requested.end() >= MMArch::USER_END_VADDR || !vaddr.check_aligned(MMArch::PAGE_SIZE) {
969             return Err(SystemError::EINVAL);
970         }
971 
972         if let Some(_x) = self.conflicts(requested).next() {
973             if flags.contains(MapFlags::MAP_FIXED_NOREPLACE) {
974                 // 如果指定了 MAP_FIXED_NOREPLACE 标志,由于所指定的地址无法成功建立映射,则放弃映射,不对地址做修正
975                 return Err(SystemError::EEXIST);
976             }
977 
978             if flags.contains(MapFlags::MAP_FIXED) {
979                 // todo: 支持MAP_FIXED标志对已有的VMA进行覆盖
980                 return Err(SystemError::ENOSYS);
981             }
982 
983             // 如果没有指定MAP_FIXED标志,那么就对地址做修正
984             let requested = self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM)?;
985             return Ok(requested);
986         }
987 
988         return Ok(requested);
989     }
990 
991     /// 在当前进程的地址空间中,保留一个指定大小的区域,使得该区域不在空洞中。
992     /// 该函数会修改vm_holes中的空洞信息。
993     ///
994     /// @param region 要保留的区域
995     ///
996     /// 请注意,在调用本函数之前,必须先确定region所在范围内没有VMA。
997     fn reserve_hole(&mut self, region: &VirtRegion) {
998         let prev_hole: Option<(&VirtAddr, &mut usize)> =
999             self.vm_holes.range_mut(..=region.start()).next_back();
1000 
1001         if let Some((prev_hole_vaddr, prev_hole_size)) = prev_hole {
1002             let prev_hole_end = prev_hole_vaddr.add(*prev_hole_size);
1003 
1004             if prev_hole_end > region.start() {
1005                 // 如果前一个空洞的结束地址大于当前空洞的起始地址,那么就需要调整前一个空洞的大小。
1006                 *prev_hole_size = region.start().data() - prev_hole_vaddr.data();
1007             }
1008 
1009             if prev_hole_end > region.end() {
1010                 // 如果前一个空洞的结束地址大于当前空洞的结束地址,那么就需要增加一个新的空洞。
1011                 self.vm_holes
1012                     .insert(region.end(), prev_hole_end - region.end());
1013             }
1014         }
1015     }
1016 
1017     /// 在当前进程的地址空间中,释放一个指定大小的区域,使得该区域成为一个空洞。
1018     /// 该函数会修改vm_holes中的空洞信息。
1019     fn unreserve_hole(&mut self, region: &VirtRegion) {
1020         // 如果将要插入的空洞与后一个空洞相邻,那么就需要合并。
1021         let next_hole_size: Option<usize> = self.vm_holes.remove(&region.end());
1022 
1023         if let Some((_prev_hole_vaddr, prev_hole_size)) = self
1024             .vm_holes
1025             .range_mut(..region.start())
1026             .next_back()
1027             .filter(|(offset, size)| offset.data() + **size == region.start().data())
1028         {
1029             *prev_hole_size += region.size() + next_hole_size.unwrap_or(0);
1030         } else {
1031             self.vm_holes
1032                 .insert(region.start(), region.size() + next_hole_size.unwrap_or(0));
1033         }
1034     }
1035 
1036     /// 在当前进程的映射关系中,插入一个新的VMA。
1037     pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) {
1038         let region = vma.lock_irqsave().region;
1039         // 要求插入的地址范围必须是空闲的,也就是说,当前进程的地址空间中,不能有任何与之重叠的VMA。
1040         assert!(self.conflicts(region).next().is_none());
1041         self.reserve_hole(&region);
1042 
1043         self.vmas.insert(vma);
1044     }
1045 
1046     /// @brief 删除一个VMA,并把对应的地址空间加入空洞中。
1047     ///
1048     /// 这里不会取消VMA对应的地址的映射
1049     ///
1050     /// @param region 要删除的VMA所在的地址范围
1051     ///
1052     /// @return 如果成功删除了VMA,则返回被删除的VMA,否则返回None
1053     /// 如果没有可以删除的VMA,则不会执行删除操作,并报告失败。
1054     pub fn remove_vma(&mut self, region: &VirtRegion) -> Option<Arc<LockedVMA>> {
1055         // 请注意,由于这里会对每个VMA加锁,因此性能很低
1056         let vma: Arc<LockedVMA> = self
1057             .vmas
1058             .drain_filter(|vma| vma.lock_irqsave().region == *region)
1059             .next()?;
1060         self.unreserve_hole(region);
1061 
1062         return Some(vma);
1063     }
1064 
1065     /// @brief Get the iterator of all VMAs in this process.
1066     pub fn iter_vmas(&self) -> hashbrown::hash_set::Iter<Arc<LockedVMA>> {
1067         return self.vmas.iter();
1068     }
1069 }
1070 
1071 impl Default for UserMappings {
1072     fn default() -> Self {
1073         return Self::new();
1074     }
1075 }
1076 
1077 /// 加了锁的VMA
1078 ///
1079 /// 备注:进行性能测试,看看SpinLock和RwLock哪个更快。
1080 #[derive(Debug)]
1081 pub struct LockedVMA {
1082     /// 用于计算哈希值,避免总是获取vma锁来计算哈希值
1083     id: usize,
1084     vma: SpinLock<VMA>,
1085 }
1086 
1087 impl core::hash::Hash for LockedVMA {
1088     fn hash<H: Hasher>(&self, state: &mut H) {
1089         self.id.hash(state);
1090     }
1091 }
1092 
1093 impl PartialEq for LockedVMA {
1094     fn eq(&self, other: &Self) -> bool {
1095         self.id.eq(&other.id)
1096     }
1097 }
1098 
1099 impl Eq for LockedVMA {}
1100 
1101 #[allow(dead_code)]
1102 impl LockedVMA {
1103     pub fn new(vma: VMA) -> Arc<Self> {
1104         let r = Arc::new(Self {
1105             id: LOCKEDVMA_ID_ALLOCATOR.lock().alloc().unwrap(),
1106             vma: SpinLock::new(vma),
1107         });
1108         r.vma.lock_irqsave().self_ref = Arc::downgrade(&r);
1109         return r;
1110     }
1111 
1112     pub fn id(&self) -> usize {
1113         self.id
1114     }
1115 
1116     pub fn lock(&self) -> SpinLockGuard<VMA> {
1117         return self.vma.lock();
1118     }
1119 
1120     pub fn lock_irqsave(&self) -> SpinLockGuard<VMA> {
1121         return self.vma.lock_irqsave();
1122     }
1123 
1124     /// 调整当前VMA的页面的标志位
1125     ///
1126     /// TODO:增加调整虚拟页映射的物理地址的功能
1127     ///
1128     /// @param flags 新的标志位
1129     /// @param mapper 页表映射器
1130     /// @param flusher 页表项刷新器
1131     ///
1132     pub fn remap(
1133         &self,
1134         flags: EntryFlags<MMArch>,
1135         mapper: &mut PageMapper,
1136         mut flusher: impl Flusher<MMArch>,
1137     ) -> Result<(), SystemError> {
1138         let mut guard = self.lock_irqsave();
1139         for page in guard.region.pages() {
1140             // 暂时要求所有的页帧都已经映射到页表
1141             // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了
1142             let r = unsafe {
1143                 mapper
1144                     .remap(page.virt_address(), flags)
1145                     .expect("Failed to remap, beacuse of some page is not mapped")
1146             };
1147             flusher.consume(r);
1148         }
1149         guard.flags = flags;
1150         return Ok(());
1151     }
1152 
1153     pub fn unmap(&self, mapper: &mut PageMapper, mut flusher: impl Flusher<MMArch>) {
1154         // todo: 如果当前vma与文件相关,完善文件相关的逻辑
1155 
1156         let mut guard = self.lock_irqsave();
1157 
1158         // 获取物理页的anon_vma的守卫
1159         let mut page_manager_guard: SpinLockGuard<'_, crate::mm::page::PageManager> =
1160             page_manager_lock_irqsave();
1161         for page in guard.region.pages() {
1162             if mapper.translate(page.virt_address()).is_none() {
1163                 continue;
1164             }
1165             let (paddr, _, flush) = unsafe { mapper.unmap_phys(page.virt_address(), true) }
1166                 .expect("Failed to unmap, beacuse of some page is not mapped");
1167 
1168             // 从anon_vma中删除当前VMA
1169             let page = page_manager_guard.get_unwrap(&paddr);
1170             page.write_irqsave().remove_vma(self);
1171 
1172             // 如果物理页的anon_vma链表长度为0并且不是共享页,则释放物理页.
1173             if page.read_irqsave().can_deallocate() {
1174                 unsafe {
1175                     drop(page);
1176                     deallocate_page_frames(
1177                         PhysPageFrame::new(paddr),
1178                         PageFrameCount::new(1),
1179                         &mut page_manager_guard,
1180                     )
1181                 };
1182             }
1183 
1184             flusher.consume(flush);
1185         }
1186         guard.mapped = false;
1187 
1188         // 当vma对应共享文件的写映射时,唤醒脏页回写线程
1189         if guard.vm_file().is_some()
1190             && guard
1191                 .vm_flags()
1192                 .contains(VmFlags::VM_SHARED | VmFlags::VM_WRITE)
1193         {
1194             crate::mm::page::PageReclaimer::wakeup_claim_thread();
1195         }
1196     }
1197 
1198     pub fn mapped(&self) -> bool {
1199         return self.vma.lock_irqsave().mapped;
1200     }
1201 
1202     /// 将当前VMA进行切分,切分成3个VMA,分别是:
1203     ///
1204     /// 1. 前面的VMA,如果没有则为None
1205     /// 2. 中间的VMA,也就是传入的Region
1206     /// 3. 后面的VMA,如果没有则为None
1207     pub fn extract(&self, region: VirtRegion, utable: &PageMapper) -> Option<VMASplitResult> {
1208         assert!(region.start().check_aligned(MMArch::PAGE_SIZE));
1209         assert!(region.end().check_aligned(MMArch::PAGE_SIZE));
1210 
1211         let mut guard = self.lock_irqsave();
1212         {
1213             // 如果传入的region不在当前VMA的范围内,则直接返回None
1214             if unlikely(region.start() < guard.region.start() || region.end() > guard.region.end())
1215             {
1216                 return None;
1217             }
1218 
1219             let intersect: Option<VirtRegion> = guard.region.intersect(&region);
1220             // 如果当前VMA不包含region,则直接返回None
1221             if unlikely(intersect.is_none()) {
1222                 return None;
1223             }
1224             let intersect: VirtRegion = intersect.unwrap();
1225             if unlikely(intersect == guard.region) {
1226                 // 如果当前VMA完全包含region,则直接返回当前VMA
1227                 return Some(VMASplitResult::new(
1228                     None,
1229                     guard.self_ref.upgrade().unwrap(),
1230                     None,
1231                 ));
1232             }
1233         }
1234 
1235         let before: Option<Arc<LockedVMA>> = guard.region.before(&region).map(|virt_region| {
1236             let mut vma: VMA = unsafe { guard.clone() };
1237             vma.region = virt_region;
1238             vma.mapped = false;
1239             let vma: Arc<LockedVMA> = LockedVMA::new(vma);
1240             vma
1241         });
1242 
1243         let after: Option<Arc<LockedVMA>> = guard.region.after(&region).map(|virt_region| {
1244             let mut vma: VMA = unsafe { guard.clone() };
1245             vma.region = virt_region;
1246             vma.mapped = false;
1247             let vma: Arc<LockedVMA> = LockedVMA::new(vma);
1248             vma
1249         });
1250 
1251         // 重新设置before、after这两个VMA里面的物理页的anon_vma
1252         let mut page_manager_guard = page_manager_lock_irqsave();
1253         if let Some(before) = before.clone() {
1254             let virt_iter = before.lock_irqsave().region.iter_pages();
1255             for frame in virt_iter {
1256                 if let Some((paddr, _)) = utable.translate(frame.virt_address()) {
1257                     let page = page_manager_guard.get_unwrap(&paddr);
1258                     let mut page_guard = page.write_irqsave();
1259                     page_guard.insert_vma(before.clone());
1260                     page_guard.remove_vma(self);
1261                     before.lock_irqsave().mapped = true;
1262                 }
1263             }
1264         }
1265 
1266         if let Some(after) = after.clone() {
1267             let virt_iter = after.lock_irqsave().region.iter_pages();
1268             for frame in virt_iter {
1269                 if let Some((paddr, _)) = utable.translate(frame.virt_address()) {
1270                     let page = page_manager_guard.get_unwrap(&paddr);
1271                     let mut page_guard = page.write_irqsave();
1272                     page_guard.insert_vma(after.clone());
1273                     page_guard.remove_vma(self);
1274                     after.lock_irqsave().mapped = true;
1275                 }
1276             }
1277         }
1278 
1279         guard.region = region;
1280 
1281         return Some(VMASplitResult::new(
1282             before,
1283             guard.self_ref.upgrade().unwrap(),
1284             after,
1285         ));
1286     }
1287 
1288     /// 判断VMA是否为外部(非当前进程空间)的VMA
1289     pub fn is_foreign(&self) -> bool {
1290         let guard = self.lock_irqsave();
1291         if let Some(space) = guard.user_address_space.clone() {
1292             if let Some(space) = space.upgrade() {
1293                 return AddressSpace::is_current(&space);
1294             } else {
1295                 return true;
1296             }
1297         } else {
1298             return true;
1299         }
1300     }
1301 
1302     /// 判断VMA是否可访问
1303     pub fn is_accessible(&self) -> bool {
1304         let guard = self.lock_irqsave();
1305         let vm_access_flags: VmFlags = VmFlags::VM_READ | VmFlags::VM_WRITE | VmFlags::VM_EXEC;
1306         guard.vm_flags().intersects(vm_access_flags)
1307     }
1308 
1309     /// 判断VMA是否为匿名映射
1310     pub fn is_anonymous(&self) -> bool {
1311         let guard = self.lock_irqsave();
1312         guard.vm_file.is_none()
1313     }
1314 
1315     /// 判断VMA是否为大页映射
1316     pub fn is_hugepage(&self) -> bool {
1317         //TODO: 实现巨页映射判断逻辑,目前不支持巨页映射
1318         false
1319     }
1320 }
1321 
1322 impl Drop for LockedVMA {
1323     fn drop(&mut self) {
1324         LOCKEDVMA_ID_ALLOCATOR.lock().free(self.id);
1325     }
1326 }
1327 
1328 /// VMA切分结果
1329 #[allow(dead_code)]
1330 pub struct VMASplitResult {
1331     pub prev: Option<Arc<LockedVMA>>,
1332     pub middle: Arc<LockedVMA>,
1333     pub after: Option<Arc<LockedVMA>>,
1334 }
1335 
1336 impl VMASplitResult {
1337     pub fn new(
1338         prev: Option<Arc<LockedVMA>>,
1339         middle: Arc<LockedVMA>,
1340         post: Option<Arc<LockedVMA>>,
1341     ) -> Self {
1342         Self {
1343             prev,
1344             middle,
1345             after: post,
1346         }
1347     }
1348 }
1349 
1350 /// @brief 虚拟内存区域
1351 #[derive(Debug)]
1352 pub struct VMA {
1353     /// 虚拟内存区域对应的虚拟地址范围
1354     region: VirtRegion,
1355     /// 虚拟内存区域标志
1356     vm_flags: VmFlags,
1357     /// VMA内的页帧的标志
1358     flags: EntryFlags<MMArch>,
1359     /// VMA内的页帧是否已经映射到页表
1360     mapped: bool,
1361     /// VMA所属的用户地址空间
1362     user_address_space: Option<Weak<AddressSpace>>,
1363     self_ref: Weak<LockedVMA>,
1364 
1365     vm_file: Option<Arc<File>>,
1366     /// VMA映射的文件部分相对于整个文件的偏移页数
1367     file_pgoff: Option<usize>,
1368 
1369     provider: Provider,
1370 }
1371 
1372 impl core::hash::Hash for VMA {
1373     fn hash<H: Hasher>(&self, state: &mut H) {
1374         self.region.hash(state);
1375         self.flags.hash(state);
1376         self.mapped.hash(state);
1377     }
1378 }
1379 
1380 /// 描述不同类型的内存提供者或资源
1381 #[derive(Debug)]
1382 pub enum Provider {
1383     Allocated, // TODO:其他
1384 }
1385 
1386 #[allow(dead_code)]
1387 impl VMA {
1388     pub fn new(
1389         region: VirtRegion,
1390         vm_flags: VmFlags,
1391         flags: EntryFlags<MMArch>,
1392         file: Option<Arc<File>>,
1393         pgoff: Option<usize>,
1394         mapped: bool,
1395     ) -> Self {
1396         VMA {
1397             region,
1398             vm_flags,
1399             flags,
1400             mapped,
1401             user_address_space: None,
1402             self_ref: Weak::default(),
1403             provider: Provider::Allocated,
1404             vm_file: file,
1405             file_pgoff: pgoff,
1406         }
1407     }
1408 
1409     pub fn region(&self) -> &VirtRegion {
1410         return &self.region;
1411     }
1412 
1413     pub fn vm_flags(&self) -> &VmFlags {
1414         return &self.vm_flags;
1415     }
1416 
1417     pub fn vm_file(&self) -> Option<Arc<File>> {
1418         return self.vm_file.clone();
1419     }
1420 
1421     pub fn address_space(&self) -> Option<Weak<AddressSpace>> {
1422         return self.user_address_space.clone();
1423     }
1424 
1425     pub fn set_vm_flags(&mut self, vm_flags: VmFlags) {
1426         self.vm_flags = vm_flags;
1427     }
1428 
1429     pub fn set_region_size(&mut self, new_region_size: usize) {
1430         self.region.set_size(new_region_size);
1431     }
1432 
1433     pub fn set_mapped(&mut self, mapped: bool) {
1434         self.mapped = mapped;
1435     }
1436 
1437     pub fn set_flags(&mut self) {
1438         self.flags = MMArch::vm_get_page_prot(self.vm_flags);
1439     }
1440 
1441     /// # 拷贝当前VMA的内容
1442     ///
1443     /// ### 安全性
1444     ///
1445     /// 由于这样操作可能由于错误的拷贝,导致内存泄露、内存重复释放等问题,所以需要小心使用。
1446     pub unsafe fn clone(&self) -> Self {
1447         return Self {
1448             region: self.region,
1449             vm_flags: self.vm_flags,
1450             flags: self.flags,
1451             mapped: self.mapped,
1452             user_address_space: self.user_address_space.clone(),
1453             self_ref: self.self_ref.clone(),
1454             provider: Provider::Allocated,
1455             file_pgoff: self.file_pgoff,
1456             vm_file: self.vm_file.clone(),
1457         };
1458     }
1459 
1460     pub fn clone_info_only(&self) -> Self {
1461         return Self {
1462             region: self.region,
1463             vm_flags: self.vm_flags,
1464             flags: self.flags,
1465             mapped: self.mapped,
1466             user_address_space: None,
1467             self_ref: Weak::default(),
1468             provider: Provider::Allocated,
1469             file_pgoff: self.file_pgoff,
1470             vm_file: self.vm_file.clone(),
1471         };
1472     }
1473 
1474     #[inline(always)]
1475     pub fn flags(&self) -> EntryFlags<MMArch> {
1476         return self.flags;
1477     }
1478 
1479     #[inline(always)]
1480     pub fn file_page_offset(&self) -> Option<usize> {
1481         return self.file_pgoff;
1482     }
1483 
1484     pub fn pages(&self) -> VirtPageFrameIter {
1485         return VirtPageFrameIter::new(
1486             VirtPageFrame::new(self.region.start()),
1487             VirtPageFrame::new(self.region.end()),
1488         );
1489     }
1490 
1491     pub fn remap(
1492         &mut self,
1493         flags: EntryFlags<MMArch>,
1494         mapper: &mut PageMapper,
1495         mut flusher: impl Flusher<MMArch>,
1496     ) -> Result<(), SystemError> {
1497         for page in self.region.pages() {
1498             // debug!("remap page {:?}", page.virt_address());
1499             if mapper.translate(page.virt_address()).is_some() {
1500                 let r = unsafe {
1501                     mapper
1502                         .remap(page.virt_address(), flags)
1503                         .expect("Failed to remap")
1504                 };
1505                 flusher.consume(r);
1506             }
1507             // debug!("consume page {:?}", page.virt_address());
1508             // debug!("remap page {:?} done", page.virt_address());
1509         }
1510         self.flags = flags;
1511         return Ok(());
1512     }
1513 
1514     /// 检查当前VMA是否可以拥有指定的标志位
1515     ///
1516     /// ## 参数
1517     ///
1518     /// - `prot_flags` 要检查的标志位
1519     pub fn can_have_flags(&self, prot_flags: ProtFlags) -> bool {
1520         let is_downgrade = (self.flags.has_write() || !prot_flags.contains(ProtFlags::PROT_WRITE))
1521             && (self.flags.has_execute() || !prot_flags.contains(ProtFlags::PROT_EXEC));
1522 
1523         match self.provider {
1524             Provider::Allocated { .. } => true,
1525 
1526             #[allow(unreachable_patterns)]
1527             _ => is_downgrade,
1528         }
1529     }
1530 
1531     /// 把物理地址映射到虚拟地址
1532     ///
1533     /// @param phys 要映射的物理地址
1534     /// @param destination 要映射到的虚拟地址
1535     /// @param count 要映射的页帧数量
1536     /// @param flags 页面标志位
1537     /// @param mapper 页表映射器
1538     /// @param flusher 页表项刷新器
1539     ///
1540     /// @return 返回映射后的虚拟内存区域
1541     pub fn physmap(
1542         phys: PhysPageFrame,
1543         destination: VirtPageFrame,
1544         count: PageFrameCount,
1545         vm_flags: VmFlags,
1546         flags: EntryFlags<MMArch>,
1547         mapper: &mut PageMapper,
1548         mut flusher: impl Flusher<MMArch>,
1549     ) -> Result<Arc<LockedVMA>, SystemError> {
1550         let mut cur_phy = phys;
1551         let mut cur_dest = destination;
1552 
1553         for _ in 0..count.data() {
1554             // 将物理页帧映射到虚拟页帧
1555             let r =
1556                 unsafe { mapper.map_phys(cur_dest.virt_address(), cur_phy.phys_address(), flags) }
1557                     .expect("Failed to map phys, may be OOM error");
1558 
1559             // todo: 增加OOM处理
1560 
1561             // 刷新TLB
1562             flusher.consume(r);
1563 
1564             cur_phy = cur_phy.next();
1565             cur_dest = cur_dest.next();
1566         }
1567 
1568         let r: Arc<LockedVMA> = LockedVMA::new(VMA::new(
1569             VirtRegion::new(destination.virt_address(), count.data() * MMArch::PAGE_SIZE),
1570             vm_flags,
1571             flags,
1572             None,
1573             None,
1574             true,
1575         ));
1576 
1577         // 将VMA加入到anon_vma中
1578         let mut page_manager_guard = page_manager_lock_irqsave();
1579         cur_phy = phys;
1580         for _ in 0..count.data() {
1581             let paddr = cur_phy.phys_address();
1582             let page = page_manager_guard.get_unwrap(&paddr);
1583             page.write_irqsave().insert_vma(r.clone());
1584             cur_phy = cur_phy.next();
1585         }
1586 
1587         return Ok(r);
1588     }
1589 
1590     /// 从页分配器中分配一些物理页,并把它们映射到指定的虚拟地址,然后创建VMA
1591     /// ## 参数
1592     ///
1593     /// - `destination`: 要映射到的虚拟地址
1594     /// - `page_count`: 要映射的页帧数量
1595     /// - `vm_flags`: VMA标志位
1596     /// - `flags`: 页面标志位
1597     /// - `mapper`: 页表映射器
1598     /// - `flusher`: 页表项刷新器
1599     /// - `file`: 映射文件
1600     /// - `pgoff`: 返回映射后的虚拟内存区域
1601     ///
1602     /// ## 返回值
1603     /// - 页面错误处理信息标志
1604     #[allow(clippy::too_many_arguments)]
1605     pub fn zeroed(
1606         destination: VirtPageFrame,
1607         page_count: PageFrameCount,
1608         vm_flags: VmFlags,
1609         flags: EntryFlags<MMArch>,
1610         mapper: &mut PageMapper,
1611         mut flusher: impl Flusher<MMArch>,
1612         file: Option<Arc<File>>,
1613         pgoff: Option<usize>,
1614     ) -> Result<Arc<LockedVMA>, SystemError> {
1615         let mut cur_dest: VirtPageFrame = destination;
1616         // debug!(
1617         //     "VMA::zeroed: page_count = {:?}, destination={destination:?}",
1618         //     page_count
1619         // );
1620         for _ in 0..page_count.data() {
1621             // debug!(
1622             //     "VMA::zeroed: cur_dest={cur_dest:?}, vaddr = {:?}",
1623             //     cur_dest.virt_address()
1624             // );
1625             let r = unsafe { mapper.map(cur_dest.virt_address(), flags) }
1626                 .expect("Failed to map zero, may be OOM error");
1627             // todo: 增加OOM处理
1628 
1629             // 稍后再刷新TLB,这里取消刷新
1630             flusher.consume(r);
1631             cur_dest = cur_dest.next();
1632         }
1633         let r = LockedVMA::new(VMA::new(
1634             VirtRegion::new(
1635                 destination.virt_address(),
1636                 page_count.data() * MMArch::PAGE_SIZE,
1637             ),
1638             vm_flags,
1639             flags,
1640             file,
1641             pgoff,
1642             true,
1643         ));
1644         drop(flusher);
1645         // debug!("VMA::zeroed: flusher dropped");
1646 
1647         // 清空这些内存并将VMA加入到anon_vma中
1648         let mut page_manager_guard = page_manager_lock_irqsave();
1649         let virt_iter: VirtPageFrameIter =
1650             VirtPageFrameIter::new(destination, destination.add(page_count));
1651         for frame in virt_iter {
1652             let paddr = mapper.translate(frame.virt_address()).unwrap().0;
1653 
1654             // 将VMA加入到anon_vma
1655             let page = page_manager_guard.get_unwrap(&paddr);
1656             page.write_irqsave().insert_vma(r.clone());
1657         }
1658         // debug!("VMA::zeroed: done");
1659         return Ok(r);
1660     }
1661 
1662     pub fn page_address(&self, page: &Arc<Page>) -> Result<VirtAddr, SystemError> {
1663         let page_guard = page.read_irqsave();
1664         let index = page_guard.index().unwrap();
1665         if index >= self.file_pgoff.unwrap() {
1666             let address =
1667                 self.region.start + ((index - self.file_pgoff.unwrap()) << MMArch::PAGE_SHIFT);
1668             if address <= self.region.end() {
1669                 return Ok(address);
1670             }
1671         }
1672         return Err(SystemError::EFAULT);
1673     }
1674 }
1675 
1676 impl Drop for VMA {
1677     fn drop(&mut self) {
1678         // 当VMA被释放时,需要确保它已经被从页表中解除映射
1679         assert!(!self.mapped, "VMA is still mapped");
1680     }
1681 }
1682 
1683 impl PartialEq for VMA {
1684     fn eq(&self, other: &Self) -> bool {
1685         return self.region == other.region;
1686     }
1687 }
1688 
1689 impl Eq for VMA {}
1690 
1691 impl PartialOrd for VMA {
1692     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
1693         Some(self.cmp(other))
1694     }
1695 }
1696 
1697 impl Ord for VMA {
1698     fn cmp(&self, other: &Self) -> cmp::Ordering {
1699         return self.region.cmp(&other.region);
1700     }
1701 }
1702 
1703 #[derive(Debug)]
1704 pub struct UserStack {
1705     // 栈底地址
1706     stack_bottom: VirtAddr,
1707     // 当前已映射的大小
1708     mapped_size: usize,
1709     /// 栈顶地址(这个值需要仔细确定!因为它可能不会实时与用户栈的真实栈顶保持一致!要小心!)
1710     current_sp: VirtAddr,
1711 }
1712 
1713 impl UserStack {
1714     /// 默认的用户栈底地址
1715     pub const DEFAULT_USER_STACK_BOTTOM: VirtAddr = MMArch::USER_STACK_START;
1716     /// 默认的用户栈大小为8MB
1717     pub const DEFAULT_USER_STACK_SIZE: usize = 8 * 1024 * 1024;
1718     /// 用户栈的保护页数量
1719     pub const GUARD_PAGES_NUM: usize = 4;
1720 
1721     /// 创建一个用户栈
1722     pub fn new(
1723         vm: &mut InnerAddressSpace,
1724         stack_bottom: Option<VirtAddr>,
1725         stack_size: usize,
1726     ) -> Result<Self, SystemError> {
1727         let stack_bottom = stack_bottom.unwrap_or(Self::DEFAULT_USER_STACK_BOTTOM);
1728         assert!(stack_bottom.check_aligned(MMArch::PAGE_SIZE));
1729 
1730         // 分配用户栈的保护页
1731         let guard_size = Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE;
1732         let actual_stack_bottom = stack_bottom - guard_size;
1733 
1734         let mut prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE;
1735         let map_flags = MapFlags::MAP_PRIVATE
1736             | MapFlags::MAP_ANONYMOUS
1737             | MapFlags::MAP_FIXED_NOREPLACE
1738             | MapFlags::MAP_GROWSDOWN;
1739         // debug!(
1740         //     "map anonymous stack: {:?} {}",
1741         //     actual_stack_bottom,
1742         //     guard_size
1743         // );
1744         vm.map_anonymous(
1745             actual_stack_bottom,
1746             guard_size,
1747             prot_flags,
1748             map_flags,
1749             false,
1750             false,
1751         )?;
1752         // test_buddy();
1753         // 设置保护页只读
1754         prot_flags.remove(ProtFlags::PROT_WRITE);
1755         // debug!(
1756         //     "to mprotect stack guard pages: {:?} {}",
1757         //     actual_stack_bottom,
1758         //     guard_size
1759         // );
1760         vm.mprotect(
1761             VirtPageFrame::new(actual_stack_bottom),
1762             PageFrameCount::new(Self::GUARD_PAGES_NUM),
1763             prot_flags,
1764         )?;
1765 
1766         // debug!(
1767         //     "mprotect stack guard pages done: {:?} {}",
1768         //     actual_stack_bottom,
1769         //     guard_size
1770         // );
1771 
1772         let mut user_stack = UserStack {
1773             stack_bottom: actual_stack_bottom,
1774             mapped_size: guard_size,
1775             current_sp: actual_stack_bottom - guard_size,
1776         };
1777 
1778         // debug!("extend user stack: {:?} {}", stack_bottom, stack_size);
1779         // 分配用户栈
1780         user_stack.initial_extend(vm, stack_size)?;
1781         // debug!("user stack created: {:?} {}", stack_bottom, stack_size);
1782         return Ok(user_stack);
1783     }
1784 
1785     fn initial_extend(
1786         &mut self,
1787         vm: &mut InnerAddressSpace,
1788         mut bytes: usize,
1789     ) -> Result<(), SystemError> {
1790         let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC;
1791         let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_GROWSDOWN;
1792 
1793         bytes = page_align_up(bytes);
1794         self.mapped_size += bytes;
1795 
1796         vm.map_anonymous(
1797             self.stack_bottom - self.mapped_size,
1798             bytes,
1799             prot_flags,
1800             map_flags,
1801             false,
1802             false,
1803         )?;
1804 
1805         return Ok(());
1806     }
1807 
1808     /// 扩展用户栈
1809     ///
1810     /// ## 参数
1811     ///
1812     /// - `vm` 用户地址空间结构体
1813     /// - `bytes` 要扩展的字节数
1814     ///
1815     /// ## 返回值
1816     ///
1817     /// - **Ok(())** 扩展成功
1818     /// - **Err(SystemError)** 扩展失败
1819     #[allow(dead_code)]
1820     pub fn extend(
1821         &mut self,
1822         vm: &mut InnerAddressSpace,
1823         mut bytes: usize,
1824     ) -> Result<(), SystemError> {
1825         let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC;
1826         let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS;
1827 
1828         bytes = page_align_up(bytes);
1829         self.mapped_size += bytes;
1830 
1831         vm.map_anonymous(
1832             self.stack_bottom - self.mapped_size,
1833             bytes,
1834             prot_flags,
1835             map_flags,
1836             false,
1837             false,
1838         )?;
1839 
1840         return Ok(());
1841     }
1842 
1843     /// 获取栈顶地址
1844     ///
1845     /// 请注意,如果用户栈的栈顶地址发生变化,这个值可能不会实时更新!
1846     pub fn sp(&self) -> VirtAddr {
1847         return self.current_sp;
1848     }
1849 
1850     pub unsafe fn set_sp(&mut self, sp: VirtAddr) {
1851         self.current_sp = sp;
1852     }
1853 
1854     /// 仅仅克隆用户栈的信息,不会克隆用户栈的内容/映射
1855     pub unsafe fn clone_info_only(&self) -> Self {
1856         return Self {
1857             stack_bottom: self.stack_bottom,
1858             mapped_size: self.mapped_size,
1859             current_sp: self.current_sp,
1860         };
1861     }
1862 
1863     /// 获取当前用户栈的大小(不包括保护页)
1864     pub fn stack_size(&self) -> usize {
1865         return self.mapped_size - Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE;
1866     }
1867 }
1868