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