1
1
use core:: { alloc:: Layout , cmp:: min, intrinsics:: unlikely, panic} ;
2
2
3
- use alloc:: sync:: Arc ;
3
+ use alloc:: { sync:: Arc , vec :: Vec } ;
4
4
5
5
use crate :: {
6
6
arch:: { mm:: PageMapper , MMArch } ,
@@ -15,7 +15,8 @@ use crate::{
15
15
use crate :: mm:: MemoryManagementArch ;
16
16
17
17
use super :: {
18
- page:: { self , PageFlags } ,
18
+ allocator:: page_frame:: { FrameAllocator , PhysPageFrame } ,
19
+ page:: { Page , PageFlags } ,
19
20
phys_2_virt,
20
21
} ;
21
22
@@ -309,19 +310,20 @@ impl PageFaultHandler {
309
310
/// - VmFaultReason: 页面错误处理信息标志
310
311
#[ allow( dead_code, unused_variables) ]
311
312
pub unsafe fn do_read_fault ( pfm : PageFaultMessage , mapper : & mut PageMapper ) -> VmFaultReason {
312
- panic ! (
313
- "do_read_fault has not yet been implemented,
314
- fault message: {:?},
315
- pid: {}\n " ,
316
- pfm,
317
- crate :: process:: ProcessManager :: current_pid( ) . data( )
318
- ) ;
313
+ // panic!(
314
+ // "do_read_fault has not yet been implemented,
315
+ // fault message: {:?},
316
+ // pid: {}\n",
317
+ // pfm,
318
+ // crate::process::ProcessManager::current_pid().data()
319
+ // );
319
320
320
321
// TODO https://code.dragonos.org.cn/xref/linux-6.6.21/mm/memory.c#do_read_fault
321
- let mut ret = VmFaultReason :: empty ( ) ;
322
- ret = Self :: do_fault_around ( pfm, mapper) ;
323
- ret = Self :: filemap_fault ( pfm, mapper) ;
324
- return ret;
322
+ let ret = Self :: do_fault_around ( pfm. clone ( ) , mapper) ;
323
+ if !ret. is_empty ( ) {
324
+ return ret;
325
+ }
326
+ return Self :: filemap_fault ( pfm. clone ( ) , mapper) ;
325
327
}
326
328
327
329
/// 处理对共享文件映射区写入引起的缺页
@@ -433,20 +435,24 @@ impl PageFaultHandler {
433
435
}
434
436
435
437
pub unsafe fn do_fault_around ( pfm : PageFaultMessage , mapper : & mut PageMapper ) -> VmFaultReason {
436
- mapper
437
- . allocate_table ( * pfm. address ( ) , 0 )
438
- . expect ( "failed to allocate pte table" ) ;
438
+ if mapper. get_table ( * pfm. address ( ) , 0 ) . is_none ( ) {
439
+ mapper
440
+ . allocate_table ( * pfm. address ( ) , 0 )
441
+ . expect ( "failed to allocate pte table" ) ;
442
+ }
439
443
let vma = pfm. vma ( ) ;
440
444
let vma_guard = vma. lock ( ) ;
441
445
let vma_region = vma_guard. region ( ) ;
442
446
// 缺页在VMA中的偏移量
443
447
let vm_pgoff = ( * pfm. address ( ) - vma_region. start ( ) ) >> MMArch :: PAGE_SHIFT ;
448
+
444
449
// 缺页在PTE中的偏移量
445
- let pte_pgoff = ( pfm. address ( ) . data ( ) >> MMArch :: PAGE_SHIFT ) & ( 1 << MMArch :: PAGE_SIZE ) ;
450
+ let pte_pgoff =
451
+ ( pfm. address ( ) . data ( ) >> MMArch :: PAGE_SHIFT ) & ( 1 << MMArch :: PAGE_ENTRY_SHIFT ) ;
446
452
447
453
let vma_pages_count = ( vma_region. end ( ) - vma_region. start ( ) ) >> MMArch :: PAGE_SHIFT ;
448
454
449
- // 开始位置不能超出当前pte和vma头部的最小值
455
+ // 开始位置不能超出当前pte和vma头部
450
456
let from_pte = pte_pgoff - min ( vm_pgoff, pte_pgoff) ;
451
457
452
458
let fault_around_page_number = 16 ;
@@ -464,11 +470,11 @@ impl PageFaultHandler {
464
470
) ;
465
471
466
472
// 预先分配pte页表(如果不存在)
467
- if mapper. get_table ( * pfm. address ( ) , 0 ) . is_none ( ) {
468
- if mapper. allocate_table ( * pfm. address ( ) , 0 ) . is_none ( ) {
469
- return VmFaultReason :: VM_FAULT_OOM ;
470
- }
471
- } ;
473
+ if mapper. get_table ( * pfm. address ( ) , 0 ) . is_none ( )
474
+ && mapper. allocate_table ( * pfm. address ( ) , 0 ) . is_none ( )
475
+ {
476
+ return VmFaultReason :: VM_FAULT_OOM ;
477
+ }
472
478
473
479
// from_pte - pte_pgoff得出预读起始pte相对缺失页的偏移,加上pfm.file_pgoff(缺失页在文件中的偏移)得出起始页在文件中的偏移,结束pte同理
474
480
Self :: filemap_map_pages (
@@ -515,7 +521,7 @@ impl PageFaultHandler {
515
521
let frame = virt as * mut u8 ;
516
522
let new_frame =
517
523
phys_2_virt ( mapper. translate ( address) . unwrap ( ) . 0 . data ( ) ) as * mut u8 ;
518
- frame . copy_from_nonoverlapping ( new_frame , MMArch :: PAGE_SIZE ) ;
524
+ new_frame . copy_from_nonoverlapping ( frame , MMArch :: PAGE_SIZE ) ;
519
525
}
520
526
}
521
527
}
@@ -526,22 +532,44 @@ impl PageFaultHandler {
526
532
let vma = pfm. vma ( ) ;
527
533
let vma_guard = vma. lock ( ) ;
528
534
let file = vma_guard. vm_file ( ) . expect ( "no vm_file in vma" ) ;
529
- let page_cache = file. inode ( ) . page_cache ( ) . unwrap ( ) ;
535
+ let mut page_cache = file. inode ( ) . page_cache ( ) . unwrap ( ) ;
530
536
531
537
if let Some ( page) = page_cache. get_page ( pfm. file_pgoff ) {
532
538
// TODO 异步从磁盘中预读页面进PageCache
533
539
let address = vma_guard. region ( ) . start
534
- + ( pfm. file_pgoff
540
+ + ( ( pfm. file_pgoff
535
541
- vma_guard
536
542
. file_page_offset ( )
537
- . expect ( "file_page_offset is none" )
543
+ . expect ( "file_page_offset is none" ) )
538
544
<< MMArch :: PAGE_SHIFT ) ;
539
545
mapper. map ( address, vma_guard. flags ( ) ) . unwrap ( ) . flush ( ) ;
540
546
let frame = phys_2_virt ( page. phys_frame ( ) . phys_address ( ) . data ( ) ) as * mut u8 ;
541
547
let new_frame = phys_2_virt ( mapper. translate ( address) . unwrap ( ) . 0 . data ( ) ) as * mut u8 ;
542
- frame . copy_from_nonoverlapping ( new_frame , MMArch :: PAGE_SIZE ) ;
548
+ new_frame . copy_from_nonoverlapping ( frame , MMArch :: PAGE_SIZE ) ;
543
549
} else {
544
550
// TODO 同步预读
551
+ let mut buf: Vec < u8 > = vec ! [ 0 ; MMArch :: PAGE_SIZE ] ;
552
+ file. pread (
553
+ pfm. file_pgoff * MMArch :: PAGE_SIZE ,
554
+ MMArch :: PAGE_SIZE ,
555
+ & mut buf[ ..] ,
556
+ )
557
+ . unwrap ( ) ;
558
+ let allocator = mapper. allocator_mut ( ) ;
559
+
560
+ // 分配一个物理页面作为加入PageCache的新页
561
+ let new_cache_page = allocator. allocate_one ( ) . unwrap ( ) ;
562
+ ( phys_2_virt ( new_cache_page. data ( ) ) as * mut u8 )
563
+ . copy_from_nonoverlapping ( buf. as_mut_ptr ( ) , MMArch :: PAGE_SIZE ) ;
564
+ page_cache. add_page (
565
+ pfm. file_pgoff ,
566
+ Arc :: new ( Page :: new ( false , PhysPageFrame :: new ( new_cache_page) ) ) ,
567
+ ) ;
568
+
569
+ // 分配空白页并映射到缺页地址
570
+ mapper. map ( pfm. address , vma_guard. flags ( ) ) . unwrap ( ) . flush ( ) ;
571
+ let new_frame = phys_2_virt ( mapper. translate ( pfm. address ) . unwrap ( ) . 0 . data ( ) ) ;
572
+ ( new_frame as * mut u8 ) . copy_from_nonoverlapping ( buf. as_mut_ptr ( ) , MMArch :: PAGE_SIZE ) ;
545
573
}
546
574
VmFaultReason :: VM_FAULT_COMPLETED
547
575
}
0 commit comments