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