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