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