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