1 use core::{ 2 alloc::Layout, 3 cmp::{max, min}, 4 intrinsics::unlikely, 5 panic, 6 }; 7 8 use alloc::sync::Arc; 9 10 use crate::{ 11 arch::{mm::PageMapper, MMArch}, 12 libs::align::align_down, 13 mm::{ 14 page::{page_manager_lock_irqsave, EntryFlags}, 15 ucontext::LockedVMA, 16 VirtAddr, VmFaultReason, VmFlags, 17 }, 18 process::{ProcessManager, ProcessState}, 19 }; 20 21 use crate::mm::MemoryManagementArch; 22 23 use super::{ 24 allocator::page_frame::FrameAllocator, 25 page::{page_reclaimer_lock_irqsave, Page, PageFlags}, 26 }; 27 28 bitflags! { 29 pub struct FaultFlags: u64{ 30 const FAULT_FLAG_WRITE = 1 << 0; 31 const FAULT_FLAG_MKWRITE = 1 << 1; 32 const FAULT_FLAG_ALLOW_RETRY = 1 << 2; 33 const FAULT_FLAG_RETRY_NOWAIT = 1 << 3; 34 const FAULT_FLAG_KILLABLE = 1 << 4; 35 const FAULT_FLAG_TRIED = 1 << 5; 36 const FAULT_FLAG_USER = 1 << 6; 37 const FAULT_FLAG_REMOTE = 1 << 7; 38 const FAULT_FLAG_INSTRUCTION = 1 << 8; 39 const FAULT_FLAG_INTERRUPTIBLE =1 << 9; 40 const FAULT_FLAG_UNSHARE = 1 << 10; 41 const FAULT_FLAG_ORIG_PTE_VALID = 1 << 11; 42 const FAULT_FLAG_VMA_LOCK = 1 << 12; 43 } 44 } 45 46 /// # 缺页异常信息结构体 47 /// 包含了页面错误处理的相关信息,例如出错的地址、VMA等 48 #[derive(Debug)] 49 pub struct PageFaultMessage<'a> { 50 /// 产生缺页的VMA结构体 51 vma: Arc<LockedVMA>, 52 /// 缺页地址 53 address: VirtAddr, 54 /// 异常处理标志 55 flags: FaultFlags, 56 /// 页表映射器 57 mapper: &'a mut PageMapper, 58 /// 缺页的文件页在文件中的偏移量 59 file_pgoff: Option<usize>, 60 /// 缺页对应PageCache中的文件页 61 page: Option<Arc<Page>>, 62 /// 写时拷贝需要的页面 63 cow_page: Option<Arc<Page>>, 64 } 65 66 impl<'a> PageFaultMessage<'a> { 67 pub fn new( 68 vma: Arc<LockedVMA>, 69 address: VirtAddr, 70 flags: FaultFlags, 71 mapper: &'a mut PageMapper, 72 ) -> Self { 73 let guard = vma.lock_irqsave(); 74 let file_pgoff = guard.file_page_offset().map(|file_page_offset| { 75 ((address - guard.region().start()) >> MMArch::PAGE_SHIFT) + file_page_offset 76 }); 77 Self { 78 vma: vma.clone(), 79 address: VirtAddr::new(crate::libs::align::page_align_down(address.data())), 80 flags, 81 file_pgoff, 82 page: None, 83 mapper, 84 cow_page: None, 85 } 86 } 87 88 #[inline(always)] 89 #[allow(dead_code)] 90 pub fn vma(&self) -> Arc<LockedVMA> { 91 self.vma.clone() 92 } 93 94 #[inline(always)] 95 #[allow(dead_code)] 96 pub fn address(&self) -> VirtAddr { 97 self.address 98 } 99 100 #[inline(always)] 101 #[allow(dead_code)] 102 pub fn address_aligned_down(&self) -> VirtAddr { 103 VirtAddr::new(crate::libs::align::page_align_down(self.address.data())) 104 } 105 106 #[inline(always)] 107 #[allow(dead_code)] 108 pub fn flags(&self) -> FaultFlags { 109 self.flags 110 } 111 } 112 113 /// 缺页中断处理结构体 114 pub struct PageFaultHandler; 115 116 impl PageFaultHandler { 117 /// 处理缺页异常 118 /// ## 参数 119 /// 120 /// - `pfm`: 缺页异常信息 121 /// - `mapper`: 页表映射器 122 /// 123 /// ## 返回值 124 /// - VmFaultReason: 页面错误处理信息标志 125 pub unsafe fn handle_mm_fault(mut pfm: PageFaultMessage) -> VmFaultReason { 126 let flags = pfm.flags(); 127 let vma = pfm.vma(); 128 let current_pcb = ProcessManager::current_pcb(); 129 let mut guard = current_pcb.sched_info().inner_lock_write_irqsave(); 130 guard.set_state(ProcessState::Runnable); 131 132 if !MMArch::vma_access_permitted( 133 vma.clone(), 134 flags.contains(FaultFlags::FAULT_FLAG_WRITE), 135 flags.contains(FaultFlags::FAULT_FLAG_INSTRUCTION), 136 flags.contains(FaultFlags::FAULT_FLAG_REMOTE), 137 ) { 138 return VmFaultReason::VM_FAULT_SIGSEGV; 139 } 140 141 let guard = vma.lock_irqsave(); 142 let vm_flags = *guard.vm_flags(); 143 drop(guard); 144 if unlikely(vm_flags.contains(VmFlags::VM_HUGETLB)) { 145 //TODO: 添加handle_hugetlb_fault处理大页缺页异常 146 } else { 147 Self::handle_normal_fault(&mut pfm); 148 } 149 150 VmFaultReason::VM_FAULT_COMPLETED 151 } 152 153 /// 处理普通页缺页异常 154 /// ## 参数 155 /// 156 /// - `pfm`: 缺页异常信息 157 /// - `mapper`: 页表映射器 158 /// 159 /// ## 返回值 160 /// - VmFaultReason: 页面错误处理信息标志 161 pub unsafe fn handle_normal_fault(pfm: &mut PageFaultMessage) -> VmFaultReason { 162 let address = pfm.address_aligned_down(); 163 let vma = pfm.vma.clone(); 164 let mapper = &mut pfm.mapper; 165 if mapper.get_entry(address, 3).is_none() { 166 mapper 167 .allocate_table(address, 2) 168 .expect("failed to allocate PUD table"); 169 } 170 let page_flags = vma.lock_irqsave().flags(); 171 172 for level in 2..=3 { 173 let level = MMArch::PAGE_LEVELS - level; 174 if mapper.get_entry(address, level).is_none() { 175 if vma.is_hugepage() { 176 if vma.is_anonymous() { 177 mapper.map_huge_page(address, page_flags); 178 } 179 } else if mapper.allocate_table(address, level - 1).is_none() { 180 return VmFaultReason::VM_FAULT_OOM; 181 } 182 } 183 } 184 185 Self::handle_pte_fault(pfm) 186 } 187 188 /// 处理页表项异常 189 /// ## 参数 190 /// 191 /// - `pfm`: 缺页异常信息 192 /// - `mapper`: 页表映射器 193 /// 194 /// ## 返回值 195 /// - VmFaultReason: 页面错误处理信息标志 196 pub unsafe fn handle_pte_fault(pfm: &mut PageFaultMessage) -> VmFaultReason { 197 let address = pfm.address_aligned_down(); 198 let flags = pfm.flags; 199 let vma = pfm.vma.clone(); 200 let mut ret = VmFaultReason::VM_FAULT_COMPLETED; 201 let mapper = &pfm.mapper; 202 203 // pte存在 204 if let Some(mut entry) = mapper.get_entry(address, 0) { 205 if !entry.present() { 206 ret = Self::do_swap_page(pfm); 207 } 208 209 if entry.protnone() && vma.is_accessible() { 210 ret = Self::do_numa_page(pfm); 211 } 212 213 if flags.intersects(FaultFlags::FAULT_FLAG_WRITE | FaultFlags::FAULT_FLAG_UNSHARE) { 214 if !entry.write() { 215 ret = Self::do_wp_page(pfm); 216 } else { 217 entry.set_flags(EntryFlags::from_data(MMArch::ENTRY_FLAG_DIRTY)); 218 } 219 } 220 } else if vma.is_anonymous() { 221 ret = Self::do_anonymous_page(pfm); 222 } else { 223 ret = Self::do_fault(pfm); 224 } 225 226 vma.lock_irqsave().set_mapped(true); 227 228 return ret; 229 } 230 231 /// 处理匿名映射页缺页异常 232 /// ## 参数 233 /// 234 /// - `pfm`: 缺页异常信息 235 /// - `mapper`: 页表映射器 236 /// 237 /// ## 返回值 238 /// - VmFaultReason: 页面错误处理信息标志 239 pub unsafe fn do_anonymous_page(pfm: &mut PageFaultMessage) -> VmFaultReason { 240 let address = pfm.address_aligned_down(); 241 let vma = pfm.vma.clone(); 242 let guard = vma.lock_irqsave(); 243 let mapper = &mut pfm.mapper; 244 245 if let Some(flush) = mapper.map(address, guard.flags()) { 246 flush.flush(); 247 crate::debug::klog::mm::mm_debug_log( 248 klog_types::AllocatorLogType::LazyAlloc(klog_types::AllocLogItem::new( 249 Layout::from_size_align(MMArch::PAGE_SIZE, MMArch::PAGE_SIZE).unwrap(), 250 Some(address.data()), 251 Some(mapper.translate(address).unwrap().0.data()), 252 )), 253 klog_types::LogSource::Buddy, 254 ); 255 let paddr = mapper.translate(address).unwrap().0; 256 let mut page_manager_guard = page_manager_lock_irqsave(); 257 let page = page_manager_guard.get_unwrap(&paddr); 258 page.write_irqsave().insert_vma(vma.clone()); 259 VmFaultReason::VM_FAULT_COMPLETED 260 } else { 261 VmFaultReason::VM_FAULT_OOM 262 } 263 } 264 265 /// 处理文件映射页的缺页异常 266 /// ## 参数 267 /// 268 /// - `pfm`: 缺页异常信息 269 /// - `mapper`: 页表映射器 270 /// 271 /// ## 返回值 272 /// - VmFaultReason: 页面错误处理信息标志 273 pub unsafe fn do_fault(pfm: &mut PageFaultMessage) -> VmFaultReason { 274 if !pfm.flags().contains(FaultFlags::FAULT_FLAG_WRITE) { 275 return Self::do_read_fault(pfm); 276 } else if !pfm 277 .vma() 278 .lock_irqsave() 279 .vm_flags() 280 .contains(VmFlags::VM_SHARED) 281 { 282 return Self::do_cow_fault(pfm); 283 } else { 284 return Self::do_shared_fault(pfm); 285 } 286 } 287 288 /// 处理私有文件映射的写时复制 289 /// ## 参数 290 /// 291 /// - `pfm`: 缺页异常信息 292 /// - `mapper`: 页表映射器 293 /// 294 /// ## 返回值 295 /// - VmFaultReason: 页面错误处理信息标志 296 pub unsafe fn do_cow_fault(pfm: &mut PageFaultMessage) -> VmFaultReason { 297 let mut ret = Self::filemap_fault(pfm); 298 299 if unlikely(ret.intersects( 300 VmFaultReason::VM_FAULT_ERROR 301 | VmFaultReason::VM_FAULT_NOPAGE 302 | VmFaultReason::VM_FAULT_RETRY 303 | VmFaultReason::VM_FAULT_DONE_COW, 304 )) { 305 return ret; 306 } 307 308 let cache_page = pfm.page.clone().unwrap(); 309 let mapper = &mut pfm.mapper; 310 311 let cow_page_phys = mapper.allocator_mut().allocate_one(); 312 if cow_page_phys.is_none() { 313 return VmFaultReason::VM_FAULT_OOM; 314 } 315 let cow_page_phys = cow_page_phys.unwrap(); 316 317 let cow_page = Arc::new(Page::new(false, cow_page_phys)); 318 pfm.cow_page = Some(cow_page.clone()); 319 320 //复制PageCache内容到新的页内 321 let new_frame = MMArch::phys_2_virt(cow_page_phys).unwrap(); 322 (new_frame.data() as *mut u8).copy_from_nonoverlapping( 323 MMArch::phys_2_virt(cache_page.read_irqsave().phys_address()) 324 .unwrap() 325 .data() as *mut u8, 326 MMArch::PAGE_SIZE, 327 ); 328 329 let mut page_manager_guard = page_manager_lock_irqsave(); 330 331 // 新页加入页管理器中 332 page_manager_guard.insert(cow_page_phys, &cow_page); 333 cow_page.write_irqsave().set_page_cache_index( 334 cache_page.read_irqsave().page_cache(), 335 cache_page.read_irqsave().index(), 336 ); 337 338 ret = ret.union(Self::finish_fault(pfm)); 339 340 ret 341 } 342 343 /// 处理文件映射页的缺页异常 344 /// ## 参数 345 /// 346 /// - `pfm`: 缺页异常信息 347 /// - `mapper`: 页表映射器 348 /// 349 /// ## 返回值 350 /// - VmFaultReason: 页面错误处理信息标志 351 pub unsafe fn do_read_fault(pfm: &mut PageFaultMessage) -> VmFaultReason { 352 let fs = pfm.vma().lock_irqsave().vm_file().unwrap().inode().fs(); 353 354 let mut ret = Self::do_fault_around(pfm); 355 if !ret.is_empty() { 356 return ret; 357 } 358 359 ret = fs.fault(pfm); 360 361 ret = ret.union(Self::finish_fault(pfm)); 362 363 ret 364 } 365 366 /// 处理对共享文件映射区写入引起的缺页 367 /// ## 参数 368 /// 369 /// - `pfm`: 缺页异常信息 370 /// - `mapper`: 页表映射器 371 /// 372 /// ## 返回值 373 /// - VmFaultReason: 页面错误处理信息标志 374 pub unsafe fn do_shared_fault(pfm: &mut PageFaultMessage) -> VmFaultReason { 375 let mut ret = Self::filemap_fault(pfm); 376 377 let cache_page = pfm.page.clone().expect("no cache_page in PageFaultMessage"); 378 379 // 将pagecache页设为脏页,以便回收时能够回写 380 cache_page.write_irqsave().add_flags(PageFlags::PG_DIRTY); 381 ret = ret.union(Self::finish_fault(pfm)); 382 383 ret 384 } 385 386 /// 处理被置换页面的缺页异常 387 /// ## 参数 388 /// 389 /// - `pfm`: 缺页异常信息 390 /// - `mapper`: 页表映射器 391 /// 392 /// ## 返回值 393 /// - VmFaultReason: 页面错误处理信息标志 394 #[allow(unused_variables)] 395 pub unsafe fn do_swap_page(pfm: &mut PageFaultMessage) -> VmFaultReason { 396 panic!( 397 "do_swap_page has not yet been implemented, 398 fault message: {:?}, 399 pid: {}\n", 400 pfm, 401 crate::process::ProcessManager::current_pid().data() 402 ); 403 // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_swap_page 404 } 405 406 /// 处理NUMA的缺页异常 407 /// ## 参数 408 /// 409 /// - `pfm`: 缺页异常信息 410 /// - `mapper`: 页表映射器 411 /// 412 /// ## 返回值 413 /// - VmFaultReason: 页面错误处理信息标志 414 #[allow(unused_variables)] 415 pub unsafe fn do_numa_page(pfm: &mut PageFaultMessage) -> VmFaultReason { 416 panic!( 417 "do_numa_page has not yet been implemented, 418 fault message: {:?}, 419 pid: {}\n", 420 pfm, 421 crate::process::ProcessManager::current_pid().data() 422 ); 423 // TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_numa_page 424 } 425 426 /// 处理写保护页面的写保护异常 427 /// ## 参数 428 /// 429 /// - `pfm`: 缺页异常信息 430 /// - `mapper`: 页表映射器 431 /// 432 /// ## 返回值 433 /// - VmFaultReason: 页面错误处理信息标志 434 pub unsafe fn do_wp_page(pfm: &mut PageFaultMessage) -> VmFaultReason { 435 let address = pfm.address_aligned_down(); 436 let vma = pfm.vma.clone(); 437 let mapper = &mut pfm.mapper; 438 439 let old_paddr = mapper.translate(address).unwrap().0; 440 let mut page_manager = page_manager_lock_irqsave(); 441 let old_page = page_manager.get_unwrap(&old_paddr); 442 let map_count = old_page.read_irqsave().map_count(); 443 drop(page_manager); 444 445 let mut entry = mapper.get_entry(address, 0).unwrap(); 446 let new_flags = entry.flags().set_write(true).set_dirty(true); 447 448 if vma.lock().vm_flags().contains(VmFlags::VM_SHARED) { 449 // 共享映射,直接修改页表项保护位,标记为脏页 450 let table = mapper.get_table(address, 0).unwrap(); 451 let i = table.index_of(address).unwrap(); 452 entry.set_flags(new_flags); 453 table.set_entry(i, entry); 454 455 old_page.write_irqsave().add_flags(PageFlags::PG_DIRTY); 456 457 VmFaultReason::VM_FAULT_COMPLETED 458 } else if vma.is_anonymous() { 459 // 私有匿名映射,根据引用计数判断是否拷贝页面 460 if map_count == 1 { 461 let table = mapper.get_table(address, 0).unwrap(); 462 let i = table.index_of(address).unwrap(); 463 entry.set_flags(new_flags); 464 table.set_entry(i, entry); 465 VmFaultReason::VM_FAULT_COMPLETED 466 } else if let Some(flush) = mapper.map(address, new_flags) { 467 let mut page_manager_guard = page_manager_lock_irqsave(); 468 let old_page = page_manager_guard.get_unwrap(&old_paddr); 469 old_page.write_irqsave().remove_vma(&vma); 470 // drop(page_manager_guard); 471 472 flush.flush(); 473 let paddr = mapper.translate(address).unwrap().0; 474 // let mut page_manager_guard = page_manager_lock_irqsave(); 475 let page = page_manager_guard.get_unwrap(&paddr); 476 page.write_irqsave().insert_vma(vma.clone()); 477 478 (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping( 479 MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8, 480 MMArch::PAGE_SIZE, 481 ); 482 483 VmFaultReason::VM_FAULT_COMPLETED 484 } else { 485 VmFaultReason::VM_FAULT_OOM 486 } 487 } else { 488 // 私有文件映射,必须拷贝页面 489 if let Some(flush) = mapper.map(address, new_flags) { 490 let mut page_manager_guard = page_manager_lock_irqsave(); 491 let old_page = page_manager_guard.get_unwrap(&old_paddr); 492 old_page.write_irqsave().remove_vma(&vma); 493 // drop(page_manager_guard); 494 495 flush.flush(); 496 let paddr = mapper.translate(address).unwrap().0; 497 // let mut page_manager_guard = page_manager_lock_irqsave(); 498 let page = page_manager_guard.get_unwrap(&paddr); 499 page.write_irqsave().insert_vma(vma.clone()); 500 501 (MMArch::phys_2_virt(paddr).unwrap().data() as *mut u8).copy_from_nonoverlapping( 502 MMArch::phys_2_virt(old_paddr).unwrap().data() as *mut u8, 503 MMArch::PAGE_SIZE, 504 ); 505 506 VmFaultReason::VM_FAULT_COMPLETED 507 } else { 508 VmFaultReason::VM_FAULT_OOM 509 } 510 } 511 } 512 513 /// 缺页附近页预读 514 /// ## 参数 515 /// 516 /// - `pfm`: 缺页异常信息 517 /// - `mapper`: 页表映射器 518 /// 519 /// ## 返回值 520 /// - VmFaultReason: 页面错误处理信息标志 521 pub unsafe fn do_fault_around(pfm: &mut PageFaultMessage) -> VmFaultReason { 522 let vma = pfm.vma(); 523 let address = pfm.address(); 524 let mapper = &mut pfm.mapper; 525 526 if mapper.get_table(address, 0).is_none() { 527 mapper 528 .allocate_table(address, 0) 529 .expect("failed to allocate pte table"); 530 } 531 let vma_guard = vma.lock_irqsave(); 532 let vma_region = *vma_guard.region(); 533 drop(vma_guard); 534 535 // 缺页在VMA中的偏移量 536 let vm_pgoff = (address - vma_region.start()) >> MMArch::PAGE_SHIFT; 537 538 // 缺页在PTE中的偏移量 539 let pte_pgoff = (address.data() >> MMArch::PAGE_SHIFT) & (1 << MMArch::PAGE_ENTRY_SHIFT); 540 541 // 缺页在文件中的偏移量 542 let file_pgoff = pfm.file_pgoff.expect("no file_pgoff"); 543 544 let vma_pages_count = (vma_region.end() - vma_region.start()) >> MMArch::PAGE_SHIFT; 545 546 let fault_around_page_number = 16; 547 548 // 开始位置不能超出当前pte和vma头部 549 let from_pte = max( 550 align_down(pte_pgoff, fault_around_page_number), 551 pte_pgoff - min(vm_pgoff, pte_pgoff), 552 ); 553 554 // pte结束位置不能超过: 555 // 1.最大预读上限(默认16) 556 // 2.最大pte(512) 557 // 3.vma结束位置(pte_pgoff + (vma_pages_count - vm_pgoff)计算出vma结束页号对当前pte开头的偏移) 558 let to_pte = min( 559 from_pte + fault_around_page_number, 560 min( 561 1 << MMArch::PAGE_SHIFT, 562 pte_pgoff + (vma_pages_count - vm_pgoff), 563 ), 564 ); 565 566 // 预先分配pte页表(如果不存在) 567 if mapper.get_table(address, 0).is_none() && mapper.allocate_table(address, 0).is_none() { 568 return VmFaultReason::VM_FAULT_OOM; 569 } 570 571 let fs = pfm.vma().lock_irqsave().vm_file().unwrap().inode().fs(); 572 // from_pte - pte_pgoff得出预读起始pte相对缺失页的偏移,加上pfm.file_pgoff(缺失页在文件中的偏移)得出起始页在文件中的偏移,结束pte同理 573 fs.map_pages( 574 pfm, 575 file_pgoff + (from_pte - pte_pgoff), 576 file_pgoff + (to_pte - pte_pgoff), 577 ); 578 579 VmFaultReason::empty() 580 } 581 582 /// 通用的VMA文件映射页面映射函数,将PageCache中的页面映射到进程空间 583 /// ## 参数 584 /// 585 /// - `pfm`: 缺页异常信息 586 /// - `mapper`: 页表映射器 587 /// 588 /// ## 返回值 589 /// - VmFaultReason: 页面错误处理信息标志 590 pub unsafe fn filemap_map_pages( 591 pfm: &mut PageFaultMessage, 592 593 start_pgoff: usize, 594 end_pgoff: usize, 595 ) -> VmFaultReason { 596 let vma = pfm.vma(); 597 let vma_guard = vma.lock_irqsave(); 598 let file = vma_guard.vm_file().expect("no vm_file in vma"); 599 let page_cache = file.inode().page_cache().unwrap(); 600 let mapper = &mut pfm.mapper; 601 602 // 起始页地址 603 let addr = vma_guard.region().start 604 + ((start_pgoff 605 - vma_guard 606 .file_page_offset() 607 .expect("file_page_offset is none")) 608 << MMArch::PAGE_SHIFT); 609 610 for pgoff in start_pgoff..=end_pgoff { 611 if let Some(page) = page_cache.get_page(pgoff) { 612 let page_guard = page.read_irqsave(); 613 if page_guard.flags().contains(PageFlags::PG_UPTODATE) { 614 let phys = page_guard.phys_address(); 615 616 let address = 617 VirtAddr::new(addr.data() + ((pgoff - start_pgoff) << MMArch::PAGE_SHIFT)); 618 mapper 619 .map_phys(address, phys, vma_guard.flags()) 620 .unwrap() 621 .flush(); 622 } 623 } 624 } 625 VmFaultReason::empty() 626 } 627 628 /// 通用的VMA文件映射错误处理函数 629 /// ## 参数 630 /// 631 /// - `pfm`: 缺页异常信息 632 /// - `mapper`: 页表映射器 633 /// 634 /// ## 返回值 635 /// - VmFaultReason: 页面错误处理信息标志 636 pub unsafe fn filemap_fault(pfm: &mut PageFaultMessage) -> VmFaultReason { 637 let vma = pfm.vma(); 638 let vma_guard = vma.lock_irqsave(); 639 let file = vma_guard.vm_file().expect("no vm_file in vma"); 640 let page_cache = file.inode().page_cache().unwrap(); 641 let file_pgoff = pfm.file_pgoff.expect("no file_pgoff"); 642 let mapper = &mut pfm.mapper; 643 let mut ret = VmFaultReason::empty(); 644 645 if let Some(page) = page_cache.get_page(file_pgoff) { 646 // TODO 异步从磁盘中预读页面进PageCache 647 648 // 直接将PageCache中的页面作为要映射的页面 649 pfm.page = Some(page.clone()); 650 } else { 651 // TODO 同步预读 652 //涉及磁盘IO,返回标志为VM_FAULT_MAJOR 653 ret = VmFaultReason::VM_FAULT_MAJOR; 654 // let mut buf: Vec<u8> = vec![0; MMArch::PAGE_SIZE]; 655 656 let allocator = mapper.allocator_mut(); 657 658 // 分配一个物理页面作为加入PageCache的新页 659 let new_cache_page = allocator.allocate_one().unwrap(); 660 // (MMArch::phys_2_virt(new_cache_page).unwrap().data() as *mut u8) 661 // .copy_from_nonoverlapping(buf.as_mut_ptr(), MMArch::PAGE_SIZE); 662 file.pread( 663 file_pgoff * MMArch::PAGE_SIZE, 664 MMArch::PAGE_SIZE, 665 core::slice::from_raw_parts_mut( 666 MMArch::phys_2_virt(new_cache_page).unwrap().data() as *mut u8, 667 MMArch::PAGE_SIZE, 668 ), 669 ) 670 .expect("failed to read file to create pagecache page"); 671 672 let page = Arc::new(Page::new(true, new_cache_page)); 673 pfm.page = Some(page.clone()); 674 675 page.write_irqsave().add_flags(PageFlags::PG_LRU); 676 page_manager_lock_irqsave().insert(new_cache_page, &page); 677 page_reclaimer_lock_irqsave().insert_page(new_cache_page, &page); 678 page_cache.add_page(file_pgoff, &page); 679 680 page.write_irqsave() 681 .set_page_cache_index(Some(page_cache), Some(file_pgoff)); 682 } 683 ret 684 } 685 686 /// 将文件页映射到缺页地址 687 /// ## 参数 688 /// 689 /// - `pfm`: 缺页异常信息 690 /// - `mapper`: 页表映射器 691 /// 692 /// ## 返回值 693 /// - VmFaultReason: 页面错误处理信息标志 694 pub unsafe fn finish_fault(pfm: &mut PageFaultMessage) -> VmFaultReason { 695 let vma = pfm.vma(); 696 let vma_guard = vma.lock_irqsave(); 697 let flags = pfm.flags(); 698 let cache_page = pfm.page.clone(); 699 let cow_page = pfm.cow_page.clone(); 700 let address = pfm.address(); 701 let mapper = &mut pfm.mapper; 702 703 let page_to_map = if flags.contains(FaultFlags::FAULT_FLAG_WRITE) 704 && !vma_guard.vm_flags().contains(VmFlags::VM_SHARED) 705 { 706 // 私有文件映射的写时复制 707 cow_page.expect("no cow_page in PageFaultMessage") 708 } else { 709 // 直接映射到PageCache 710 cache_page.expect("no cache_page in PageFaultMessage") 711 }; 712 713 let page_phys = page_to_map.read_irqsave().phys_address(); 714 715 mapper.map_phys(address, page_phys, vma_guard.flags()); 716 page_to_map.write_irqsave().insert_vma(pfm.vma()); 717 VmFaultReason::VM_FAULT_COMPLETED 718 } 719 } 720