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