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