@@ -35,6 +35,7 @@ pub struct EqPageTable64Ext<
3535> {
3636 root_paddr : PhysAddr ,
3737 shared_vaddr_range : Option < AddrRange < M :: VirtAddr > > ,
38+ shared_vaddr_pgdir_initialized : bool ,
3839 _phantom : PhantomData < ( M , PTE , H , SH ) > ,
3940}
4041
@@ -70,10 +71,60 @@ impl<M: PagingMetaData, PTE: GenericPTE, H: PagingHandler, SH: PagingHandler>
7071 Ok ( Self {
7172 root_paddr,
7273 shared_vaddr_range,
74+ shared_vaddr_pgdir_initialized : false ,
7375 _phantom : PhantomData ,
7476 } )
7577 }
7678
79+ /// Initialize the P4E entries for the shared virtual address range,
80+ /// this function should be called before forking this process.
81+ fn init_shared_vaddr_range_pgdir ( & mut self ) -> PagingResult < ( ) > {
82+ let range = if let Some ( range) = & self . shared_vaddr_range {
83+ range
84+ } else {
85+ return Ok ( ( ) ) ;
86+ } ;
87+
88+ if M :: LEVELS == 3 {
89+ error ! (
90+ "shared_vaddr_range {:?} is not supported in 3-level page table" ,
91+ range
92+ ) ;
93+ return Err ( PagingError :: NotAligned ) ;
94+ }
95+
96+ let start_vaddr = range. start ;
97+ let end_vaddr = range. end ;
98+ if !start_vaddr. is_aligned ( P4E_ADDR_RANGE ) || !end_vaddr. is_aligned ( P4E_ADDR_RANGE ) {
99+ error ! (
100+ "shared_vaddr_range {:?} is not aligned to {:#x}" ,
101+ range, P4E_ADDR_RANGE
102+ ) ;
103+ return Err ( PagingError :: NotAligned ) ;
104+ }
105+
106+ let mut vaddr = start_vaddr. into ( ) ;
107+
108+ while vaddr < end_vaddr. into ( ) {
109+ let p4 = self . table_of_mut ( self . root_paddr ( ) ) ;
110+ let index = p4_index ( vaddr) ;
111+ let p4e = & mut p4[ index] ;
112+
113+ // Prefill the P4E, allocate the physical frame for the next level page table.
114+ // Because the PGDIR frame will be copied during fork, while the next level
115+ // page table is shared among processes.
116+ let _p3e = self . next_table_mut_or_create ( p4e, true ) ?;
117+
118+ info ! ( "Prefilled P4E[{index}] for vaddr {:#x}" , vaddr) ;
119+
120+ vaddr = vaddr. add ( P4E_ADDR_RANGE ) ;
121+ }
122+
123+ self . shared_vaddr_pgdir_initialized = true ;
124+
125+ Ok ( ( ) )
126+ }
127+
77128 /// Returns the physical address of the root page table.
78129 pub const fn root_paddr ( & self ) -> PhysAddr {
79130 self . root_paddr
@@ -507,6 +558,10 @@ impl<M: PagingMetaData, PTE: GenericPTE, H: PagingHandler, SH: PagingHandler>
507558 false
508559 } ;
509560
561+ if shared_pt && !self . shared_vaddr_pgdir_initialized {
562+ self . init_shared_vaddr_range_pgdir ( ) ?;
563+ }
564+
510565 let vaddr: usize = vaddr. into ( ) ;
511566
512567 // if shared_pt {
0 commit comments