Skip to content

Commit 5ce026e

Browse files
committed
[feat] add init_shared_vaddr_range_pgdir
1 parent 3bb49b9 commit 5ce026e

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

page_table_multiarch/src/eqbits64.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)