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