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