140fe15e0SLoGin // 进程的用户空间内存管理 240fe15e0SLoGin 340fe15e0SLoGin use core::{ 440fe15e0SLoGin cmp, 540fe15e0SLoGin hash::Hasher, 640fe15e0SLoGin intrinsics::unlikely, 740fe15e0SLoGin ops::Add, 840fe15e0SLoGin sync::atomic::{compiler_fence, Ordering}, 940fe15e0SLoGin }; 1040fe15e0SLoGin 1140fe15e0SLoGin use alloc::{ 1240fe15e0SLoGin collections::BTreeMap, 1340fe15e0SLoGin sync::{Arc, Weak}, 1440fe15e0SLoGin vec::Vec, 1540fe15e0SLoGin }; 1640fe15e0SLoGin use hashbrown::HashSet; 1740fe15e0SLoGin 1840fe15e0SLoGin use crate::{ 191496ba7bSLoGin arch::{mm::PageMapper, CurrentIrqArch, MMArch}, 2040fe15e0SLoGin exception::InterruptArch, 2140fe15e0SLoGin libs::{ 2240fe15e0SLoGin align::page_align_up, 2340fe15e0SLoGin rwlock::{RwLock, RwLockWriteGuard}, 2440fe15e0SLoGin spinlock::{SpinLock, SpinLockGuard}, 2540fe15e0SLoGin }, 261496ba7bSLoGin process::ProcessManager, 2740fe15e0SLoGin syscall::SystemError, 2840fe15e0SLoGin }; 2940fe15e0SLoGin 3040fe15e0SLoGin use super::{ 3140fe15e0SLoGin allocator::page_frame::{ 3240fe15e0SLoGin deallocate_page_frames, PageFrameCount, PhysPageFrame, VirtPageFrame, VirtPageFrameIter, 3340fe15e0SLoGin }, 3440fe15e0SLoGin page::{Flusher, InactiveFlusher, PageFlags, PageFlushAll}, 3540fe15e0SLoGin syscall::{MapFlags, ProtFlags}, 3640fe15e0SLoGin MemoryManagementArch, PageTableKind, VirtAddr, VirtRegion, 3740fe15e0SLoGin }; 3840fe15e0SLoGin 3940fe15e0SLoGin /// MMAP_MIN_ADDR的默认值 4040fe15e0SLoGin /// 以下内容来自linux-5.19: 4140fe15e0SLoGin /// This is the portion of low virtual memory which should be protected 4240fe15e0SLoGin // from userspace allocation. Keeping a user from writing to low pages 4340fe15e0SLoGin // can help reduce the impact of kernel NULL pointer bugs. 4440fe15e0SLoGin // For most ia64, ppc64 and x86 users with lots of address space 4540fe15e0SLoGin // a value of 65536 is reasonable and should cause no problems. 4640fe15e0SLoGin // On arm and other archs it should not be higher than 32768. 4740fe15e0SLoGin // Programs which use vm86 functionality or have some need to map 4840fe15e0SLoGin // this low address space will need CAP_SYS_RAWIO or disable this 4940fe15e0SLoGin // protection by setting the value to 0. 5040fe15e0SLoGin pub const DEFAULT_MMAP_MIN_ADDR: usize = 65536; 5140fe15e0SLoGin 5240fe15e0SLoGin #[derive(Debug)] 5340fe15e0SLoGin pub struct AddressSpace { 5440fe15e0SLoGin inner: RwLock<InnerAddressSpace>, 5540fe15e0SLoGin } 5640fe15e0SLoGin 5740fe15e0SLoGin impl AddressSpace { 5840fe15e0SLoGin pub fn new(create_stack: bool) -> Result<Arc<Self>, SystemError> { 5940fe15e0SLoGin let inner = InnerAddressSpace::new(create_stack)?; 6040fe15e0SLoGin let result = Self { 6140fe15e0SLoGin inner: RwLock::new(inner), 6240fe15e0SLoGin }; 6340fe15e0SLoGin return Ok(Arc::new(result)); 6440fe15e0SLoGin } 6540fe15e0SLoGin 6640fe15e0SLoGin /// 从pcb中获取当前进程的地址空间结构体的Arc指针 6740fe15e0SLoGin pub fn current() -> Result<Arc<AddressSpace>, SystemError> { 681496ba7bSLoGin let vm = ProcessManager::current_pcb() 691496ba7bSLoGin .basic() 701496ba7bSLoGin .user_vm() 7140fe15e0SLoGin .expect("Current process has no address space"); 721496ba7bSLoGin 731496ba7bSLoGin return Ok(vm); 7440fe15e0SLoGin } 7540fe15e0SLoGin 7640fe15e0SLoGin /// 判断某个地址空间是否为当前进程的地址空间 7740fe15e0SLoGin pub fn is_current(self: &Arc<Self>) -> bool { 7840fe15e0SLoGin let current = Self::current(); 7940fe15e0SLoGin if let Ok(current) = current { 8040fe15e0SLoGin return Arc::ptr_eq(¤t, self); 8140fe15e0SLoGin } 8240fe15e0SLoGin return false; 8340fe15e0SLoGin } 8440fe15e0SLoGin } 8540fe15e0SLoGin 8640fe15e0SLoGin impl core::ops::Deref for AddressSpace { 8740fe15e0SLoGin type Target = RwLock<InnerAddressSpace>; 8840fe15e0SLoGin 8940fe15e0SLoGin fn deref(&self) -> &Self::Target { 9040fe15e0SLoGin &self.inner 9140fe15e0SLoGin } 9240fe15e0SLoGin } 9340fe15e0SLoGin 9440fe15e0SLoGin impl core::ops::DerefMut for AddressSpace { 9540fe15e0SLoGin fn deref_mut(&mut self) -> &mut Self::Target { 9640fe15e0SLoGin &mut self.inner 9740fe15e0SLoGin } 9840fe15e0SLoGin } 9940fe15e0SLoGin 10040fe15e0SLoGin /// @brief 用户地址空间结构体(每个进程都有一个) 10140fe15e0SLoGin #[derive(Debug)] 10240fe15e0SLoGin pub struct InnerAddressSpace { 10340fe15e0SLoGin pub user_mapper: UserMapper, 10440fe15e0SLoGin pub mappings: UserMappings, 10540fe15e0SLoGin pub mmap_min: VirtAddr, 10640fe15e0SLoGin /// 用户栈信息结构体 10740fe15e0SLoGin pub user_stack: Option<UserStack>, 10840fe15e0SLoGin 10940fe15e0SLoGin pub elf_brk_start: VirtAddr, 11040fe15e0SLoGin pub elf_brk: VirtAddr, 11140fe15e0SLoGin 11240fe15e0SLoGin /// 当前进程的堆空间的起始地址 11340fe15e0SLoGin pub brk_start: VirtAddr, 11440fe15e0SLoGin /// 当前进程的堆空间的结束地址(不包含) 11540fe15e0SLoGin pub brk: VirtAddr, 11640fe15e0SLoGin 11740fe15e0SLoGin pub start_code: VirtAddr, 11840fe15e0SLoGin pub end_code: VirtAddr, 11940fe15e0SLoGin pub start_data: VirtAddr, 12040fe15e0SLoGin pub end_data: VirtAddr, 12140fe15e0SLoGin } 12240fe15e0SLoGin 12340fe15e0SLoGin impl InnerAddressSpace { 12440fe15e0SLoGin pub fn new(create_stack: bool) -> Result<Self, SystemError> { 12540fe15e0SLoGin let mut result = Self { 12640fe15e0SLoGin user_mapper: MMArch::setup_new_usermapper()?, 12740fe15e0SLoGin mappings: UserMappings::new(), 12840fe15e0SLoGin mmap_min: VirtAddr(DEFAULT_MMAP_MIN_ADDR), 12940fe15e0SLoGin elf_brk_start: VirtAddr::new(0), 13040fe15e0SLoGin elf_brk: VirtAddr::new(0), 13140fe15e0SLoGin brk_start: MMArch::USER_BRK_START, 13240fe15e0SLoGin brk: MMArch::USER_BRK_START, 13340fe15e0SLoGin user_stack: None, 13440fe15e0SLoGin start_code: VirtAddr(0), 13540fe15e0SLoGin end_code: VirtAddr(0), 13640fe15e0SLoGin start_data: VirtAddr(0), 13740fe15e0SLoGin end_data: VirtAddr(0), 13840fe15e0SLoGin }; 13940fe15e0SLoGin if create_stack { 14040fe15e0SLoGin // kdebug!("to create user stack."); 14140fe15e0SLoGin result.new_user_stack(UserStack::DEFAULT_USER_STACK_SIZE)?; 14240fe15e0SLoGin } 14340fe15e0SLoGin 14440fe15e0SLoGin return Ok(result); 14540fe15e0SLoGin } 14640fe15e0SLoGin 14740fe15e0SLoGin /// 尝试克隆当前进程的地址空间,包括这些映射都会被克隆 14840fe15e0SLoGin /// 14940fe15e0SLoGin /// # Returns 15040fe15e0SLoGin /// 15140fe15e0SLoGin /// 返回克隆后的,新的地址空间的Arc指针 152*4fda81ceSLoGin #[inline(never)] 15340fe15e0SLoGin pub fn try_clone(&mut self) -> Result<Arc<AddressSpace>, SystemError> { 15440fe15e0SLoGin let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 15540fe15e0SLoGin let new_addr_space = AddressSpace::new(false)?; 15640fe15e0SLoGin let mut new_guard = new_addr_space.write(); 15740fe15e0SLoGin 15840fe15e0SLoGin // 拷贝用户栈的结构体信息,但是不拷贝用户栈的内容(因为后面VMA的拷贝会拷贝用户栈的内容) 15940fe15e0SLoGin unsafe { 16040fe15e0SLoGin new_guard.user_stack = Some(self.user_stack.as_ref().unwrap().clone_info_only()); 16140fe15e0SLoGin } 16240fe15e0SLoGin let _current_stack_size = self.user_stack.as_ref().unwrap().stack_size(); 16340fe15e0SLoGin 16440fe15e0SLoGin let current_mapper = &mut self.user_mapper.utable; 16540fe15e0SLoGin 166ea8ad4d4SLoGin // 拷贝空洞 167ea8ad4d4SLoGin new_guard.mappings.vm_holes = self.mappings.vm_holes.clone(); 168ea8ad4d4SLoGin 16940fe15e0SLoGin for vma in self.mappings.vmas.iter() { 17040fe15e0SLoGin // TODO: 增加对VMA是否为文件映射的判断,如果是的话,就跳过 17140fe15e0SLoGin 17240fe15e0SLoGin let vma_guard: SpinLockGuard<'_, VMA> = vma.lock(); 17340fe15e0SLoGin let old_flags = vma_guard.flags(); 17440fe15e0SLoGin let tmp_flags: PageFlags<MMArch> = PageFlags::new().set_write(true); 17540fe15e0SLoGin 17640fe15e0SLoGin // 分配内存页并创建新的VMA 17740fe15e0SLoGin let new_vma = VMA::zeroed( 17840fe15e0SLoGin VirtPageFrame::new(vma_guard.region.start()), 17940fe15e0SLoGin PageFrameCount::new(vma_guard.region.size() / MMArch::PAGE_SIZE), 18040fe15e0SLoGin tmp_flags, 18140fe15e0SLoGin &mut new_guard.user_mapper.utable, 18240fe15e0SLoGin (), 18340fe15e0SLoGin )?; 18440fe15e0SLoGin new_guard.mappings.vmas.insert(new_vma.clone()); 18540fe15e0SLoGin // kdebug!("new vma: {:x?}", new_vma); 18640fe15e0SLoGin let mut new_vma_guard = new_vma.lock(); 18740fe15e0SLoGin for page in new_vma_guard.pages().map(|p| p.virt_address()) { 18840fe15e0SLoGin // kdebug!("page: {:x?}", page); 18940fe15e0SLoGin let current_frame = unsafe { 19040fe15e0SLoGin MMArch::phys_2_virt( 19140fe15e0SLoGin current_mapper 19240fe15e0SLoGin .translate(page) 19340fe15e0SLoGin .expect("VMA page not mapped") 19440fe15e0SLoGin .0, 19540fe15e0SLoGin ) 19640fe15e0SLoGin } 19740fe15e0SLoGin .expect("Phys2Virt: vaddr overflow.") 19840fe15e0SLoGin .data() as *mut u8; 19940fe15e0SLoGin 20040fe15e0SLoGin let new_frame = unsafe { 20140fe15e0SLoGin MMArch::phys_2_virt( 20240fe15e0SLoGin new_guard 20340fe15e0SLoGin .user_mapper 20440fe15e0SLoGin .utable 20540fe15e0SLoGin .translate(page) 20640fe15e0SLoGin .expect("VMA page not mapped") 20740fe15e0SLoGin .0, 20840fe15e0SLoGin ) 20940fe15e0SLoGin } 21040fe15e0SLoGin .expect("Phys2Virt: vaddr overflow.") 21140fe15e0SLoGin .data() as *mut u8; 21240fe15e0SLoGin 21340fe15e0SLoGin unsafe { 21440fe15e0SLoGin // 拷贝数据 21540fe15e0SLoGin new_frame.copy_from_nonoverlapping(current_frame, MMArch::PAGE_SIZE); 21640fe15e0SLoGin } 21740fe15e0SLoGin } 21840fe15e0SLoGin drop(vma_guard); 21940fe15e0SLoGin 22040fe15e0SLoGin new_vma_guard.remap(old_flags, &mut new_guard.user_mapper.utable, ())?; 22140fe15e0SLoGin drop(new_vma_guard); 22240fe15e0SLoGin } 22340fe15e0SLoGin drop(new_guard); 22440fe15e0SLoGin drop(irq_guard); 22540fe15e0SLoGin return Ok(new_addr_space); 22640fe15e0SLoGin } 22740fe15e0SLoGin 22840fe15e0SLoGin /// 判断当前的地址空间是否是当前进程的地址空间 22940fe15e0SLoGin #[inline] 23040fe15e0SLoGin pub fn is_current(&self) -> bool { 23140fe15e0SLoGin return self.user_mapper.utable.is_current(); 23240fe15e0SLoGin } 23340fe15e0SLoGin 23440fe15e0SLoGin /// 进行匿名页映射 23540fe15e0SLoGin /// 23640fe15e0SLoGin /// ## 参数 23740fe15e0SLoGin /// 23840fe15e0SLoGin /// - `start_vaddr`:映射的起始地址 23940fe15e0SLoGin /// - `len`:映射的长度 24040fe15e0SLoGin /// - `prot_flags`:保护标志 24140fe15e0SLoGin /// - `map_flags`:映射标志 24240fe15e0SLoGin /// - `round_to_min`:是否将`start_vaddr`对齐到`mmap_min`,如果为`true`,则当`start_vaddr`不为0时,会对齐到`mmap_min`,否则仅向下对齐到页边界 2431496ba7bSLoGin /// 2441496ba7bSLoGin /// ## 返回 2451496ba7bSLoGin /// 2461496ba7bSLoGin /// 返回映射的起始虚拟页帧 24740fe15e0SLoGin pub fn map_anonymous( 24840fe15e0SLoGin &mut self, 24940fe15e0SLoGin start_vaddr: VirtAddr, 25040fe15e0SLoGin len: usize, 25140fe15e0SLoGin prot_flags: ProtFlags, 25240fe15e0SLoGin map_flags: MapFlags, 25340fe15e0SLoGin round_to_min: bool, 25440fe15e0SLoGin ) -> Result<VirtPageFrame, SystemError> { 25540fe15e0SLoGin // 用于对齐hint的函数 25640fe15e0SLoGin let round_hint_to_min = |hint: VirtAddr| { 25740fe15e0SLoGin // 先把hint向下对齐到页边界 25840fe15e0SLoGin let addr = hint.data() & (!MMArch::PAGE_OFFSET_MASK); 25940fe15e0SLoGin // kdebug!("map_anonymous: hint = {:?}, addr = {addr:#x}", hint); 26040fe15e0SLoGin // 如果hint不是0,且hint小于DEFAULT_MMAP_MIN_ADDR,则对齐到DEFAULT_MMAP_MIN_ADDR 26140fe15e0SLoGin if (addr != 0) && round_to_min && (addr < DEFAULT_MMAP_MIN_ADDR) { 26240fe15e0SLoGin Some(VirtAddr::new(page_align_up(DEFAULT_MMAP_MIN_ADDR))) 26340fe15e0SLoGin } else if addr == 0 { 26440fe15e0SLoGin None 26540fe15e0SLoGin } else { 26640fe15e0SLoGin Some(VirtAddr::new(addr)) 26740fe15e0SLoGin } 26840fe15e0SLoGin }; 26940fe15e0SLoGin // kdebug!("map_anonymous: start_vaddr = {:?}", start_vaddr); 27040fe15e0SLoGin // kdebug!("map_anonymous: len(no align) = {}", len); 27140fe15e0SLoGin 27240fe15e0SLoGin let len = page_align_up(len); 27340fe15e0SLoGin 27440fe15e0SLoGin // kdebug!("map_anonymous: len = {}", len); 27540fe15e0SLoGin 27640fe15e0SLoGin let start_page: VirtPageFrame = self.mmap( 27740fe15e0SLoGin round_hint_to_min(start_vaddr), 27840fe15e0SLoGin PageFrameCount::from_bytes(len).unwrap(), 27940fe15e0SLoGin prot_flags, 28040fe15e0SLoGin map_flags, 28140fe15e0SLoGin move |page, count, flags, mapper, flusher| { 28240fe15e0SLoGin Ok(VMA::zeroed(page, count, flags, mapper, flusher)?) 28340fe15e0SLoGin }, 28440fe15e0SLoGin )?; 28540fe15e0SLoGin 28640fe15e0SLoGin return Ok(start_page); 28740fe15e0SLoGin } 28840fe15e0SLoGin 28940fe15e0SLoGin /// 向进程的地址空间映射页面 29040fe15e0SLoGin /// 29140fe15e0SLoGin /// # 参数 29240fe15e0SLoGin /// 29340fe15e0SLoGin /// - `addr`:映射的起始地址,如果为`None`,则由内核自动分配 29440fe15e0SLoGin /// - `page_count`:映射的页面数量 29540fe15e0SLoGin /// - `prot_flags`:保护标志 29640fe15e0SLoGin /// - `map_flags`:映射标志 29740fe15e0SLoGin /// - `map_func`:映射函数,用于创建VMA 29840fe15e0SLoGin /// 29940fe15e0SLoGin /// # Returns 30040fe15e0SLoGin /// 30140fe15e0SLoGin /// 返回映射的起始虚拟页帧 30240fe15e0SLoGin /// 30340fe15e0SLoGin /// # Errors 30440fe15e0SLoGin /// 30540fe15e0SLoGin /// - `EINVAL`:参数错误 30640fe15e0SLoGin pub fn mmap< 30740fe15e0SLoGin F: FnOnce( 30840fe15e0SLoGin VirtPageFrame, 30940fe15e0SLoGin PageFrameCount, 31040fe15e0SLoGin PageFlags<MMArch>, 31140fe15e0SLoGin &mut PageMapper, 31240fe15e0SLoGin &mut dyn Flusher<MMArch>, 31340fe15e0SLoGin ) -> Result<Arc<LockedVMA>, SystemError>, 31440fe15e0SLoGin >( 31540fe15e0SLoGin &mut self, 31640fe15e0SLoGin addr: Option<VirtAddr>, 31740fe15e0SLoGin page_count: PageFrameCount, 31840fe15e0SLoGin prot_flags: ProtFlags, 31940fe15e0SLoGin map_flags: MapFlags, 32040fe15e0SLoGin map_func: F, 32140fe15e0SLoGin ) -> Result<VirtPageFrame, SystemError> { 32240fe15e0SLoGin if page_count == PageFrameCount::new(0) { 32340fe15e0SLoGin return Err(SystemError::EINVAL); 32440fe15e0SLoGin } 32540fe15e0SLoGin // kdebug!("mmap: addr: {addr:?}, page_count: {page_count:?}, prot_flags: {prot_flags:?}, map_flags: {map_flags:?}"); 32640fe15e0SLoGin 32740fe15e0SLoGin // 找到未使用的区域 32840fe15e0SLoGin let region = match addr { 32940fe15e0SLoGin Some(vaddr) => { 33040fe15e0SLoGin self.mappings 33140fe15e0SLoGin .find_free_at(self.mmap_min, vaddr, page_count.bytes(), map_flags)? 33240fe15e0SLoGin } 33340fe15e0SLoGin None => self 33440fe15e0SLoGin .mappings 33540fe15e0SLoGin .find_free(self.mmap_min, page_count.bytes()) 33640fe15e0SLoGin .ok_or(SystemError::ENOMEM)?, 33740fe15e0SLoGin }; 33840fe15e0SLoGin 33940fe15e0SLoGin let page = VirtPageFrame::new(region.start()); 34040fe15e0SLoGin 34140fe15e0SLoGin // kdebug!("mmap: page: {:?}, region={region:?}", page.virt_address()); 34240fe15e0SLoGin 34340fe15e0SLoGin compiler_fence(Ordering::SeqCst); 34440fe15e0SLoGin let (mut active, mut inactive); 34540fe15e0SLoGin let flusher = if self.is_current() { 34640fe15e0SLoGin active = PageFlushAll::new(); 34740fe15e0SLoGin &mut active as &mut dyn Flusher<MMArch> 34840fe15e0SLoGin } else { 34940fe15e0SLoGin inactive = InactiveFlusher::new(); 35040fe15e0SLoGin &mut inactive as &mut dyn Flusher<MMArch> 35140fe15e0SLoGin }; 35240fe15e0SLoGin compiler_fence(Ordering::SeqCst); 35340fe15e0SLoGin // 映射页面,并将VMA插入到地址空间的VMA列表中 35440fe15e0SLoGin self.mappings.insert_vma(map_func( 35540fe15e0SLoGin page, 35640fe15e0SLoGin page_count, 35740fe15e0SLoGin PageFlags::from_prot_flags(prot_flags, true), 35840fe15e0SLoGin &mut self.user_mapper.utable, 35940fe15e0SLoGin flusher, 36040fe15e0SLoGin )?); 36140fe15e0SLoGin 36240fe15e0SLoGin return Ok(page); 36340fe15e0SLoGin } 36440fe15e0SLoGin 36540fe15e0SLoGin /// 取消进程的地址空间中的映射 36640fe15e0SLoGin /// 36740fe15e0SLoGin /// # 参数 36840fe15e0SLoGin /// 36940fe15e0SLoGin /// - `start_page`:起始页帧 37040fe15e0SLoGin /// - `page_count`:取消映射的页帧数量 37140fe15e0SLoGin /// 37240fe15e0SLoGin /// # Errors 37340fe15e0SLoGin /// 37440fe15e0SLoGin /// - `EINVAL`:参数错误 37540fe15e0SLoGin /// - `ENOMEM`:内存不足 37640fe15e0SLoGin pub fn munmap( 37740fe15e0SLoGin &mut self, 37840fe15e0SLoGin start_page: VirtPageFrame, 37940fe15e0SLoGin page_count: PageFrameCount, 38040fe15e0SLoGin ) -> Result<(), SystemError> { 38140fe15e0SLoGin let to_unmap = VirtRegion::new(start_page.virt_address(), page_count.bytes()); 38240fe15e0SLoGin let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new(); 38340fe15e0SLoGin 38440fe15e0SLoGin let regions: Vec<Arc<LockedVMA>> = self.mappings.conflicts(to_unmap).collect::<Vec<_>>(); 38540fe15e0SLoGin 38640fe15e0SLoGin for r in regions { 38740fe15e0SLoGin let r = r.lock().region; 38840fe15e0SLoGin let r = self.mappings.remove_vma(&r).unwrap(); 38940fe15e0SLoGin let intersection = r.lock().region().intersect(&to_unmap).unwrap(); 39040fe15e0SLoGin let (before, r, after) = r.extract(intersection).unwrap(); 39140fe15e0SLoGin 39240fe15e0SLoGin // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑 39340fe15e0SLoGin 39440fe15e0SLoGin if let Some(before) = before { 39540fe15e0SLoGin // 如果前面有VMA,则需要将前面的VMA重新插入到地址空间的VMA列表中 39640fe15e0SLoGin self.mappings.insert_vma(before); 39740fe15e0SLoGin } 39840fe15e0SLoGin 39940fe15e0SLoGin if let Some(after) = after { 40040fe15e0SLoGin // 如果后面有VMA,则需要将后面的VMA重新插入到地址空间的VMA列表中 40140fe15e0SLoGin self.mappings.insert_vma(after); 40240fe15e0SLoGin } 40340fe15e0SLoGin 40440fe15e0SLoGin r.unmap(&mut self.user_mapper.utable, &mut flusher); 40540fe15e0SLoGin } 40640fe15e0SLoGin 40740fe15e0SLoGin // TODO: 当引入后备页映射后,这里需要增加通知文件的逻辑 40840fe15e0SLoGin 40940fe15e0SLoGin return Ok(()); 41040fe15e0SLoGin } 41140fe15e0SLoGin 41240fe15e0SLoGin pub fn mprotect( 41340fe15e0SLoGin &mut self, 41440fe15e0SLoGin start_page: VirtPageFrame, 41540fe15e0SLoGin page_count: PageFrameCount, 41640fe15e0SLoGin prot_flags: ProtFlags, 41740fe15e0SLoGin ) -> Result<(), SystemError> { 41840fe15e0SLoGin // kdebug!( 41940fe15e0SLoGin // "mprotect: start_page: {:?}, page_count: {:?}, prot_flags:{prot_flags:?}", 42040fe15e0SLoGin // start_page, 42140fe15e0SLoGin // page_count 42240fe15e0SLoGin // ); 42340fe15e0SLoGin let (mut active, mut inactive); 42440fe15e0SLoGin let mut flusher = if self.is_current() { 42540fe15e0SLoGin active = PageFlushAll::new(); 42640fe15e0SLoGin &mut active as &mut dyn Flusher<MMArch> 42740fe15e0SLoGin } else { 42840fe15e0SLoGin inactive = InactiveFlusher::new(); 42940fe15e0SLoGin &mut inactive as &mut dyn Flusher<MMArch> 43040fe15e0SLoGin }; 43140fe15e0SLoGin 43240fe15e0SLoGin let mapper = &mut self.user_mapper.utable; 43340fe15e0SLoGin let region = VirtRegion::new(start_page.virt_address(), page_count.bytes()); 43440fe15e0SLoGin // kdebug!("mprotect: region: {:?}", region); 43540fe15e0SLoGin 43640fe15e0SLoGin let regions = self.mappings.conflicts(region).collect::<Vec<_>>(); 43740fe15e0SLoGin // kdebug!("mprotect: regions: {:?}", regions); 43840fe15e0SLoGin 43940fe15e0SLoGin for r in regions { 44040fe15e0SLoGin // kdebug!("mprotect: r: {:?}", r); 44140fe15e0SLoGin let r = r.lock().region().clone(); 44240fe15e0SLoGin let r = self.mappings.remove_vma(&r).unwrap(); 44340fe15e0SLoGin 44440fe15e0SLoGin let intersection = r.lock().region().intersect(®ion).unwrap(); 44540fe15e0SLoGin let (before, r, after) = r.extract(intersection).expect("Failed to extract VMA"); 44640fe15e0SLoGin 44740fe15e0SLoGin if let Some(before) = before { 44840fe15e0SLoGin self.mappings.insert_vma(before); 44940fe15e0SLoGin } 45040fe15e0SLoGin if let Some(after) = after { 45140fe15e0SLoGin self.mappings.insert_vma(after); 45240fe15e0SLoGin } 45340fe15e0SLoGin 45440fe15e0SLoGin let mut r_guard = r.lock(); 45540fe15e0SLoGin // 如果VMA的保护标志不允许指定的修改,则返回错误 45640fe15e0SLoGin if !r_guard.can_have_flags(prot_flags) { 45740fe15e0SLoGin drop(r_guard); 45840fe15e0SLoGin self.mappings.insert_vma(r.clone()); 45940fe15e0SLoGin return Err(SystemError::EACCES); 46040fe15e0SLoGin } 46140fe15e0SLoGin 46240fe15e0SLoGin let new_flags: PageFlags<MMArch> = r_guard 46340fe15e0SLoGin .flags() 46440fe15e0SLoGin .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC)) 46540fe15e0SLoGin .set_write(prot_flags.contains(ProtFlags::PROT_WRITE)); 46640fe15e0SLoGin 46740fe15e0SLoGin r_guard.remap(new_flags, mapper, &mut flusher)?; 46840fe15e0SLoGin drop(r_guard); 46940fe15e0SLoGin self.mappings.insert_vma(r); 47040fe15e0SLoGin } 47140fe15e0SLoGin 47240fe15e0SLoGin return Ok(()); 47340fe15e0SLoGin } 47440fe15e0SLoGin 47540fe15e0SLoGin /// 创建新的用户栈 47640fe15e0SLoGin /// 47740fe15e0SLoGin /// ## 参数 47840fe15e0SLoGin /// 47940fe15e0SLoGin /// - `size`:栈的大小 48040fe15e0SLoGin pub fn new_user_stack(&mut self, size: usize) -> Result<(), SystemError> { 48140fe15e0SLoGin assert!(self.user_stack.is_none(), "User stack already exists"); 48240fe15e0SLoGin let stack = UserStack::new(self, None, size)?; 48340fe15e0SLoGin self.user_stack = Some(stack); 48440fe15e0SLoGin return Ok(()); 48540fe15e0SLoGin } 48640fe15e0SLoGin 48740fe15e0SLoGin #[inline(always)] 48840fe15e0SLoGin pub fn user_stack_mut(&mut self) -> Option<&mut UserStack> { 48940fe15e0SLoGin return self.user_stack.as_mut(); 49040fe15e0SLoGin } 49140fe15e0SLoGin 49240fe15e0SLoGin /// 取消用户空间内的所有映射 49340fe15e0SLoGin pub unsafe fn unmap_all(&mut self) { 49440fe15e0SLoGin let mut flusher: PageFlushAll<MMArch> = PageFlushAll::new(); 49540fe15e0SLoGin for vma in self.mappings.iter_vmas() { 49640fe15e0SLoGin vma.unmap(&mut self.user_mapper.utable, &mut flusher); 49740fe15e0SLoGin } 49840fe15e0SLoGin } 49940fe15e0SLoGin 50040fe15e0SLoGin /// 设置进程的堆的内存空间 50140fe15e0SLoGin /// 50240fe15e0SLoGin /// ## 参数 50340fe15e0SLoGin /// 50440fe15e0SLoGin /// - `new_brk`:新的堆的结束地址。需要满足页对齐要求,并且是用户空间地址,且大于等于当前的堆的起始地址 50540fe15e0SLoGin /// 50640fe15e0SLoGin /// ## 返回值 50740fe15e0SLoGin /// 50840fe15e0SLoGin /// 返回旧的堆的结束地址 50940fe15e0SLoGin pub unsafe fn set_brk(&mut self, new_brk: VirtAddr) -> Result<VirtAddr, SystemError> { 51040fe15e0SLoGin assert!(new_brk.check_aligned(MMArch::PAGE_SIZE)); 51140fe15e0SLoGin 51240fe15e0SLoGin if !new_brk.check_user() || new_brk < self.brk_start { 51340fe15e0SLoGin return Err(SystemError::EFAULT); 51440fe15e0SLoGin } 51540fe15e0SLoGin 51640fe15e0SLoGin let old_brk = self.brk; 5171496ba7bSLoGin 51840fe15e0SLoGin if new_brk > self.brk { 51940fe15e0SLoGin let len = new_brk - self.brk; 52040fe15e0SLoGin let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC; 52140fe15e0SLoGin let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED; 5221496ba7bSLoGin self.map_anonymous(old_brk, len, prot_flags, map_flags, true)?; 5231496ba7bSLoGin 52440fe15e0SLoGin self.brk = new_brk; 52540fe15e0SLoGin return Ok(old_brk); 52640fe15e0SLoGin } else { 52740fe15e0SLoGin let unmap_len = self.brk - new_brk; 52840fe15e0SLoGin let unmap_start = new_brk; 52940fe15e0SLoGin if unmap_len == 0 { 53040fe15e0SLoGin return Ok(old_brk); 53140fe15e0SLoGin } 53240fe15e0SLoGin self.munmap( 53340fe15e0SLoGin VirtPageFrame::new(unmap_start), 53440fe15e0SLoGin PageFrameCount::from_bytes(unmap_len).unwrap(), 53540fe15e0SLoGin )?; 53640fe15e0SLoGin self.brk = new_brk; 53740fe15e0SLoGin return Ok(old_brk); 53840fe15e0SLoGin } 53940fe15e0SLoGin } 54040fe15e0SLoGin 54140fe15e0SLoGin pub unsafe fn sbrk(&mut self, incr: isize) -> Result<VirtAddr, SystemError> { 54240fe15e0SLoGin if incr == 0 { 54340fe15e0SLoGin return Ok(self.brk); 54440fe15e0SLoGin } 54540fe15e0SLoGin 54640fe15e0SLoGin let new_brk = if incr > 0 { 54740fe15e0SLoGin self.brk + incr as usize 54840fe15e0SLoGin } else { 54940fe15e0SLoGin self.brk - (incr.abs() as usize) 55040fe15e0SLoGin }; 55140fe15e0SLoGin 55240fe15e0SLoGin let new_brk = VirtAddr::new(page_align_up(new_brk.data())); 55340fe15e0SLoGin 55440fe15e0SLoGin return self.set_brk(new_brk); 55540fe15e0SLoGin } 55640fe15e0SLoGin } 55740fe15e0SLoGin 55840fe15e0SLoGin impl Drop for InnerAddressSpace { 55940fe15e0SLoGin fn drop(&mut self) { 56040fe15e0SLoGin unsafe { 56140fe15e0SLoGin self.unmap_all(); 56240fe15e0SLoGin } 56340fe15e0SLoGin } 56440fe15e0SLoGin } 56540fe15e0SLoGin 56640fe15e0SLoGin #[derive(Debug, Hash)] 56740fe15e0SLoGin pub struct UserMapper { 56840fe15e0SLoGin pub utable: PageMapper, 56940fe15e0SLoGin } 57040fe15e0SLoGin 57140fe15e0SLoGin impl UserMapper { 57240fe15e0SLoGin pub fn new(utable: PageMapper) -> Self { 57340fe15e0SLoGin return Self { utable }; 57440fe15e0SLoGin } 57540fe15e0SLoGin } 57640fe15e0SLoGin 57740fe15e0SLoGin impl Drop for UserMapper { 57840fe15e0SLoGin fn drop(&mut self) { 57940fe15e0SLoGin if self.utable.is_current() { 58040fe15e0SLoGin // 如果当前要被销毁的用户空间的页表是当前进程的页表,那么就切换回初始内核页表 58140fe15e0SLoGin unsafe { MMArch::set_table(PageTableKind::User, MMArch::initial_page_table()) } 58240fe15e0SLoGin } 58340fe15e0SLoGin // 释放用户空间顶层页表占用的页帧 58440fe15e0SLoGin // 请注意,在释放这个页帧之前,用户页表应该已经被完全释放,否则会产生内存泄露 58540fe15e0SLoGin unsafe { 58640fe15e0SLoGin deallocate_page_frames( 58740fe15e0SLoGin PhysPageFrame::new(self.utable.table().phys()), 58840fe15e0SLoGin PageFrameCount::new(1), 58940fe15e0SLoGin ) 59040fe15e0SLoGin }; 59140fe15e0SLoGin } 59240fe15e0SLoGin } 59340fe15e0SLoGin 59440fe15e0SLoGin /// 用户空间映射信息 59540fe15e0SLoGin #[derive(Debug)] 59640fe15e0SLoGin pub struct UserMappings { 59740fe15e0SLoGin /// 当前用户空间的虚拟内存区域 59840fe15e0SLoGin vmas: HashSet<Arc<LockedVMA>>, 59940fe15e0SLoGin /// 当前用户空间的VMA空洞 60040fe15e0SLoGin vm_holes: BTreeMap<VirtAddr, usize>, 60140fe15e0SLoGin } 60240fe15e0SLoGin 60340fe15e0SLoGin impl UserMappings { 60440fe15e0SLoGin pub fn new() -> Self { 60540fe15e0SLoGin return Self { 60640fe15e0SLoGin vmas: HashSet::new(), 60740fe15e0SLoGin vm_holes: core::iter::once((VirtAddr::new(0), MMArch::USER_END_VADDR.data())) 60840fe15e0SLoGin .collect::<BTreeMap<_, _>>(), 60940fe15e0SLoGin }; 61040fe15e0SLoGin } 61140fe15e0SLoGin 61240fe15e0SLoGin /// 判断当前进程的VMA内,是否有包含指定的虚拟地址的VMA。 61340fe15e0SLoGin /// 61440fe15e0SLoGin /// 如果有,返回包含指定虚拟地址的VMA的Arc指针,否则返回None。 61540fe15e0SLoGin #[allow(dead_code)] 61640fe15e0SLoGin pub fn contains(&self, vaddr: VirtAddr) -> Option<Arc<LockedVMA>> { 61740fe15e0SLoGin for v in self.vmas.iter() { 61840fe15e0SLoGin let guard = v.lock(); 61940fe15e0SLoGin if guard.region.contains(vaddr) { 62040fe15e0SLoGin return Some(v.clone()); 62140fe15e0SLoGin } 62240fe15e0SLoGin } 62340fe15e0SLoGin return None; 62440fe15e0SLoGin } 62540fe15e0SLoGin 62640fe15e0SLoGin /// 获取当前进程的地址空间中,与给定虚拟地址范围有重叠的VMA的迭代器。 62740fe15e0SLoGin pub fn conflicts(&self, request: VirtRegion) -> impl Iterator<Item = Arc<LockedVMA>> + '_ { 62840fe15e0SLoGin let r = self 62940fe15e0SLoGin .vmas 63040fe15e0SLoGin .iter() 63140fe15e0SLoGin .filter(move |v| !v.lock().region.intersect(&request).is_none()) 63240fe15e0SLoGin .cloned(); 63340fe15e0SLoGin return r; 63440fe15e0SLoGin } 63540fe15e0SLoGin 63640fe15e0SLoGin /// 在当前进程的地址空间中,寻找第一个符合条件的空闲的虚拟内存范围。 63740fe15e0SLoGin /// 63840fe15e0SLoGin /// @param min_vaddr 最小的起始地址 63940fe15e0SLoGin /// @param size 请求的大小 64040fe15e0SLoGin /// 64140fe15e0SLoGin /// @return 如果找到了,返回虚拟内存范围,否则返回None 64240fe15e0SLoGin pub fn find_free(&self, min_vaddr: VirtAddr, size: usize) -> Option<VirtRegion> { 64340fe15e0SLoGin let _vaddr = min_vaddr; 64440fe15e0SLoGin let mut iter = self 64540fe15e0SLoGin .vm_holes 64640fe15e0SLoGin .iter() 64740fe15e0SLoGin .skip_while(|(hole_vaddr, hole_size)| hole_vaddr.add(**hole_size) <= min_vaddr); 64840fe15e0SLoGin 64940fe15e0SLoGin let (hole_vaddr, size) = iter.find(|(hole_vaddr, hole_size)| { 65040fe15e0SLoGin // 计算当前空洞的可用大小 65140fe15e0SLoGin let available_size: usize = 65240fe15e0SLoGin if hole_vaddr <= &&min_vaddr && min_vaddr <= hole_vaddr.add(**hole_size) { 65340fe15e0SLoGin **hole_size - (min_vaddr - **hole_vaddr) 65440fe15e0SLoGin } else { 65540fe15e0SLoGin **hole_size 65640fe15e0SLoGin }; 65740fe15e0SLoGin 65840fe15e0SLoGin size <= available_size 65940fe15e0SLoGin })?; 66040fe15e0SLoGin 66140fe15e0SLoGin // 创建一个新的虚拟内存范围。 66240fe15e0SLoGin let region = VirtRegion::new(cmp::max(*hole_vaddr, min_vaddr), *size); 66340fe15e0SLoGin return Some(region); 66440fe15e0SLoGin } 66540fe15e0SLoGin 66640fe15e0SLoGin pub fn find_free_at( 66740fe15e0SLoGin &self, 66840fe15e0SLoGin min_vaddr: VirtAddr, 66940fe15e0SLoGin vaddr: VirtAddr, 67040fe15e0SLoGin size: usize, 67140fe15e0SLoGin flags: MapFlags, 67240fe15e0SLoGin ) -> Result<VirtRegion, SystemError> { 67340fe15e0SLoGin // 如果没有指定地址,那么就在当前进程的地址空间中寻找一个空闲的虚拟内存范围。 67440fe15e0SLoGin if vaddr == VirtAddr::new(0) { 67540fe15e0SLoGin return self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM); 67640fe15e0SLoGin } 67740fe15e0SLoGin 67840fe15e0SLoGin // 如果指定了地址,那么就检查指定的地址是否可用。 67940fe15e0SLoGin 68040fe15e0SLoGin let requested = VirtRegion::new(vaddr, size); 68140fe15e0SLoGin 68240fe15e0SLoGin if requested.end() >= MMArch::USER_END_VADDR || !vaddr.check_aligned(MMArch::PAGE_SIZE) { 68340fe15e0SLoGin return Err(SystemError::EINVAL); 68440fe15e0SLoGin } 68540fe15e0SLoGin 68640fe15e0SLoGin if let Some(_x) = self.conflicts(requested).next() { 68740fe15e0SLoGin if flags.contains(MapFlags::MAP_FIXED_NOREPLACE) { 68840fe15e0SLoGin // 如果指定了 MAP_FIXED_NOREPLACE 标志,由于所指定的地址无法成功建立映射,则放弃映射,不对地址做修正 68940fe15e0SLoGin return Err(SystemError::EEXIST); 69040fe15e0SLoGin } 69140fe15e0SLoGin 69240fe15e0SLoGin if flags.contains(MapFlags::MAP_FIXED) { 69340fe15e0SLoGin // todo: 支持MAP_FIXED标志对已有的VMA进行覆盖 69440fe15e0SLoGin return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP); 69540fe15e0SLoGin } 69640fe15e0SLoGin 69740fe15e0SLoGin // 如果没有指定MAP_FIXED标志,那么就对地址做修正 69840fe15e0SLoGin let requested = self.find_free(min_vaddr, size).ok_or(SystemError::ENOMEM)?; 69940fe15e0SLoGin return Ok(requested); 70040fe15e0SLoGin } 70140fe15e0SLoGin 70240fe15e0SLoGin return Ok(requested); 70340fe15e0SLoGin } 70440fe15e0SLoGin 70540fe15e0SLoGin /// 在当前进程的地址空间中,保留一个指定大小的区域,使得该区域不在空洞中。 70640fe15e0SLoGin /// 该函数会修改vm_holes中的空洞信息。 70740fe15e0SLoGin /// 70840fe15e0SLoGin /// @param region 要保留的区域 70940fe15e0SLoGin /// 71040fe15e0SLoGin /// 请注意,在调用本函数之前,必须先确定region所在范围内没有VMA。 71140fe15e0SLoGin fn reserve_hole(&mut self, region: &VirtRegion) { 71240fe15e0SLoGin let prev_hole: Option<(&VirtAddr, &mut usize)> = 713971462beSGnoCiYeH self.vm_holes.range_mut(..=region.start()).next_back(); 71440fe15e0SLoGin 71540fe15e0SLoGin if let Some((prev_hole_vaddr, prev_hole_size)) = prev_hole { 71640fe15e0SLoGin let prev_hole_end = prev_hole_vaddr.add(*prev_hole_size); 71740fe15e0SLoGin 71840fe15e0SLoGin if prev_hole_end > region.start() { 71940fe15e0SLoGin // 如果前一个空洞的结束地址大于当前空洞的起始地址,那么就需要调整前一个空洞的大小。 72040fe15e0SLoGin *prev_hole_size = region.start().data() - prev_hole_vaddr.data(); 72140fe15e0SLoGin } 72240fe15e0SLoGin 72340fe15e0SLoGin if prev_hole_end > region.end() { 72440fe15e0SLoGin // 如果前一个空洞的结束地址大于当前空洞的结束地址,那么就需要增加一个新的空洞。 72540fe15e0SLoGin self.vm_holes 72640fe15e0SLoGin .insert(region.end(), prev_hole_end - region.end()); 72740fe15e0SLoGin } 72840fe15e0SLoGin } 72940fe15e0SLoGin } 73040fe15e0SLoGin 73140fe15e0SLoGin /// 在当前进程的地址空间中,释放一个指定大小的区域,使得该区域成为一个空洞。 73240fe15e0SLoGin /// 该函数会修改vm_holes中的空洞信息。 73340fe15e0SLoGin fn unreserve_hole(&mut self, region: &VirtRegion) { 73440fe15e0SLoGin // 如果将要插入的空洞与后一个空洞相邻,那么就需要合并。 73540fe15e0SLoGin let next_hole_size: Option<usize> = self.vm_holes.remove(®ion.end()); 73640fe15e0SLoGin 73740fe15e0SLoGin if let Some((_prev_hole_vaddr, prev_hole_size)) = self 73840fe15e0SLoGin .vm_holes 73940fe15e0SLoGin .range_mut(..region.start()) 74040fe15e0SLoGin .next_back() 74140fe15e0SLoGin .filter(|(offset, size)| offset.data() + **size == region.start().data()) 74240fe15e0SLoGin { 74340fe15e0SLoGin *prev_hole_size += region.size() + next_hole_size.unwrap_or(0); 74440fe15e0SLoGin } else { 74540fe15e0SLoGin self.vm_holes 74640fe15e0SLoGin .insert(region.start(), region.size() + next_hole_size.unwrap_or(0)); 74740fe15e0SLoGin } 74840fe15e0SLoGin } 74940fe15e0SLoGin 75040fe15e0SLoGin /// 在当前进程的映射关系中,插入一个新的VMA。 75140fe15e0SLoGin pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) { 75240fe15e0SLoGin let region = vma.lock().region.clone(); 75340fe15e0SLoGin // 要求插入的地址范围必须是空闲的,也就是说,当前进程的地址空间中,不能有任何与之重叠的VMA。 75440fe15e0SLoGin assert!(self.conflicts(region).next().is_none()); 75540fe15e0SLoGin self.reserve_hole(®ion); 75640fe15e0SLoGin 75740fe15e0SLoGin self.vmas.insert(vma); 75840fe15e0SLoGin } 75940fe15e0SLoGin 76040fe15e0SLoGin /// @brief 删除一个VMA,并把对应的地址空间加入空洞中。 76140fe15e0SLoGin /// 76240fe15e0SLoGin /// 这里不会取消VMA对应的地址的映射 76340fe15e0SLoGin /// 76440fe15e0SLoGin /// @param region 要删除的VMA所在的地址范围 76540fe15e0SLoGin /// 76640fe15e0SLoGin /// @return 如果成功删除了VMA,则返回被删除的VMA,否则返回None 76740fe15e0SLoGin /// 如果没有可以删除的VMA,则不会执行删除操作,并报告失败。 76840fe15e0SLoGin pub fn remove_vma(&mut self, region: &VirtRegion) -> Option<Arc<LockedVMA>> { 76940fe15e0SLoGin // 请注意,由于这里会对每个VMA加锁,因此性能很低 77040fe15e0SLoGin let vma: Arc<LockedVMA> = self 77140fe15e0SLoGin .vmas 77240fe15e0SLoGin .drain_filter(|vma| vma.lock().region == *region) 77340fe15e0SLoGin .next()?; 77440fe15e0SLoGin self.unreserve_hole(region); 77540fe15e0SLoGin 77640fe15e0SLoGin return Some(vma); 77740fe15e0SLoGin } 77840fe15e0SLoGin 77940fe15e0SLoGin /// @brief Get the iterator of all VMAs in this process. 78040fe15e0SLoGin pub fn iter_vmas(&self) -> hashbrown::hash_set::Iter<Arc<LockedVMA>> { 78140fe15e0SLoGin return self.vmas.iter(); 78240fe15e0SLoGin } 78340fe15e0SLoGin } 78440fe15e0SLoGin 78540fe15e0SLoGin impl Default for UserMappings { 78640fe15e0SLoGin fn default() -> Self { 78740fe15e0SLoGin return Self::new(); 78840fe15e0SLoGin } 78940fe15e0SLoGin } 79040fe15e0SLoGin 79140fe15e0SLoGin /// 加了锁的VMA 79240fe15e0SLoGin /// 79340fe15e0SLoGin /// 备注:进行性能测试,看看SpinLock和RwLock哪个更快。 79440fe15e0SLoGin #[derive(Debug)] 79540fe15e0SLoGin pub struct LockedVMA(SpinLock<VMA>); 79640fe15e0SLoGin 79740fe15e0SLoGin impl core::hash::Hash for LockedVMA { 79840fe15e0SLoGin fn hash<H: Hasher>(&self, state: &mut H) { 79940fe15e0SLoGin self.0.lock().hash(state); 80040fe15e0SLoGin } 80140fe15e0SLoGin } 80240fe15e0SLoGin 80340fe15e0SLoGin impl PartialEq for LockedVMA { 80440fe15e0SLoGin fn eq(&self, other: &Self) -> bool { 80540fe15e0SLoGin self.0.lock().eq(&other.0.lock()) 80640fe15e0SLoGin } 80740fe15e0SLoGin } 80840fe15e0SLoGin 80940fe15e0SLoGin impl Eq for LockedVMA {} 81040fe15e0SLoGin 81140fe15e0SLoGin #[allow(dead_code)] 81240fe15e0SLoGin impl LockedVMA { 81340fe15e0SLoGin pub fn new(vma: VMA) -> Arc<Self> { 81440fe15e0SLoGin let r = Arc::new(Self(SpinLock::new(vma))); 81540fe15e0SLoGin r.0.lock().self_ref = Arc::downgrade(&r); 81640fe15e0SLoGin return r; 81740fe15e0SLoGin } 81840fe15e0SLoGin 81940fe15e0SLoGin pub fn lock(&self) -> SpinLockGuard<VMA> { 82040fe15e0SLoGin return self.0.lock(); 82140fe15e0SLoGin } 82240fe15e0SLoGin 82340fe15e0SLoGin /// 调整当前VMA的页面的标志位 82440fe15e0SLoGin /// 82540fe15e0SLoGin /// TODO:增加调整虚拟页映射的物理地址的功能 82640fe15e0SLoGin /// 82740fe15e0SLoGin /// @param flags 新的标志位 82840fe15e0SLoGin /// @param mapper 页表映射器 82940fe15e0SLoGin /// @param flusher 页表项刷新器 83040fe15e0SLoGin /// 83140fe15e0SLoGin pub fn remap( 83240fe15e0SLoGin &self, 83340fe15e0SLoGin flags: PageFlags<MMArch>, 83440fe15e0SLoGin mapper: &mut PageMapper, 83540fe15e0SLoGin mut flusher: impl Flusher<MMArch>, 83640fe15e0SLoGin ) -> Result<(), SystemError> { 83740fe15e0SLoGin let mut guard = self.lock(); 83840fe15e0SLoGin assert!(guard.mapped); 83940fe15e0SLoGin for page in guard.region.pages() { 84040fe15e0SLoGin // 暂时要求所有的页帧都已经映射到页表 84140fe15e0SLoGin // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了 84240fe15e0SLoGin let r = unsafe { 84340fe15e0SLoGin mapper 84440fe15e0SLoGin .remap(page.virt_address(), flags) 84540fe15e0SLoGin .expect("Failed to remap, beacuse of some page is not mapped") 84640fe15e0SLoGin }; 84740fe15e0SLoGin flusher.consume(r); 84840fe15e0SLoGin } 84940fe15e0SLoGin guard.flags = flags; 85040fe15e0SLoGin return Ok(()); 85140fe15e0SLoGin } 85240fe15e0SLoGin 85340fe15e0SLoGin pub fn unmap(&self, mapper: &mut PageMapper, mut flusher: impl Flusher<MMArch>) { 8541a62e776SLoGin // todo: 如果当前vma与文件相关,完善文件相关的逻辑 8551a62e776SLoGin 85640fe15e0SLoGin let mut guard = self.lock(); 85740fe15e0SLoGin assert!(guard.mapped); 85840fe15e0SLoGin for page in guard.region.pages() { 85940fe15e0SLoGin let (paddr, _, flush) = unsafe { mapper.unmap_phys(page.virt_address(), true) } 86040fe15e0SLoGin .expect("Failed to unmap, beacuse of some page is not mapped"); 86140fe15e0SLoGin 86240fe15e0SLoGin // todo: 获取物理页的anon_vma的守卫 86340fe15e0SLoGin 86440fe15e0SLoGin // todo: 从anon_vma中删除当前VMA 86540fe15e0SLoGin 86640fe15e0SLoGin // todo: 如果物理页的anon_vma链表长度为0,则释放物理页. 86740fe15e0SLoGin 86840fe15e0SLoGin // 目前由于还没有实现共享页,所以直接释放物理页也没问题。 86940fe15e0SLoGin // 但是在实现共享页之后,就不能直接释放物理页了,需要在anon_vma链表长度为0的时候才能释放物理页 87040fe15e0SLoGin unsafe { deallocate_page_frames(PhysPageFrame::new(paddr), PageFrameCount::new(1)) }; 87140fe15e0SLoGin 87240fe15e0SLoGin flusher.consume(flush); 87340fe15e0SLoGin } 87440fe15e0SLoGin guard.mapped = false; 87540fe15e0SLoGin } 87640fe15e0SLoGin 87740fe15e0SLoGin pub fn mapped(&self) -> bool { 87840fe15e0SLoGin return self.0.lock().mapped; 87940fe15e0SLoGin } 88040fe15e0SLoGin 88140fe15e0SLoGin /// 将当前VMA进行切分,切分成3个VMA,分别是: 88240fe15e0SLoGin /// 88340fe15e0SLoGin /// 1. 前面的VMA,如果没有则为None 88440fe15e0SLoGin /// 2. 中间的VMA,也就是传入的Region 88540fe15e0SLoGin /// 3. 后面的VMA,如果没有则为None 88640fe15e0SLoGin pub fn extract( 88740fe15e0SLoGin &self, 88840fe15e0SLoGin region: VirtRegion, 88940fe15e0SLoGin ) -> Option<( 89040fe15e0SLoGin Option<Arc<LockedVMA>>, 89140fe15e0SLoGin Arc<LockedVMA>, 89240fe15e0SLoGin Option<Arc<LockedVMA>>, 89340fe15e0SLoGin )> { 89440fe15e0SLoGin assert!(region.start().check_aligned(MMArch::PAGE_SIZE)); 89540fe15e0SLoGin assert!(region.end().check_aligned(MMArch::PAGE_SIZE)); 89640fe15e0SLoGin 89740fe15e0SLoGin let mut guard = self.lock(); 89840fe15e0SLoGin { 89940fe15e0SLoGin // 如果传入的region不在当前VMA的范围内,则直接返回None 90040fe15e0SLoGin if unlikely(region.start() < guard.region.start() || region.end() > guard.region.end()) 90140fe15e0SLoGin { 90240fe15e0SLoGin return None; 90340fe15e0SLoGin } 90440fe15e0SLoGin 90540fe15e0SLoGin let intersect: Option<VirtRegion> = guard.region.intersect(®ion); 90640fe15e0SLoGin // 如果当前VMA不包含region,则直接返回None 90740fe15e0SLoGin if unlikely(intersect.is_none()) { 90840fe15e0SLoGin return None; 90940fe15e0SLoGin } 91040fe15e0SLoGin let intersect: VirtRegion = intersect.unwrap(); 91140fe15e0SLoGin if unlikely(intersect == guard.region) { 91240fe15e0SLoGin // 如果当前VMA完全包含region,则直接返回当前VMA 91340fe15e0SLoGin return Some((None, guard.self_ref.upgrade().unwrap(), None)); 91440fe15e0SLoGin } 91540fe15e0SLoGin } 91640fe15e0SLoGin 91740fe15e0SLoGin let before: Option<Arc<LockedVMA>> = guard.region.before(®ion).map(|virt_region| { 91840fe15e0SLoGin let mut vma: VMA = unsafe { guard.clone() }; 91940fe15e0SLoGin vma.region = virt_region; 92040fe15e0SLoGin 92140fe15e0SLoGin let vma: Arc<LockedVMA> = LockedVMA::new(vma); 92240fe15e0SLoGin vma 92340fe15e0SLoGin }); 92440fe15e0SLoGin 92540fe15e0SLoGin let after: Option<Arc<LockedVMA>> = guard.region.after(®ion).map(|virt_region| { 92640fe15e0SLoGin let mut vma: VMA = unsafe { guard.clone() }; 92740fe15e0SLoGin vma.region = virt_region; 92840fe15e0SLoGin 92940fe15e0SLoGin let vma: Arc<LockedVMA> = LockedVMA::new(vma); 93040fe15e0SLoGin vma 93140fe15e0SLoGin }); 93240fe15e0SLoGin 93340fe15e0SLoGin guard.region = region; 93440fe15e0SLoGin 93540fe15e0SLoGin // TODO: 重新设置before、after这两个VMA里面的物理页的anon_vma 93640fe15e0SLoGin 93740fe15e0SLoGin return Some((before, guard.self_ref.upgrade().unwrap(), after)); 93840fe15e0SLoGin } 93940fe15e0SLoGin } 94040fe15e0SLoGin 94140fe15e0SLoGin /// @brief 虚拟内存区域 94240fe15e0SLoGin #[derive(Debug)] 94340fe15e0SLoGin pub struct VMA { 94440fe15e0SLoGin /// 虚拟内存区域对应的虚拟地址范围 94540fe15e0SLoGin region: VirtRegion, 94640fe15e0SLoGin /// VMA内的页帧的标志 94740fe15e0SLoGin flags: PageFlags<MMArch>, 94840fe15e0SLoGin /// VMA内的页帧是否已经映射到页表 94940fe15e0SLoGin mapped: bool, 95040fe15e0SLoGin /// VMA所属的用户地址空间 95140fe15e0SLoGin user_address_space: Option<Weak<AddressSpace>>, 95240fe15e0SLoGin self_ref: Weak<LockedVMA>, 953971462beSGnoCiYeH 954971462beSGnoCiYeH provider: Provider, 95540fe15e0SLoGin } 95640fe15e0SLoGin 95740fe15e0SLoGin impl core::hash::Hash for VMA { 95840fe15e0SLoGin fn hash<H: Hasher>(&self, state: &mut H) { 95940fe15e0SLoGin self.region.hash(state); 96040fe15e0SLoGin self.flags.hash(state); 96140fe15e0SLoGin self.mapped.hash(state); 96240fe15e0SLoGin } 96340fe15e0SLoGin } 96440fe15e0SLoGin 965971462beSGnoCiYeH /// 描述不同类型的内存提供者或资源 966971462beSGnoCiYeH #[derive(Debug)] 967971462beSGnoCiYeH pub enum Provider { 968971462beSGnoCiYeH Allocated, // TODO:其他 969971462beSGnoCiYeH } 970971462beSGnoCiYeH 97140fe15e0SLoGin #[allow(dead_code)] 97240fe15e0SLoGin impl VMA { 97340fe15e0SLoGin pub fn region(&self) -> &VirtRegion { 97440fe15e0SLoGin return &self.region; 97540fe15e0SLoGin } 97640fe15e0SLoGin 97740fe15e0SLoGin /// # 拷贝当前VMA的内容 97840fe15e0SLoGin /// 97940fe15e0SLoGin /// ### 安全性 98040fe15e0SLoGin /// 98140fe15e0SLoGin /// 由于这样操作可能由于错误的拷贝,导致内存泄露、内存重复释放等问题,所以需要小心使用。 98240fe15e0SLoGin pub unsafe fn clone(&self) -> Self { 98340fe15e0SLoGin return Self { 98440fe15e0SLoGin region: self.region, 98540fe15e0SLoGin flags: self.flags, 98640fe15e0SLoGin mapped: self.mapped, 98740fe15e0SLoGin user_address_space: self.user_address_space.clone(), 98840fe15e0SLoGin self_ref: self.self_ref.clone(), 989971462beSGnoCiYeH provider: Provider::Allocated, 99040fe15e0SLoGin }; 99140fe15e0SLoGin } 99240fe15e0SLoGin 99340fe15e0SLoGin #[inline(always)] 99440fe15e0SLoGin pub fn flags(&self) -> PageFlags<MMArch> { 99540fe15e0SLoGin return self.flags; 99640fe15e0SLoGin } 99740fe15e0SLoGin 99840fe15e0SLoGin pub fn pages(&self) -> VirtPageFrameIter { 99940fe15e0SLoGin return VirtPageFrameIter::new( 100040fe15e0SLoGin VirtPageFrame::new(self.region.start()), 100140fe15e0SLoGin VirtPageFrame::new(self.region.end()), 100240fe15e0SLoGin ); 100340fe15e0SLoGin } 100440fe15e0SLoGin 100540fe15e0SLoGin pub fn remap( 100640fe15e0SLoGin &mut self, 100740fe15e0SLoGin flags: PageFlags<MMArch>, 100840fe15e0SLoGin mapper: &mut PageMapper, 100940fe15e0SLoGin mut flusher: impl Flusher<MMArch>, 101040fe15e0SLoGin ) -> Result<(), SystemError> { 101140fe15e0SLoGin assert!(self.mapped); 101240fe15e0SLoGin for page in self.region.pages() { 101340fe15e0SLoGin // kdebug!("remap page {:?}", page.virt_address()); 101440fe15e0SLoGin // 暂时要求所有的页帧都已经映射到页表 101540fe15e0SLoGin // TODO: 引入Lazy Mapping, 通过缺页中断来映射页帧,这里就不必要求所有的页帧都已经映射到页表了 101640fe15e0SLoGin let r = unsafe { 101740fe15e0SLoGin mapper 101840fe15e0SLoGin .remap(page.virt_address(), flags) 101940fe15e0SLoGin .expect("Failed to remap, beacuse of some page is not mapped") 102040fe15e0SLoGin }; 102140fe15e0SLoGin // kdebug!("consume page {:?}", page.virt_address()); 102240fe15e0SLoGin flusher.consume(r); 102340fe15e0SLoGin // kdebug!("remap page {:?} done", page.virt_address()); 102440fe15e0SLoGin } 102540fe15e0SLoGin self.flags = flags; 102640fe15e0SLoGin return Ok(()); 102740fe15e0SLoGin } 102840fe15e0SLoGin 102940fe15e0SLoGin /// 检查当前VMA是否可以拥有指定的标志位 103040fe15e0SLoGin /// 103140fe15e0SLoGin /// ## 参数 103240fe15e0SLoGin /// 103340fe15e0SLoGin /// - `prot_flags` 要检查的标志位 103440fe15e0SLoGin pub fn can_have_flags(&self, prot_flags: ProtFlags) -> bool { 1035971462beSGnoCiYeH let is_downgrade = (self.flags.has_write() || !prot_flags.contains(ProtFlags::PROT_WRITE)) 103640fe15e0SLoGin && (self.flags.has_execute() || !prot_flags.contains(ProtFlags::PROT_EXEC)); 1037971462beSGnoCiYeH 1038971462beSGnoCiYeH match self.provider { 1039971462beSGnoCiYeH Provider::Allocated { .. } => true, 1040971462beSGnoCiYeH 1041971462beSGnoCiYeH #[allow(unreachable_patterns)] 1042971462beSGnoCiYeH _ => is_downgrade, 1043971462beSGnoCiYeH } 104440fe15e0SLoGin } 104540fe15e0SLoGin 104640fe15e0SLoGin /// 把物理地址映射到虚拟地址 104740fe15e0SLoGin /// 104840fe15e0SLoGin /// @param phys 要映射的物理地址 104940fe15e0SLoGin /// @param destination 要映射到的虚拟地址 105040fe15e0SLoGin /// @param count 要映射的页帧数量 105140fe15e0SLoGin /// @param flags 页面标志位 105240fe15e0SLoGin /// @param mapper 页表映射器 105340fe15e0SLoGin /// @param flusher 页表项刷新器 105440fe15e0SLoGin /// 105540fe15e0SLoGin /// @return 返回映射后的虚拟内存区域 105640fe15e0SLoGin pub fn physmap( 105740fe15e0SLoGin phys: PhysPageFrame, 105840fe15e0SLoGin destination: VirtPageFrame, 105940fe15e0SLoGin count: PageFrameCount, 106040fe15e0SLoGin flags: PageFlags<MMArch>, 106140fe15e0SLoGin mapper: &mut PageMapper, 106240fe15e0SLoGin mut flusher: impl Flusher<MMArch>, 106340fe15e0SLoGin ) -> Result<Arc<LockedVMA>, SystemError> { 106440fe15e0SLoGin { 106540fe15e0SLoGin let mut cur_phy = phys; 106640fe15e0SLoGin let mut cur_dest = destination; 106740fe15e0SLoGin 106840fe15e0SLoGin for _ in 0..count.data() { 106940fe15e0SLoGin // 将物理页帧映射到虚拟页帧 107040fe15e0SLoGin let r = unsafe { 107140fe15e0SLoGin mapper.map_phys(cur_dest.virt_address(), cur_phy.phys_address(), flags) 107240fe15e0SLoGin } 107340fe15e0SLoGin .expect("Failed to map phys, may be OOM error"); 107440fe15e0SLoGin 107540fe15e0SLoGin // todo: 增加OOM处理 107640fe15e0SLoGin 107740fe15e0SLoGin // todo: 将VMA加入到anon_vma中 107840fe15e0SLoGin 107940fe15e0SLoGin // 刷新TLB 108040fe15e0SLoGin flusher.consume(r); 108140fe15e0SLoGin 108240fe15e0SLoGin cur_phy = cur_phy.next(); 108340fe15e0SLoGin cur_dest = cur_dest.next(); 108440fe15e0SLoGin } 108540fe15e0SLoGin } 108640fe15e0SLoGin 108740fe15e0SLoGin let r: Arc<LockedVMA> = LockedVMA::new(VMA { 108840fe15e0SLoGin region: VirtRegion::new(destination.virt_address(), count.data() * MMArch::PAGE_SIZE), 108940fe15e0SLoGin flags, 109040fe15e0SLoGin mapped: true, 109140fe15e0SLoGin user_address_space: None, 109240fe15e0SLoGin self_ref: Weak::default(), 1093971462beSGnoCiYeH provider: Provider::Allocated, 109440fe15e0SLoGin }); 109540fe15e0SLoGin return Ok(r); 109640fe15e0SLoGin } 109740fe15e0SLoGin 109840fe15e0SLoGin /// 从页分配器中分配一些物理页,并把它们映射到指定的虚拟地址,然后创建VMA 109940fe15e0SLoGin /// 110040fe15e0SLoGin /// @param destination 要映射到的虚拟地址 110140fe15e0SLoGin /// @param count 要映射的页帧数量 110240fe15e0SLoGin /// @param flags 页面标志位 110340fe15e0SLoGin /// @param mapper 页表映射器 110440fe15e0SLoGin /// @param flusher 页表项刷新器 110540fe15e0SLoGin /// 110640fe15e0SLoGin /// @return 返回映射后的虚拟内存区域 110740fe15e0SLoGin pub fn zeroed( 110840fe15e0SLoGin destination: VirtPageFrame, 110940fe15e0SLoGin page_count: PageFrameCount, 111040fe15e0SLoGin flags: PageFlags<MMArch>, 111140fe15e0SLoGin mapper: &mut PageMapper, 111240fe15e0SLoGin mut flusher: impl Flusher<MMArch>, 111340fe15e0SLoGin ) -> Result<Arc<LockedVMA>, SystemError> { 111440fe15e0SLoGin let mut cur_dest: VirtPageFrame = destination; 111540fe15e0SLoGin // kdebug!( 111640fe15e0SLoGin // "VMA::zeroed: page_count = {:?}, destination={destination:?}", 111740fe15e0SLoGin // page_count 111840fe15e0SLoGin // ); 111940fe15e0SLoGin for _ in 0..page_count.data() { 112040fe15e0SLoGin // kdebug!( 112140fe15e0SLoGin // "VMA::zeroed: cur_dest={cur_dest:?}, vaddr = {:?}", 112240fe15e0SLoGin // cur_dest.virt_address() 112340fe15e0SLoGin // ); 112440fe15e0SLoGin let r = unsafe { mapper.map(cur_dest.virt_address(), flags) } 112540fe15e0SLoGin .expect("Failed to map zero, may be OOM error"); 112640fe15e0SLoGin // todo: 将VMA加入到anon_vma中 112740fe15e0SLoGin // todo: 增加OOM处理 112840fe15e0SLoGin 112940fe15e0SLoGin // 稍后再刷新TLB,这里取消刷新 113040fe15e0SLoGin flusher.consume(r); 113140fe15e0SLoGin cur_dest = cur_dest.next(); 113240fe15e0SLoGin } 113340fe15e0SLoGin let r = LockedVMA::new(VMA { 113440fe15e0SLoGin region: VirtRegion::new( 113540fe15e0SLoGin destination.virt_address(), 113640fe15e0SLoGin page_count.data() * MMArch::PAGE_SIZE, 113740fe15e0SLoGin ), 113840fe15e0SLoGin flags, 113940fe15e0SLoGin mapped: true, 114040fe15e0SLoGin user_address_space: None, 114140fe15e0SLoGin self_ref: Weak::default(), 1142971462beSGnoCiYeH provider: Provider::Allocated, 114340fe15e0SLoGin }); 114440fe15e0SLoGin drop(flusher); 114540fe15e0SLoGin // kdebug!("VMA::zeroed: flusher dropped"); 114640fe15e0SLoGin 114740fe15e0SLoGin // 清空这些内存 11489550910aSChiichen let virt_iter: VirtPageFrameIter = 11499550910aSChiichen VirtPageFrameIter::new(destination, destination.add(page_count)); 115040fe15e0SLoGin for frame in virt_iter { 115140fe15e0SLoGin let paddr = mapper.translate(frame.virt_address()).unwrap().0; 115240fe15e0SLoGin 115340fe15e0SLoGin unsafe { 115440fe15e0SLoGin let vaddr = MMArch::phys_2_virt(paddr).unwrap(); 115540fe15e0SLoGin MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE); 115640fe15e0SLoGin } 115740fe15e0SLoGin } 115840fe15e0SLoGin // kdebug!("VMA::zeroed: done"); 115940fe15e0SLoGin return Ok(r); 116040fe15e0SLoGin } 116140fe15e0SLoGin } 116240fe15e0SLoGin 116340fe15e0SLoGin impl Drop for VMA { 116440fe15e0SLoGin fn drop(&mut self) { 116540fe15e0SLoGin // 当VMA被释放时,需要确保它已经被从页表中解除映射 116640fe15e0SLoGin assert!(!self.mapped, "VMA is still mapped"); 116740fe15e0SLoGin } 116840fe15e0SLoGin } 116940fe15e0SLoGin 117040fe15e0SLoGin impl PartialEq for VMA { 117140fe15e0SLoGin fn eq(&self, other: &Self) -> bool { 117240fe15e0SLoGin return self.region == other.region; 117340fe15e0SLoGin } 117440fe15e0SLoGin } 117540fe15e0SLoGin 117640fe15e0SLoGin impl Eq for VMA {} 117740fe15e0SLoGin 117840fe15e0SLoGin impl PartialOrd for VMA { 117940fe15e0SLoGin fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { 118040fe15e0SLoGin return self.region.partial_cmp(&other.region); 118140fe15e0SLoGin } 118240fe15e0SLoGin } 118340fe15e0SLoGin 118440fe15e0SLoGin impl Ord for VMA { 118540fe15e0SLoGin fn cmp(&self, other: &Self) -> cmp::Ordering { 118640fe15e0SLoGin return self.region.cmp(&other.region); 118740fe15e0SLoGin } 118840fe15e0SLoGin } 118940fe15e0SLoGin 119040fe15e0SLoGin #[derive(Debug)] 119140fe15e0SLoGin pub struct UserStack { 119240fe15e0SLoGin // 栈底地址 119340fe15e0SLoGin stack_bottom: VirtAddr, 119440fe15e0SLoGin // 当前已映射的大小 119540fe15e0SLoGin mapped_size: usize, 119640fe15e0SLoGin /// 栈顶地址(这个值需要仔细确定!因为它可能不会实时与用户栈的真实栈顶保持一致!要小心!) 119740fe15e0SLoGin current_sp: VirtAddr, 119840fe15e0SLoGin } 119940fe15e0SLoGin 120040fe15e0SLoGin impl UserStack { 120140fe15e0SLoGin /// 默认的用户栈底地址 120240fe15e0SLoGin pub const DEFAULT_USER_STACK_BOTTOM: VirtAddr = MMArch::USER_STACK_START; 120340fe15e0SLoGin /// 默认的用户栈大小为8MB 120440fe15e0SLoGin pub const DEFAULT_USER_STACK_SIZE: usize = 8 * 1024 * 1024; 120540fe15e0SLoGin /// 用户栈的保护页数量 120640fe15e0SLoGin pub const GUARD_PAGES_NUM: usize = 4; 120740fe15e0SLoGin 120840fe15e0SLoGin /// 创建一个用户栈 120940fe15e0SLoGin pub fn new( 121040fe15e0SLoGin vm: &mut InnerAddressSpace, 121140fe15e0SLoGin stack_bottom: Option<VirtAddr>, 121240fe15e0SLoGin stack_size: usize, 121340fe15e0SLoGin ) -> Result<Self, SystemError> { 121440fe15e0SLoGin let stack_bottom = stack_bottom.unwrap_or(Self::DEFAULT_USER_STACK_BOTTOM); 121540fe15e0SLoGin assert!(stack_bottom.check_aligned(MMArch::PAGE_SIZE)); 121640fe15e0SLoGin 121740fe15e0SLoGin // 分配用户栈的保护页 121840fe15e0SLoGin let guard_size = Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE; 121940fe15e0SLoGin let actual_stack_bottom = stack_bottom - guard_size; 122040fe15e0SLoGin 122140fe15e0SLoGin let mut prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE; 122240fe15e0SLoGin let map_flags = 122340fe15e0SLoGin MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED_NOREPLACE; 122440fe15e0SLoGin // kdebug!( 122540fe15e0SLoGin // "map anonymous stack: {:?} {}", 122640fe15e0SLoGin // actual_stack_bottom, 122740fe15e0SLoGin // guard_size 122840fe15e0SLoGin // ); 122940fe15e0SLoGin vm.map_anonymous( 123040fe15e0SLoGin actual_stack_bottom, 123140fe15e0SLoGin guard_size, 123240fe15e0SLoGin prot_flags, 123340fe15e0SLoGin map_flags, 123440fe15e0SLoGin false, 123540fe15e0SLoGin )?; 123640fe15e0SLoGin // test_buddy(); 123740fe15e0SLoGin // 设置保护页只读 123840fe15e0SLoGin prot_flags.remove(ProtFlags::PROT_WRITE); 123940fe15e0SLoGin // kdebug!( 124040fe15e0SLoGin // "to mprotect stack guard pages: {:?} {}", 124140fe15e0SLoGin // actual_stack_bottom, 124240fe15e0SLoGin // guard_size 124340fe15e0SLoGin // ); 124440fe15e0SLoGin vm.mprotect( 124540fe15e0SLoGin VirtPageFrame::new(actual_stack_bottom), 124640fe15e0SLoGin PageFrameCount::new(Self::GUARD_PAGES_NUM), 124740fe15e0SLoGin prot_flags, 124840fe15e0SLoGin )?; 124940fe15e0SLoGin 125040fe15e0SLoGin // kdebug!( 125140fe15e0SLoGin // "mprotect stack guard pages done: {:?} {}", 125240fe15e0SLoGin // actual_stack_bottom, 125340fe15e0SLoGin // guard_size 125440fe15e0SLoGin // ); 125540fe15e0SLoGin 125640fe15e0SLoGin let mut user_stack = UserStack { 125740fe15e0SLoGin stack_bottom: actual_stack_bottom, 125840fe15e0SLoGin mapped_size: guard_size, 125940fe15e0SLoGin current_sp: actual_stack_bottom - guard_size, 126040fe15e0SLoGin }; 126140fe15e0SLoGin 126240fe15e0SLoGin // kdebug!("extend user stack: {:?} {}", stack_bottom, stack_size); 126340fe15e0SLoGin // 分配用户栈 126440fe15e0SLoGin user_stack.initial_extend(vm, stack_size)?; 126540fe15e0SLoGin // kdebug!("user stack created: {:?} {}", stack_bottom, stack_size); 126640fe15e0SLoGin return Ok(user_stack); 126740fe15e0SLoGin } 126840fe15e0SLoGin 126940fe15e0SLoGin fn initial_extend( 127040fe15e0SLoGin &mut self, 127140fe15e0SLoGin vm: &mut InnerAddressSpace, 127240fe15e0SLoGin mut bytes: usize, 127340fe15e0SLoGin ) -> Result<(), SystemError> { 127440fe15e0SLoGin let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC; 127540fe15e0SLoGin let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS; 127640fe15e0SLoGin 127740fe15e0SLoGin bytes = page_align_up(bytes); 127840fe15e0SLoGin self.mapped_size += bytes; 127940fe15e0SLoGin 128040fe15e0SLoGin vm.map_anonymous( 128140fe15e0SLoGin self.stack_bottom - self.mapped_size, 128240fe15e0SLoGin bytes, 128340fe15e0SLoGin prot_flags, 128440fe15e0SLoGin map_flags, 128540fe15e0SLoGin false, 128640fe15e0SLoGin )?; 128740fe15e0SLoGin 128840fe15e0SLoGin return Ok(()); 128940fe15e0SLoGin } 129040fe15e0SLoGin 129140fe15e0SLoGin /// 扩展用户栈 129240fe15e0SLoGin /// 129340fe15e0SLoGin /// ## 参数 129440fe15e0SLoGin /// 129540fe15e0SLoGin /// - `vm` 用户地址空间结构体 129640fe15e0SLoGin /// - `bytes` 要扩展的字节数 129740fe15e0SLoGin /// 129840fe15e0SLoGin /// ## 返回值 129940fe15e0SLoGin /// 130040fe15e0SLoGin /// - **Ok(())** 扩展成功 130140fe15e0SLoGin /// - **Err(SystemError)** 扩展失败 130240fe15e0SLoGin #[allow(dead_code)] 130340fe15e0SLoGin pub fn extend( 130440fe15e0SLoGin &mut self, 130540fe15e0SLoGin vm: &mut RwLockWriteGuard<InnerAddressSpace>, 130640fe15e0SLoGin mut bytes: usize, 130740fe15e0SLoGin ) -> Result<(), SystemError> { 130840fe15e0SLoGin let prot_flags = ProtFlags::PROT_READ | ProtFlags::PROT_WRITE | ProtFlags::PROT_EXEC; 130940fe15e0SLoGin let map_flags = MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS; 131040fe15e0SLoGin 131140fe15e0SLoGin bytes = page_align_up(bytes); 131240fe15e0SLoGin self.mapped_size += bytes; 131340fe15e0SLoGin 131440fe15e0SLoGin vm.map_anonymous( 131540fe15e0SLoGin self.stack_bottom - self.mapped_size, 131640fe15e0SLoGin bytes, 131740fe15e0SLoGin prot_flags, 131840fe15e0SLoGin map_flags, 131940fe15e0SLoGin false, 132040fe15e0SLoGin )?; 132140fe15e0SLoGin 132240fe15e0SLoGin return Ok(()); 132340fe15e0SLoGin } 132440fe15e0SLoGin 132540fe15e0SLoGin /// 获取栈顶地址 132640fe15e0SLoGin /// 132740fe15e0SLoGin /// 请注意,如果用户栈的栈顶地址发生变化,这个值可能不会实时更新! 132840fe15e0SLoGin pub fn sp(&self) -> VirtAddr { 132940fe15e0SLoGin return self.current_sp; 133040fe15e0SLoGin } 133140fe15e0SLoGin 133240fe15e0SLoGin pub unsafe fn set_sp(&mut self, sp: VirtAddr) { 133340fe15e0SLoGin self.current_sp = sp; 133440fe15e0SLoGin } 133540fe15e0SLoGin 133640fe15e0SLoGin /// 仅仅克隆用户栈的信息,不会克隆用户栈的内容/映射 133740fe15e0SLoGin pub unsafe fn clone_info_only(&self) -> Self { 133840fe15e0SLoGin return Self { 133940fe15e0SLoGin stack_bottom: self.stack_bottom, 134040fe15e0SLoGin mapped_size: self.mapped_size, 134140fe15e0SLoGin current_sp: self.current_sp, 134240fe15e0SLoGin }; 134340fe15e0SLoGin } 134440fe15e0SLoGin 134540fe15e0SLoGin /// 获取当前用户栈的大小(不包括保护页) 134640fe15e0SLoGin pub fn stack_size(&self) -> usize { 134740fe15e0SLoGin return self.mapped_size - Self::GUARD_PAGES_NUM * MMArch::PAGE_SIZE; 134840fe15e0SLoGin } 134940fe15e0SLoGin } 1350