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