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