xref: /DragonOS/kernel/src/mm/ucontext.rs (revision 81294aa2e6b257f0de5e3c28c3f3c89798330836)
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 system_error::SystemError;
18 
19 use crate::{
20     arch::{mm::PageMapper, CurrentIrqArch, MMArch},
21     exception::InterruptArch,
22     libs::{
23         align::page_align_up,
24         rwlock::{RwLock, RwLockWriteGuard},
25         spinlock::{SpinLock, SpinLockGuard},
26     },
27     process::ProcessManager,
28 };
29 
30 use super::{
31     allocator::page_frame::{
32         deallocate_page_frames, PageFrameCount, PhysPageFrame, VirtPageFrame, VirtPageFrameIter,
33     },
34     page::{Flusher, InactiveFlusher, PageFlags, PageFlushAll},
35     syscall::{MapFlags, ProtFlags},
36     MemoryManagementArch, PageTableKind, VirtAddr, VirtRegion,
37 };
38 
39 /// MMAP_MIN_ADDR的默认值
40 /// 以下内容来自linux-5.19:
41 ///  This is the portion of low virtual memory which should be protected
42 //   from userspace allocation.  Keeping a user from writing to low pages
43 //   can help reduce the impact of kernel NULL pointer bugs.
44 //   For most ia64, ppc64 and x86 users with lots of address space
45 //   a value of 65536 is reasonable and should cause no problems.
46 //   On arm and other archs it should not be higher than 32768.
47 //   Programs which use vm86 functionality or have some need to map
48 //   this low address space will need CAP_SYS_RAWIO or disable this
49 //   protection by setting the value to 0.
50 pub const DEFAULT_MMAP_MIN_ADDR: usize = 65536;
51 
52 #[derive(Debug)]
53 pub struct AddressSpace {
54     inner: RwLock<InnerAddressSpace>,
55 }
56 
57 impl AddressSpace {
58     pub fn new(create_stack: bool) -> Result<Arc<Self>, SystemError> {
59         let inner = InnerAddressSpace::new(create_stack)?;
60         let result = Self {
61             inner: RwLock::new(inner),
62         };
63         return Ok(Arc::new(result));
64     }
65 
66     /// 从pcb中获取当前进程的地址空间结构体的Arc指针
67     pub fn current() -> Result<Arc<AddressSpace>, SystemError> {
68         let vm = ProcessManager::current_pcb()
69             .basic()
70             .user_vm()
71             .expect("Current process has no address space");
72 
73         return Ok(vm);
74     }
75 
76     /// 判断某个地址空间是否为当前进程的地址空间
77     pub fn is_current(self: &Arc<Self>) -> bool {
78         let current = Self::current();
79         if let Ok(current) = current {
80             return Arc::ptr_eq(&current, self);
81         }
82         return false;
83     }
84 }
85 
86 impl core::ops::Deref for AddressSpace {
87     type Target = RwLock<InnerAddressSpace>;
88 
89     fn deref(&self) -> &Self::Target {
90         &self.inner
91     }
92 }
93 
94 impl core::ops::DerefMut for AddressSpace {
95     fn deref_mut(&mut self) -> &mut Self::Target {
96         &mut self.inner
97     }
98 }
99 
100 /// @brief 用户地址空间结构体(每个进程都有一个)
101 #[derive(Debug)]
102 pub struct InnerAddressSpace {
103     pub user_mapper: UserMapper,
104     pub mappings: UserMappings,
105     pub mmap_min: VirtAddr,
106     /// 用户栈信息结构体
107     pub user_stack: Option<UserStack>,
108 
109     pub elf_brk_start: VirtAddr,
110     pub elf_brk: VirtAddr,
111 
112     /// 当前进程的堆空间的起始地址
113     pub brk_start: VirtAddr,
114     /// 当前进程的堆空间的结束地址(不包含)
115     pub brk: VirtAddr,
116 
117     pub start_code: VirtAddr,
118     pub end_code: VirtAddr,
119     pub start_data: VirtAddr,
120     pub end_data: VirtAddr,
121 }
122 
123 impl InnerAddressSpace {
124     pub fn new(create_stack: bool) -> Result<Self, SystemError> {
125         let mut result = Self {
126             user_mapper: MMArch::setup_new_usermapper()?,
127             mappings: UserMappings::new(),
128             mmap_min: VirtAddr(DEFAULT_MMAP_MIN_ADDR),
129             elf_brk_start: VirtAddr::new(0),
130             elf_brk: VirtAddr::new(0),
131             brk_start: MMArch::USER_BRK_START,
132             brk: MMArch::USER_BRK_START,
133             user_stack: None,
134             start_code: VirtAddr(0),
135             end_code: VirtAddr(0),
136             start_data: VirtAddr(0),
137             end_data: VirtAddr(0),
138         };
139         if create_stack {
140             // kdebug!("to create user stack.");
141             result.new_user_stack(UserStack::DEFAULT_USER_STACK_SIZE)?;
142         }
143 
144         return Ok(result);
145     }
146 
147     /// 尝试克隆当前进程的地址空间,包括这些映射都会被克隆
148     ///
149     /// # Returns
150     ///
151     /// 返回克隆后的,新的地址空间的Arc指针
152     #[inline(never)]
153     pub fn try_clone(&mut self) -> Result<Arc<AddressSpace>, SystemError> {
154         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
155         let new_addr_space = AddressSpace::new(false)?;
156         let mut new_guard = new_addr_space.write();
157 
158         // 拷贝用户栈的结构体信息,但是不拷贝用户栈的内容(因为后面VMA的拷贝会拷贝用户栈的内容)
159         unsafe {
160             new_guard.user_stack = Some(self.user_stack.as_ref().unwrap().clone_info_only());
161         }
162         let _current_stack_size = self.user_stack.as_ref().unwrap().stack_size();
163 
164         let current_mapper = &mut self.user_mapper.utable;
165 
166         // 拷贝空洞
167         new_guard.mappings.vm_holes = self.mappings.vm_holes.clone();
168 
169         for vma in self.mappings.vmas.iter() {
170             // TODO: 增加对VMA是否为文件映射的判断,如果是的话,就跳过
171 
172             let vma_guard: SpinLockGuard<'_, VMA> = vma.lock();
173             let old_flags = vma_guard.flags();
174             let tmp_flags: PageFlags<MMArch> = PageFlags::new().set_write(true);
175 
176             // 分配内存页并创建新的VMA
177             let new_vma = VMA::zeroed(
178                 VirtPageFrame::new(vma_guard.region.start()),
179                 PageFrameCount::new(vma_guard.region.size() / MMArch::PAGE_SIZE),
180                 tmp_flags,
181                 &mut new_guard.user_mapper.utable,
182                 (),
183             )?;
184             new_guard.mappings.vmas.insert(new_vma.clone());
185             // kdebug!("new vma: {:x?}", new_vma);
186             let mut new_vma_guard = new_vma.lock();
187             for page in new_vma_guard.pages().map(|p| p.virt_address()) {
188                 // kdebug!("page: {:x?}", page);
189                 let current_frame = unsafe {
190                     MMArch::phys_2_virt(
191                         current_mapper
192                             .translate(page)
193                             .expect("VMA page not mapped")
194                             .0,
195                     )
196                 }
197                 .expect("Phys2Virt: vaddr overflow.")
198                 .data() as *mut u8;
199 
200                 let new_frame = unsafe {
201                     MMArch::phys_2_virt(
202                         new_guard
203                             .user_mapper
204                             .utable
205                             .translate(page)
206                             .expect("VMA page not mapped")
207                             .0,
208                     )
209                 }
210                 .expect("Phys2Virt: vaddr overflow.")
211                 .data() as *mut u8;
212 
213                 unsafe {
214                     // 拷贝数据
215                     new_frame.copy_from_nonoverlapping(current_frame, MMArch::PAGE_SIZE);
216                 }
217             }
218             drop(vma_guard);
219 
220             new_vma_guard.remap(old_flags, &mut new_guard.user_mapper.utable, ())?;
221             drop(new_vma_guard);
222         }
223         drop(new_guard);
224         drop(irq_guard);
225         return Ok(new_addr_space);
226     }
227 
228     /// 判断当前的地址空间是否是当前进程的地址空间
229     #[inline]
230     pub fn is_current(&self) -> bool {
231         return self.user_mapper.utable.is_current();
232     }
233 
234     /// 进行匿名页映射
235     ///
236     /// ## 参数
237     ///
238     /// - `start_vaddr`:映射的起始地址
239     /// - `len`:映射的长度
240     /// - `prot_flags`:保护标志
241     /// - `map_flags`:映射标志
242     /// - `round_to_min`:是否将`start_vaddr`对齐到`mmap_min`,如果为`true`,则当`start_vaddr`不为0时,会对齐到`mmap_min`,否则仅向下对齐到页边界
243     ///
244     /// ## 返回
245     ///
246     /// 返回映射的起始虚拟页帧
247     pub fn map_anonymous(
248         &mut self,
249         start_vaddr: VirtAddr,
250         len: usize,
251         prot_flags: ProtFlags,
252         map_flags: MapFlags,
253         round_to_min: bool,
254     ) -> Result<VirtPageFrame, SystemError> {
255         // 用于对齐hint的函数
256         let round_hint_to_min = |hint: VirtAddr| {
257             // 先把hint向下对齐到页边界
258             let addr = hint.data() & (!MMArch::PAGE_OFFSET_MASK);
259             // kdebug!("map_anonymous: hint = {:?}, addr = {addr:#x}", hint);
260             // 如果hint不是0,且hint小于DEFAULT_MMAP_MIN_ADDR,则对齐到DEFAULT_MMAP_MIN_ADDR
261             if (addr != 0) && round_to_min && (addr < DEFAULT_MMAP_MIN_ADDR) {
262                 Some(VirtAddr::new(page_align_up(DEFAULT_MMAP_MIN_ADDR)))
263             } else if addr == 0 {
264                 None
265             } else {
266                 Some(VirtAddr::new(addr))
267             }
268         };
269         // kdebug!("map_anonymous: start_vaddr = {:?}", start_vaddr);
270         // kdebug!("map_anonymous: len(no align) = {}", len);
271 
272         let len = page_align_up(len);
273 
274         // kdebug!("map_anonymous: len = {}", len);
275 
276         let start_page: VirtPageFrame = self.mmap(
277             round_hint_to_min(start_vaddr),
278             PageFrameCount::from_bytes(len).unwrap(),
279             prot_flags,
280             map_flags,
281             move |page, count, flags, mapper, flusher| {
282                 Ok(VMA::zeroed(page, count, flags, mapper, flusher)?)
283             },
284         )?;
285 
286         return Ok(start_page);
287     }
288 
289     /// 向进程的地址空间映射页面
290     ///
291     /// # 参数
292     ///
293     /// - `addr`:映射的起始地址,如果为`None`,则由内核自动分配
294     /// - `page_count`:映射的页面数量
295     /// - `prot_flags`:保护标志
296     /// - `map_flags`:映射标志
297     /// - `map_func`:映射函数,用于创建VMA
298     ///
299     /// # Returns
300     ///
301     /// 返回映射的起始虚拟页帧
302     ///
303     /// # Errors
304     ///
305     /// - `EINVAL`:参数错误
306     pub fn mmap<
307         F: FnOnce(
308             VirtPageFrame,
309             PageFrameCount,
310             PageFlags<MMArch>,
311             &mut PageMapper,
312             &mut dyn Flusher<MMArch>,
313         ) -> Result<Arc<LockedVMA>, SystemError>,
314     >(
315         &mut self,
316         addr: Option<VirtAddr>,
317         page_count: PageFrameCount,
318         prot_flags: ProtFlags,
319         map_flags: MapFlags,
320         map_func: F,
321     ) -> Result<VirtPageFrame, SystemError> {
322         if page_count == PageFrameCount::new(0) {
323             return Err(SystemError::EINVAL);
324         }
325         // kdebug!("mmap: addr: {addr:?}, page_count: {page_count:?}, prot_flags: {prot_flags:?}, map_flags: {map_flags:?}");
326 
327         // 找到未使用的区域
328         let region = match addr {
329             Some(vaddr) => {
330                 self.mappings
331                     .find_free_at(self.mmap_min, vaddr, page_count.bytes(), map_flags)?
332             }
333             None => self
334                 .mappings
335                 .find_free(self.mmap_min, page_count.bytes())
336                 .ok_or(SystemError::ENOMEM)?,
337         };
338 
339         let page = VirtPageFrame::new(region.start());
340 
341         // kdebug!("mmap: page: {:?}, region={region:?}", page.virt_address());
342 
343         compiler_fence(Ordering::SeqCst);
344         let (mut active, mut inactive);
345         let flusher = if self.is_current() {
346             active = PageFlushAll::new();
347             &mut active as &mut dyn Flusher<MMArch>
348         } else {
349             inactive = InactiveFlusher::new();
350             &mut inactive as &mut dyn Flusher<MMArch>
351         };
352         compiler_fence(Ordering::SeqCst);
353         // 映射页面,并将VMA插入到地址空间的VMA列表中
354         self.mappings.insert_vma(map_func(
355             page,
356             page_count,
357             PageFlags::from_prot_flags(prot_flags, true),
358             &mut self.user_mapper.utable,
359             flusher,
360         )?);
361 
362         return Ok(page);
363     }
364 
365     /// 取消进程的地址空间中的映射
366     ///
367     /// # 参数
368     ///
369     /// - `start_page`:起始页帧
370     /// - `page_count`:取消映射的页帧数量
371     ///
372     /// # Errors
373     ///
374     /// - `EINVAL`:参数错误
375     /// - `ENOMEM`:内存不足
376     pub fn munmap(
377         &mut self,
378         start_page: VirtPageFrame,
379         page_count: PageFrameCount,
380     ) -> Result<(), SystemError> {
381         let to_unmap = VirtRegion::new(start_page.virt_address(), page_count.bytes());
382         let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new();
383 
384         let regions: Vec<Arc<LockedVMA>> = self.mappings.conflicts(to_unmap).collect::<Vec<_>>();
385 
386         for r in regions {
387             let r = r.lock().region;
388             let r = self.mappings.remove_vma(&r).unwrap();
389             let intersection = r.lock().region().intersect(&to_unmap).unwrap();
390             let (before, r, after) = r.extract(intersection).unwrap();
391 
392             // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑
393 
394             if let Some(before) = before {
395                 // 如果前面有VMA,则需要将前面的VMA重新插入到地址空间的VMA列表中
396                 self.mappings.insert_vma(before);
397             }
398 
399             if let Some(after) = after {
400                 // 如果后面有VMA,则需要将后面的VMA重新插入到地址空间的VMA列表中
401                 self.mappings.insert_vma(after);
402             }
403 
404             r.unmap(&mut self.user_mapper.utable, &mut flusher);
405         }
406 
407         // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑
408 
409         return Ok(());
410     }
411 
412     pub fn mprotect(
413         &mut self,
414         start_page: VirtPageFrame,
415         page_count: PageFrameCount,
416         prot_flags: ProtFlags,
417     ) -> Result<(), SystemError> {
418         // kdebug!(
419         //     "mprotect: start_page: {:?}, page_count: {:?}, prot_flags:{prot_flags:?}",
420         //     start_page,
421         //     page_count
422         // );
423         let (mut active, mut inactive);
424         let mut flusher = if self.is_current() {
425             active = PageFlushAll::new();
426             &mut active as &mut dyn Flusher<MMArch>
427         } else {
428             inactive = InactiveFlusher::new();
429             &mut inactive as &mut dyn Flusher<MMArch>
430         };
431 
432         let mapper = &mut self.user_mapper.utable;
433         let region = VirtRegion::new(start_page.virt_address(), page_count.bytes());
434         // kdebug!("mprotect: region: {:?}", region);
435 
436         let regions = self.mappings.conflicts(region).collect::<Vec<_>>();
437         // kdebug!("mprotect: regions: {:?}", regions);
438 
439         for r in regions {
440             // kdebug!("mprotect: r: {:?}", r);
441             let r = r.lock().region().clone();
442             let r = self.mappings.remove_vma(&r).unwrap();
443 
444             let intersection = r.lock().region().intersect(&region).unwrap();
445             let (before, r, after) = r.extract(intersection).expect("Failed to extract VMA");
446 
447             if let Some(before) = before {
448                 self.mappings.insert_vma(before);
449             }
450             if let Some(after) = after {
451                 self.mappings.insert_vma(after);
452             }
453 
454             let mut r_guard = r.lock();
455             // 如果VMA的保护标志不允许指定的修改,则返回错误
456             if !r_guard.can_have_flags(prot_flags) {
457                 drop(r_guard);
458                 self.mappings.insert_vma(r.clone());
459                 return Err(SystemError::EACCES);
460             }
461 
462             let new_flags: PageFlags<MMArch> = r_guard
463                 .flags()
464                 .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
465                 .set_write(prot_flags.contains(ProtFlags::PROT_WRITE));
466 
467             r_guard.remap(new_flags, mapper, &mut flusher)?;
468             drop(r_guard);
469             self.mappings.insert_vma(r);
470         }
471 
472         return Ok(());
473     }
474 
475     /// 创建新的用户栈
476     ///
477     /// ## 参数
478     ///
479     /// - `size`:栈的大小
480     pub fn new_user_stack(&mut self, size: usize) -> Result<(), SystemError> {
481         assert!(self.user_stack.is_none(), "User stack already exists");
482         let stack = UserStack::new(self, None, size)?;
483         self.user_stack = Some(stack);
484         return Ok(());
485     }
486 
487     #[inline(always)]
488     pub fn user_stack_mut(&mut self) -> Option<&mut UserStack> {
489         return self.user_stack.as_mut();
490     }
491 
492     /// 取消用户空间内的所有映射
493     pub unsafe fn unmap_all(&mut self) {
494         let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new();
495         for vma in self.mappings.iter_vmas() {
496             vma.unmap(&mut self.user_mapper.utable, &mut flusher);
497         }
498     }
499 
500     /// 设置进程的堆的内存空间
501     ///
502     /// ## 参数
503     ///
504     /// - `new_brk`:新的堆的结束地址。需要满足页对齐要求,并且是用户空间地址,且大于等于当前的堆的起始地址
505     ///
506     /// ## 返回值
507     ///
508     /// 返回旧的堆的结束地址
509     pub unsafe fn set_brk(&mut self, new_brk: VirtAddr) -> Result<VirtAddr, SystemError> {
510         assert!(new_brk.check_aligned(MMArch::PAGE_SIZE));
511 
512         if !new_brk.check_user() || new_brk < self.brk_start {
513             return Err(SystemError::EFAULT);
514         }
515 
516         let old_brk = self.brk;
517 
518         if new_brk > self.brk {
519             let len = new_brk - self.brk;
520             let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC;
521             let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED;
522             self.map_anonymous(old_brk, len, prot_flags, map_flags, true)?;
523 
524             self.brk = new_brk;
525             return Ok(old_brk);
526         } else {
527             let unmap_len = self.brk - new_brk;
528             let unmap_start = new_brk;
529             if unmap_len == 0 {
530                 return Ok(old_brk);
531             }
532             self.munmap(
533                 VirtPageFrame::new(unmap_start),
534                 PageFrameCount::from_bytes(unmap_len).unwrap(),
535             )?;
536             self.brk = new_brk;
537             return Ok(old_brk);
538         }
539     }
540 
541     pub unsafe fn sbrk(&mut self, incr: isize) -> Result<VirtAddr, SystemError> {
542         if incr == 0 {
543             return Ok(self.brk);
544         }
545 
546         let new_brk = if incr > 0 {
547             self.brk + incr as usize
548         } else {
549             self.brk - (incr.abs() as usize)
550         };
551 
552         let new_brk = VirtAddr::new(page_align_up(new_brk.data()));
553 
554         return self.set_brk(new_brk);
555     }
556 }
557 
558 impl Drop for InnerAddressSpace {
559     fn drop(&mut self) {
560         unsafe {
561             self.unmap_all();
562         }
563     }
564 }
565 
566 #[derive(Debug, Hash)]
567 pub struct UserMapper {
568     pub utable: PageMapper,
569 }
570 
571 impl UserMapper {
572     pub fn new(utable: PageMapper) -> Self {
573         return Self { utable };
574     }
575 }
576 
577 impl Drop for UserMapper {
578     fn drop(&mut self) {
579         if self.utable.is_current() {
580             // 如果当前要被销毁的用户空间的页表是当前进程的页表,那么就切换回初始内核页表
581             unsafe { MMArch::set_table(PageTableKind::User, MMArch::initial_page_table()) }
582         }
583         // 释放用户空间顶层页表占用的页帧
584         // 请注意,在释放这个页帧之前,用户页表应该已经被完全释放,否则会产生内存泄露
585         unsafe {
586             deallocate_page_frames(
587                 PhysPageFrame::new(self.utable.table().phys()),
588                 PageFrameCount::new(1),
589             )
590         };
591     }
592 }
593 
594 /// 用户空间映射信息
595 #[derive(Debug)]
596 pub struct UserMappings {
597     /// 当前用户空间的虚拟内存区域
598     vmas: HashSet<Arc<LockedVMA>>,
599     /// 当前用户空间的VMA空洞
600     vm_holes: BTreeMap<VirtAddr, usize>,
601 }
602 
603 impl UserMappings {
604     pub fn new() -> Self {
605         return Self {
606             vmas: HashSet::new(),
607             vm_holes: core::iter::once((VirtAddr::new(0), MMArch::USER_END_VADDR.data()))
608                 .collect::<BTreeMap<_, _>>(),
609         };
610     }
611 
612     /// 判断当前进程的VMA内,是否有包含指定的虚拟地址的VMA。
613     ///
614     /// 如果有,返回包含指定虚拟地址的VMA的Arc指针,否则返回None。
615     #[allow(dead_code)]
616     pub fn contains(&self, vaddr: VirtAddr) -> Option<Arc<LockedVMA>> {
617         for v in self.vmas.iter() {
618             let guard = v.lock();
619             if guard.region.contains(vaddr) {
620                 return Some(v.clone());
621             }
622         }
623         return None;
624     }
625 
626     /// 获取当前进程的地址空间中,与给定虚拟地址范围有重叠的VMA的迭代器。
627     pub fn conflicts(&self, request: VirtRegion) -> impl Iterator<Item = Arc<LockedVMA>> + '_ {
628         let r = self
629             .vmas
630             .iter()
631             .filter(move |v| !v.lock().region.intersect(&request).is_none())
632             .cloned();
633         return r;
634     }
635 
636     /// 在当前进程的地址空间中,寻找第一个符合条件的空闲的虚拟内存范围。
637     ///
638     /// @param min_vaddr 最小的起始地址
639     /// @param size 请求的大小
640     ///
641     /// @return 如果找到了,返回虚拟内存范围,否则返回None
642     pub fn find_free(&self, min_vaddr: VirtAddr, size: usize) -> Option<VirtRegion> {
643         let _vaddr = min_vaddr;
644         let mut iter = self
645             .vm_holes
646             .iter()
647             .skip_while(|(hole_vaddr, hole_size)| hole_vaddr.add(**hole_size) <= min_vaddr);
648 
649         let (hole_vaddr, size) = iter.find(|(hole_vaddr, hole_size)| {
650             // 计算当前空洞的可用大小
651             let available_size: usize =
652                 if hole_vaddr <= &&min_vaddr && min_vaddr <= hole_vaddr.add(**hole_size) {
653                     **hole_size - (min_vaddr - **hole_vaddr)
654                 } else {
655                     **hole_size
656                 };
657 
658             size <= available_size
659         })?;
660 
661         // 创建一个新的虚拟内存范围。
662         let region = VirtRegion::new(cmp::max(*hole_vaddr, min_vaddr), *size);
663         return Some(region);
664     }
665 
666     pub fn find_free_at(
667         &self,
668         min_vaddr: VirtAddr,
669         vaddr: VirtAddr,
670         size: usize,
671         flags: MapFlags,
672     ) -> Result<VirtRegion, SystemError> {
673         // 如果没有指定地址,那么就在当前进程的地址空间中寻找一个空闲的虚拟内存范围。
674         if vaddr == VirtAddr::new(0) {
675             return self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM);
676         }
677 
678         // 如果指定了地址,那么就检查指定的地址是否可用。
679 
680         let requested = VirtRegion::new(vaddr, size);
681 
682         if requested.end() >= MMArch::USER_END_VADDR || !vaddr.check_aligned(MMArch::PAGE_SIZE) {
683             return Err(SystemError::EINVAL);
684         }
685 
686         if let Some(_x) = self.conflicts(requested).next() {
687             if flags.contains(MapFlags::MAP_FIXED_NOREPLACE) {
688                 // 如果指定了 MAP_FIXED_NOREPLACE 标志,由于所指定的地址无法成功建立映射,则放弃映射,不对地址做修正
689                 return Err(SystemError::EEXIST);
690             }
691 
692             if flags.contains(MapFlags::MAP_FIXED) {
693                 // todo: 支持MAP_FIXED标志对已有的VMA进行覆盖
694                 return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
695             }
696 
697             // 如果没有指定MAP_FIXED标志,那么就对地址做修正
698             let requested = self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM)?;
699             return Ok(requested);
700         }
701 
702         return Ok(requested);
703     }
704 
705     /// 在当前进程的地址空间中,保留一个指定大小的区域,使得该区域不在空洞中。
706     /// 该函数会修改vm_holes中的空洞信息。
707     ///
708     /// @param region 要保留的区域
709     ///
710     /// 请注意,在调用本函数之前,必须先确定region所在范围内没有VMA。
711     fn reserve_hole(&mut self, region: &VirtRegion) {
712         let prev_hole: Option<(&VirtAddr, &mut usize)> =
713             self.vm_holes.range_mut(..=region.start()).next_back();
714 
715         if let Some((prev_hole_vaddr, prev_hole_size)) = prev_hole {
716             let prev_hole_end = prev_hole_vaddr.add(*prev_hole_size);
717 
718             if prev_hole_end > region.start() {
719                 // 如果前一个空洞的结束地址大于当前空洞的起始地址,那么就需要调整前一个空洞的大小。
720                 *prev_hole_size = region.start().data() - prev_hole_vaddr.data();
721             }
722 
723             if prev_hole_end > region.end() {
724                 // 如果前一个空洞的结束地址大于当前空洞的结束地址,那么就需要增加一个新的空洞。
725                 self.vm_holes
726                     .insert(region.end(), prev_hole_end - region.end());
727             }
728         }
729     }
730 
731     /// 在当前进程的地址空间中,释放一个指定大小的区域,使得该区域成为一个空洞。
732     /// 该函数会修改vm_holes中的空洞信息。
733     fn unreserve_hole(&mut self, region: &VirtRegion) {
734         // 如果将要插入的空洞与后一个空洞相邻,那么就需要合并。
735         let next_hole_size: Option<usize> = self.vm_holes.remove(&region.end());
736 
737         if let Some((_prev_hole_vaddr, prev_hole_size)) = self
738             .vm_holes
739             .range_mut(..region.start())
740             .next_back()
741             .filter(|(offset, size)| offset.data() + **size == region.start().data())
742         {
743             *prev_hole_size += region.size() + next_hole_size.unwrap_or(0);
744         } else {
745             self.vm_holes
746                 .insert(region.start(), region.size() + next_hole_size.unwrap_or(0));
747         }
748     }
749 
750     /// 在当前进程的映射关系中,插入一个新的VMA。
751     pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) {
752         let region = vma.lock().region.clone();
753         // 要求插入的地址范围必须是空闲的,也就是说,当前进程的地址空间中,不能有任何与之重叠的VMA。
754         assert!(self.conflicts(region).next().is_none());
755         self.reserve_hole(&region);
756 
757         self.vmas.insert(vma);
758     }
759 
760     /// @brief 删除一个VMA,并把对应的地址空间加入空洞中。
761     ///
762     /// 这里不会取消VMA对应的地址的映射
763     ///
764     /// @param region 要删除的VMA所在的地址范围
765     ///
766     /// @return 如果成功删除了VMA,则返回被删除的VMA,否则返回None
767     /// 如果没有可以删除的VMA,则不会执行删除操作,并报告失败。
768     pub fn remove_vma(&mut self, region: &VirtRegion) -> Option<Arc<LockedVMA>> {
769         // 请注意,由于这里会对每个VMA加锁,因此性能很低
770         let vma: Arc<LockedVMA> = self
771             .vmas
772             .drain_filter(|vma| vma.lock().region == *region)
773             .next()?;
774         self.unreserve_hole(region);
775 
776         return Some(vma);
777     }
778 
779     /// @brief Get the iterator of all VMAs in this process.
780     pub fn iter_vmas(&self) -> hashbrown::hash_set::Iter<Arc<LockedVMA>> {
781         return self.vmas.iter();
782     }
783 }
784 
785 impl Default for UserMappings {
786     fn default() -> Self {
787         return Self::new();
788     }
789 }
790 
791 /// 加了锁的VMA
792 ///
793 /// 备注:进行性能测试,看看SpinLock和RwLock哪个更快。
794 #[derive(Debug)]
795 pub struct LockedVMA(SpinLock<VMA>);
796 
797 impl core::hash::Hash for LockedVMA {
798     fn hash<H: Hasher>(&self, state: &mut H) {
799         self.0.lock().hash(state);
800     }
801 }
802 
803 impl PartialEq for LockedVMA {
804     fn eq(&self, other: &Self) -> bool {
805         self.0.lock().eq(&other.0.lock())
806     }
807 }
808 
809 impl Eq for LockedVMA {}
810 
811 #[allow(dead_code)]
812 impl LockedVMA {
813     pub fn new(vma: VMA) -> Arc<Self> {
814         let r = Arc::new(Self(SpinLock::new(vma)));
815         r.0.lock().self_ref = Arc::downgrade(&r);
816         return r;
817     }
818 
819     pub fn lock(&self) -> SpinLockGuard<VMA> {
820         return self.0.lock();
821     }
822 
823     /// 调整当前VMA的页面的标志位
824     ///
825     /// TODO:增加调整虚拟页映射的物理地址的功能
826     ///
827     /// @param flags 新的标志位
828     /// @param mapper 页表映射器
829     /// @param flusher 页表项刷新器
830     ///
831     pub fn remap(
832         &self,
833         flags: PageFlags<MMArch>,
834         mapper: &mut PageMapper,
835         mut flusher: impl Flusher<MMArch>,
836     ) -> Result<(), SystemError> {
837         let mut guard = self.lock();
838         assert!(guard.mapped);
839         for page in guard.region.pages() {
840             // 暂时要求所有的页帧都已经映射到页表
841             // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了
842             let r = unsafe {
843                 mapper
844                     .remap(page.virt_address(), flags)
845                     .expect("Failed to remap, beacuse of some page is not mapped")
846             };
847             flusher.consume(r);
848         }
849         guard.flags = flags;
850         return Ok(());
851     }
852 
853     pub fn unmap(&self, mapper: &mut PageMapper, mut flusher: impl Flusher<MMArch>) {
854         // todo: 如果当前vma与文件相关,完善文件相关的逻辑
855 
856         let mut guard = self.lock();
857         assert!(guard.mapped);
858         for page in guard.region.pages() {
859             let (paddr, _, flush) = unsafe { mapper.unmap_phys(page.virt_address(), true) }
860                 .expect("Failed to unmap, beacuse of some page is not mapped");
861 
862             // todo: 获取物理页的anon_vma的守卫
863 
864             // todo: 从anon_vma中删除当前VMA
865 
866             // todo: 如果物理页的anon_vma链表长度为0,则释放物理页.
867 
868             // 目前由于还没有实现共享页,所以直接释放物理页也没问题。
869             // 但是在实现共享页之后,就不能直接释放物理页了,需要在anon_vma链表长度为0的时候才能释放物理页
870             unsafe { deallocate_page_frames(PhysPageFrame::new(paddr), PageFrameCount::new(1)) };
871 
872             flusher.consume(flush);
873         }
874         guard.mapped = false;
875     }
876 
877     pub fn mapped(&self) -> bool {
878         return self.0.lock().mapped;
879     }
880 
881     /// 将当前VMA进行切分,切分成3个VMA,分别是:
882     ///
883     /// 1. 前面的VMA,如果没有则为None
884     /// 2. 中间的VMA,也就是传入的Region
885     /// 3. 后面的VMA,如果没有则为None
886     pub fn extract(
887         &self,
888         region: VirtRegion,
889     ) -> Option<(
890         Option<Arc<LockedVMA>>,
891         Arc<LockedVMA>,
892         Option<Arc<LockedVMA>>,
893     )> {
894         assert!(region.start().check_aligned(MMArch::PAGE_SIZE));
895         assert!(region.end().check_aligned(MMArch::PAGE_SIZE));
896 
897         let mut guard = self.lock();
898         {
899             // 如果传入的region不在当前VMA的范围内,则直接返回None
900             if unlikely(region.start() < guard.region.start() || region.end() > guard.region.end())
901             {
902                 return None;
903             }
904 
905             let intersect: Option<VirtRegion> = guard.region.intersect(&region);
906             // 如果当前VMA不包含region,则直接返回None
907             if unlikely(intersect.is_none()) {
908                 return None;
909             }
910             let intersect: VirtRegion = intersect.unwrap();
911             if unlikely(intersect == guard.region) {
912                 // 如果当前VMA完全包含region,则直接返回当前VMA
913                 return Some((None, guard.self_ref.upgrade().unwrap(), None));
914             }
915         }
916 
917         let before: Option<Arc<LockedVMA>> = guard.region.before(&region).map(|virt_region| {
918             let mut vma: VMA = unsafe { guard.clone() };
919             vma.region = virt_region;
920 
921             let vma: Arc<LockedVMA> = LockedVMA::new(vma);
922             vma
923         });
924 
925         let after: Option<Arc<LockedVMA>> = guard.region.after(&region).map(|virt_region| {
926             let mut vma: VMA = unsafe { guard.clone() };
927             vma.region = virt_region;
928 
929             let vma: Arc<LockedVMA> = LockedVMA::new(vma);
930             vma
931         });
932 
933         guard.region = region;
934 
935         // TODO: 重新设置before、after这两个VMA里面的物理页的anon_vma
936 
937         return Some((before, guard.self_ref.upgrade().unwrap(), after));
938     }
939 }
940 
941 /// @brief 虚拟内存区域
942 #[derive(Debug)]
943 pub struct VMA {
944     /// 虚拟内存区域对应的虚拟地址范围
945     region: VirtRegion,
946     /// VMA内的页帧的标志
947     flags: PageFlags<MMArch>,
948     /// VMA内的页帧是否已经映射到页表
949     mapped: bool,
950     /// VMA所属的用户地址空间
951     user_address_space: Option<Weak<AddressSpace>>,
952     self_ref: Weak<LockedVMA>,
953 
954     provider: Provider,
955 }
956 
957 impl core::hash::Hash for VMA {
958     fn hash<H: Hasher>(&self, state: &mut H) {
959         self.region.hash(state);
960         self.flags.hash(state);
961         self.mapped.hash(state);
962     }
963 }
964 
965 /// 描述不同类型的内存提供者或资源
966 #[derive(Debug)]
967 pub enum Provider {
968     Allocated, // TODO:其他
969 }
970 
971 #[allow(dead_code)]
972 impl VMA {
973     pub fn region(&self) -> &VirtRegion {
974         return &self.region;
975     }
976 
977     /// # 拷贝当前VMA的内容
978     ///
979     /// ### 安全性
980     ///
981     /// 由于这样操作可能由于错误的拷贝,导致内存泄露、内存重复释放等问题,所以需要小心使用。
982     pub unsafe fn clone(&self) -> Self {
983         return Self {
984             region: self.region,
985             flags: self.flags,
986             mapped: self.mapped,
987             user_address_space: self.user_address_space.clone(),
988             self_ref: self.self_ref.clone(),
989             provider: Provider::Allocated,
990         };
991     }
992 
993     #[inline(always)]
994     pub fn flags(&self) -> PageFlags<MMArch> {
995         return self.flags;
996     }
997 
998     pub fn pages(&self) -> VirtPageFrameIter {
999         return VirtPageFrameIter::new(
1000             VirtPageFrame::new(self.region.start()),
1001             VirtPageFrame::new(self.region.end()),
1002         );
1003     }
1004 
1005     pub fn remap(
1006         &mut self,
1007         flags: PageFlags<MMArch>,
1008         mapper: &mut PageMapper,
1009         mut flusher: impl Flusher<MMArch>,
1010     ) -> Result<(), SystemError> {
1011         assert!(self.mapped);
1012         for page in self.region.pages() {
1013             // kdebug!("remap page {:?}", page.virt_address());
1014             // 暂时要求所有的页帧都已经映射到页表
1015             // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了
1016             let r = unsafe {
1017                 mapper
1018                     .remap(page.virt_address(), flags)
1019                     .expect("Failed to remap, beacuse of some page is not mapped")
1020             };
1021             // kdebug!("consume page {:?}", page.virt_address());
1022             flusher.consume(r);
1023             // kdebug!("remap page {:?} done", page.virt_address());
1024         }
1025         self.flags = flags;
1026         return Ok(());
1027     }
1028 
1029     /// 检查当前VMA是否可以拥有指定的标志位
1030     ///
1031     /// ## 参数
1032     ///
1033     /// - `prot_flags` 要检查的标志位
1034     pub fn can_have_flags(&self, prot_flags: ProtFlags) -> bool {
1035         let is_downgrade = (self.flags.has_write() || !prot_flags.contains(ProtFlags::PROT_WRITE))
1036             && (self.flags.has_execute() || !prot_flags.contains(ProtFlags::PROT_EXEC));
1037 
1038         match self.provider {
1039             Provider::Allocated { .. } => true,
1040 
1041             #[allow(unreachable_patterns)]
1042             _ => is_downgrade,
1043         }
1044     }
1045 
1046     /// 把物理地址映射到虚拟地址
1047     ///
1048     /// @param phys 要映射的物理地址
1049     /// @param destination 要映射到的虚拟地址
1050     /// @param count 要映射的页帧数量
1051     /// @param flags 页面标志位
1052     /// @param mapper 页表映射器
1053     /// @param flusher 页表项刷新器
1054     ///
1055     /// @return 返回映射后的虚拟内存区域
1056     pub fn physmap(
1057         phys: PhysPageFrame,
1058         destination: VirtPageFrame,
1059         count: PageFrameCount,
1060         flags: PageFlags<MMArch>,
1061         mapper: &mut PageMapper,
1062         mut flusher: impl Flusher<MMArch>,
1063     ) -> Result<Arc<LockedVMA>, SystemError> {
1064         {
1065             let mut cur_phy = phys;
1066             let mut cur_dest = destination;
1067 
1068             for _ in 0..count.data() {
1069                 // 将物理页帧映射到虚拟页帧
1070                 let r = unsafe {
1071                     mapper.map_phys(cur_dest.virt_address(), cur_phy.phys_address(), flags)
1072                 }
1073                 .expect("Failed to map phys, may be OOM error");
1074 
1075                 // todo: 增加OOM处理
1076 
1077                 // todo: 将VMA加入到anon_vma中
1078 
1079                 // 刷新TLB
1080                 flusher.consume(r);
1081 
1082                 cur_phy = cur_phy.next();
1083                 cur_dest = cur_dest.next();
1084             }
1085         }
1086 
1087         let r: Arc<LockedVMA> = LockedVMA::new(VMA {
1088             region: VirtRegion::new(destination.virt_address(), count.data() * MMArch::PAGE_SIZE),
1089             flags,
1090             mapped: true,
1091             user_address_space: None,
1092             self_ref: Weak::default(),
1093             provider: Provider::Allocated,
1094         });
1095         return Ok(r);
1096     }
1097 
1098     /// 从页分配器中分配一些物理页,并把它们映射到指定的虚拟地址,然后创建VMA
1099     ///
1100     /// @param destination 要映射到的虚拟地址
1101     /// @param count 要映射的页帧数量
1102     /// @param flags 页面标志位
1103     /// @param mapper 页表映射器
1104     /// @param flusher 页表项刷新器
1105     ///
1106     /// @return 返回映射后的虚拟内存区域
1107     pub fn zeroed(
1108         destination: VirtPageFrame,
1109         page_count: PageFrameCount,
1110         flags: PageFlags<MMArch>,
1111         mapper: &mut PageMapper,
1112         mut flusher: impl Flusher<MMArch>,
1113     ) -> Result<Arc<LockedVMA>, SystemError> {
1114         let mut cur_dest: VirtPageFrame = destination;
1115         // kdebug!(
1116         //     "VMA::zeroed: page_count = {:?}, destination={destination:?}",
1117         //     page_count
1118         // );
1119         for _ in 0..page_count.data() {
1120             // kdebug!(
1121             //     "VMA::zeroed: cur_dest={cur_dest:?}, vaddr = {:?}",
1122             //     cur_dest.virt_address()
1123             // );
1124             let r = unsafe { mapper.map(cur_dest.virt_address(), flags) }
1125                 .expect("Failed to map zero, may be OOM error");
1126             // todo: 将VMA加入到anon_vma中
1127             // todo: 增加OOM处理
1128 
1129             // 稍后再刷新TLB,这里取消刷新
1130             flusher.consume(r);
1131             cur_dest = cur_dest.next();
1132         }
1133         let r = LockedVMA::new(VMA {
1134             region: VirtRegion::new(
1135                 destination.virt_address(),
1136                 page_count.data() * MMArch::PAGE_SIZE,
1137             ),
1138             flags,
1139             mapped: true,
1140             user_address_space: None,
1141             self_ref: Weak::default(),
1142             provider: Provider::Allocated,
1143         });
1144         drop(flusher);
1145         // kdebug!("VMA::zeroed: flusher dropped");
1146 
1147         // 清空这些内存
1148         let virt_iter: VirtPageFrameIter =
1149             VirtPageFrameIter::new(destination, destination.add(page_count));
1150         for frame in virt_iter {
1151             let paddr = mapper.translate(frame.virt_address()).unwrap().0;
1152 
1153             unsafe {
1154                 let vaddr = MMArch::phys_2_virt(paddr).unwrap();
1155                 MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE);
1156             }
1157         }
1158         // kdebug!("VMA::zeroed: done");
1159         return Ok(r);
1160     }
1161 }
1162 
1163 impl Drop for VMA {
1164     fn drop(&mut self) {
1165         // 当VMA被释放时,需要确保它已经被从页表中解除映射
1166         assert!(!self.mapped, "VMA is still mapped");
1167     }
1168 }
1169 
1170 impl PartialEq for VMA {
1171     fn eq(&self, other: &Self) -> bool {
1172         return self.region == other.region;
1173     }
1174 }
1175 
1176 impl Eq for VMA {}
1177 
1178 impl PartialOrd for VMA {
1179     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
1180         return self.region.partial_cmp(&other.region);
1181     }
1182 }
1183 
1184 impl Ord for VMA {
1185     fn cmp(&self, other: &Self) -> cmp::Ordering {
1186         return self.region.cmp(&other.region);
1187     }
1188 }
1189 
1190 #[derive(Debug)]
1191 pub struct UserStack {
1192     // 栈底地址
1193     stack_bottom: VirtAddr,
1194     // 当前已映射的大小
1195     mapped_size: usize,
1196     /// 栈顶地址(这个值需要仔细确定!因为它可能不会实时与用户栈的真实栈顶保持一致!要小心!)
1197     current_sp: VirtAddr,
1198 }
1199 
1200 impl UserStack {
1201     /// 默认的用户栈底地址
1202     pub const DEFAULT_USER_STACK_BOTTOM: VirtAddr = MMArch::USER_STACK_START;
1203     /// 默认的用户栈大小为8MB
1204     pub const DEFAULT_USER_STACK_SIZE: usize = 8 * 1024 * 1024;
1205     /// 用户栈的保护页数量
1206     pub const GUARD_PAGES_NUM: usize = 4;
1207 
1208     /// 创建一个用户栈
1209     pub fn new(
1210         vm: &mut InnerAddressSpace,
1211         stack_bottom: Option<VirtAddr>,
1212         stack_size: usize,
1213     ) -> Result<Self, SystemError> {
1214         let stack_bottom = stack_bottom.unwrap_or(Self::DEFAULT_USER_STACK_BOTTOM);
1215         assert!(stack_bottom.check_aligned(MMArch::PAGE_SIZE));
1216 
1217         // 分配用户栈的保护页
1218         let guard_size = Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE;
1219         let actual_stack_bottom = stack_bottom - guard_size;
1220 
1221         let mut prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE;
1222         let map_flags =
1223             MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED_NOREPLACE;
1224         // kdebug!(
1225         //     "map anonymous stack: {:?} {}",
1226         //     actual_stack_bottom,
1227         //     guard_size
1228         // );
1229         vm.map_anonymous(
1230             actual_stack_bottom,
1231             guard_size,
1232             prot_flags,
1233             map_flags,
1234             false,
1235         )?;
1236         // test_buddy();
1237         // 设置保护页只读
1238         prot_flags.remove(ProtFlags::PROT_WRITE);
1239         // kdebug!(
1240         //     "to mprotect stack guard pages: {:?} {}",
1241         //     actual_stack_bottom,
1242         //     guard_size
1243         // );
1244         vm.mprotect(
1245             VirtPageFrame::new(actual_stack_bottom),
1246             PageFrameCount::new(Self::GUARD_PAGES_NUM),
1247             prot_flags,
1248         )?;
1249 
1250         // kdebug!(
1251         //     "mprotect stack guard pages done: {:?} {}",
1252         //     actual_stack_bottom,
1253         //     guard_size
1254         // );
1255 
1256         let mut user_stack = UserStack {
1257             stack_bottom: actual_stack_bottom,
1258             mapped_size: guard_size,
1259             current_sp: actual_stack_bottom - guard_size,
1260         };
1261 
1262         // kdebug!("extend user stack: {:?} {}", stack_bottom, stack_size);
1263         // 分配用户栈
1264         user_stack.initial_extend(vm, stack_size)?;
1265         // kdebug!("user stack created: {:?} {}", stack_bottom, stack_size);
1266         return Ok(user_stack);
1267     }
1268 
1269     fn initial_extend(
1270         &mut self,
1271         vm: &mut InnerAddressSpace,
1272         mut bytes: usize,
1273     ) -> Result<(), SystemError> {
1274         let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC;
1275         let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS;
1276 
1277         bytes = page_align_up(bytes);
1278         self.mapped_size += bytes;
1279 
1280         vm.map_anonymous(
1281             self.stack_bottom - self.mapped_size,
1282             bytes,
1283             prot_flags,
1284             map_flags,
1285             false,
1286         )?;
1287 
1288         return Ok(());
1289     }
1290 
1291     /// 扩展用户栈
1292     ///
1293     /// ## 参数
1294     ///
1295     /// - `vm` 用户地址空间结构体
1296     /// - `bytes` 要扩展的字节数
1297     ///
1298     /// ## 返回值
1299     ///
1300     /// - **Ok(())** 扩展成功
1301     /// - **Err(SystemError)** 扩展失败
1302     #[allow(dead_code)]
1303     pub fn extend(
1304         &mut self,
1305         vm: &mut RwLockWriteGuard<InnerAddressSpace>,
1306         mut bytes: usize,
1307     ) -> Result<(), SystemError> {
1308         let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC;
1309         let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS;
1310 
1311         bytes = page_align_up(bytes);
1312         self.mapped_size += bytes;
1313 
1314         vm.map_anonymous(
1315             self.stack_bottom - self.mapped_size,
1316             bytes,
1317             prot_flags,
1318             map_flags,
1319             false,
1320         )?;
1321 
1322         return Ok(());
1323     }
1324 
1325     /// 获取栈顶地址
1326     ///
1327     /// 请注意,如果用户栈的栈顶地址发生变化,这个值可能不会实时更新!
1328     pub fn sp(&self) -> VirtAddr {
1329         return self.current_sp;
1330     }
1331 
1332     pub unsafe fn set_sp(&mut self, sp: VirtAddr) {
1333         self.current_sp = sp;
1334     }
1335 
1336     /// 仅仅克隆用户栈的信息,不会克隆用户栈的内容/映射
1337     pub unsafe fn clone_info_only(&self) -> Self {
1338         return Self {
1339             stack_bottom: self.stack_bottom,
1340             mapped_size: self.mapped_size,
1341             current_sp: self.current_sp,
1342         };
1343     }
1344 
1345     /// 获取当前用户栈的大小(不包括保护页)
1346     pub fn stack_size(&self) -> usize {
1347         return self.mapped_size - Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE;
1348     }
1349 }
1350