diff --git a/ostd/src/mm/page_table/boot_pt.rs b/ostd/src/mm/page_table/boot_pt.rs index c544a3870..14e9e0ea6 100644 --- a/ostd/src/mm/page_table/boot_pt.rs +++ b/ostd/src/mm/page_table/boot_pt.rs @@ -168,11 +168,14 @@ impl BootPageTable { // Walk to the last level of the page table. while level > 1 { let index = pte_index::(from, level); + // SAFETY: The result pointer is within the PT frame. let pte_ptr = unsafe { (paddr_to_vaddr(pt) as *mut E).add(index) }; + // SAFETY: The pointer to the entry is valid to read. let pte = unsafe { pte_ptr.read() }; match pte.to_repr(level) { PteScalar::Absent => { let (pte, child_pt) = self.alloc_child(level); + // SAFETY: The pointer to the entry is valid to write. unsafe { pte_ptr.write(pte) }; pt = child_pt; } @@ -187,11 +190,14 @@ impl BootPageTable { } // Map the page in the last level page table. let index = pte_index::(from, 1); + // SAFETY: The result pointer is within the PT frame. let pte_ptr = unsafe { (paddr_to_vaddr(pt) as *mut E).add(index) }; + // SAFETY: The pointer to the entry is valid to read. let pte = unsafe { pte_ptr.read() }; if matches!(pte.to_repr(1), PteScalar::Mapped(_, _)) { panic!("mapping an already mapped page in the boot page table"); } + // SAFETY: The pointer to the entry is valid to write. unsafe { pte_ptr.write(E::from_repr(&PteScalar::Mapped(to, prop), 1)) }; } @@ -219,7 +225,9 @@ impl BootPageTable { // Walk to the last level of the page table. while level > 1 { let index = pte_index::(virt_addr, level); + // SAFETY: The result pointer is within the PT frame. let pte_ptr = unsafe { (paddr_to_vaddr(pt) as *mut E).add(index) }; + // SAFETY: The pointer to the entry is valid to read. let pte = unsafe { pte_ptr.read() }; match pte.to_repr(level) { PteScalar::Absent => { @@ -232,7 +240,9 @@ impl BootPageTable { // Split the huge page. let (child_pte, child_frame_pa) = self.alloc_child(level); for i in 0..nr_subpage_per_huge::() { + // SAFETY: The result pointer is within the new PT frame. let nxt_ptr = unsafe { (paddr_to_vaddr(child_frame_pa) as *mut E).add(i) }; + // SAFETY: The pointer to the entry is valid to write. unsafe { nxt_ptr.write(E::from_repr( &PteScalar::Mapped(huge_pa + i * C::BASE_PAGE_SIZE, prop), @@ -240,6 +250,7 @@ impl BootPageTable { )) }; } + // SAFETY: The pointer to the entry is valid to write. unsafe { pte_ptr.write(child_pte) }; pt = child_frame_pa; } @@ -248,12 +259,15 @@ impl BootPageTable { } // Do protection in the last level page table. let index = pte_index::(virt_addr, 1); + // SAFETY: The result pointer is within the PT frame. let pte_ptr = unsafe { (paddr_to_vaddr(pt) as *mut E).add(index) }; + // SAFETY: The pointer to the entry is valid to read. let pte = unsafe { pte_ptr.read() }; let PteScalar::Mapped(pa, mut prop) = pte.to_repr(1) else { panic!("protecting an unmapped page in the boot page table"); }; op(&mut prop); + // SAFETY: The pointer to the entry is valid to write. unsafe { pte_ptr.write(E::from_repr(&PteScalar::Mapped(pa, prop), 1)) }; } @@ -273,6 +287,7 @@ impl BootPageTable { // Zero it out. let vaddr = paddr_to_vaddr(frame_paddr) as *mut u8; + // SAFETY: The allocated frame is valid to write. unsafe { core::ptr::write_bytes(vaddr, 0, PAGE_SIZE) }; ( @@ -304,11 +319,17 @@ fn dfs_walk_on_leave( ) { if level >= 2 { let pt_vaddr = paddr_to_vaddr(pt) as *mut E; - let pt = unsafe { core::slice::from_raw_parts_mut(pt_vaddr, nr_subpage_per_huge::()) }; - for pte in pt { + for offset in 0..nr_subpage_per_huge::() { + // SAFETY: The result pointer is within the PT frame. + let pte_ptr = unsafe { pt_vaddr.add(offset) }; + // SAFETY: The pointer to the entry is valid to read. + let mut pte = unsafe { pte_ptr.read() }; + if let PteScalar::PageTable(child_pt, flags) = pte.to_repr(level) { dfs_walk_on_leave::(child_pt, level - 1, op); - op(pte, child_pt, level, flags); + op(&mut pte, child_pt, level, flags); + // SAFETY: The pointer to the entry is valid to write. + unsafe { pte_ptr.write(pte) }; } } }