Skip to content

Commit 8b15f7d

Browse files
ziqiaozhouCopilot
andcommitted
paging: add parent flag mapping helpers
Thread parent page-table flags through allocation and add map_2m_with_parent_flags and map_4k_with_parent_flags. The existing map_2m and map_4k APIs remain as default-parent-flag wrappers, making caller-selectable parent entry attributes a focused reviewable change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Ziqiao Zhou <ziqiaozhou@microsoft.com>
1 parent d82a547 commit 8b15f7d

1 file changed

Lines changed: 91 additions & 19 deletions

File tree

paging/src/pagetable.rs

Lines changed: 91 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,12 @@ impl<A: ArchPagingMeta, P: PagingHandler + SelfMap> GenericPageTable<A, P, Pagin
514514

515515
impl<A: ArchPagingMeta, P: PagingHandler, L: PagingLevel> GenericPageTable<A, P, L> {
516516
/// Allocate from level 3 (PML4E) down to the target level.
517-
fn alloc_pte_lvl3(entry: &mut PTEntry<A>, vaddr: VirtAddr, size: PageSize) -> Mapping<'_, A> {
517+
fn alloc_pte_lvl3(
518+
entry: &mut PTEntry<A>,
519+
vaddr: VirtAddr,
520+
size: PageSize,
521+
parent_flags: A::PTFlags,
522+
) -> Mapping<'_, A> {
518523
if entry.flags().contains(A::PTFlags::PRESENT) {
519524
return Mapping::new(PageLevel::Level3, entry);
520525
}
@@ -523,14 +528,19 @@ impl<A: ArchPagingMeta, P: PagingHandler, L: PagingLevel> GenericPageTable<A, P,
523528
return Mapping::new(PageLevel::Level3, entry);
524529
};
525530

526-
entry.set(A::make_private_address(paddr), A::PTFlags::parent_flags());
531+
entry.set(A::make_private_address(paddr), parent_flags);
527532

528533
let idx = vaddr.to_pgtbl_idx::<2>();
529-
Self::alloc_pte_lvl2(&mut page[idx], vaddr, size)
534+
Self::alloc_pte_lvl2(&mut page[idx], vaddr, size, parent_flags)
530535
}
531536

532537
/// Allocate from level 2 (PDPTE) down to the target level.
533-
fn alloc_pte_lvl2(entry: &mut PTEntry<A>, vaddr: VirtAddr, size: PageSize) -> Mapping<'_, A> {
538+
fn alloc_pte_lvl2(
539+
entry: &mut PTEntry<A>,
540+
vaddr: VirtAddr,
541+
size: PageSize,
542+
parent_flags: A::PTFlags,
543+
) -> Mapping<'_, A> {
534544
if entry.flags().contains(A::PTFlags::PRESENT) {
535545
return Mapping::new(PageLevel::Level2, entry);
536546
}
@@ -539,15 +549,20 @@ impl<A: ArchPagingMeta, P: PagingHandler, L: PagingLevel> GenericPageTable<A, P,
539549
return Mapping::new(PageLevel::Level2, entry);
540550
};
541551

542-
entry.set(A::make_private_address(paddr), A::PTFlags::parent_flags());
552+
entry.set(A::make_private_address(paddr), parent_flags);
543553

544554
let idx = vaddr.to_pgtbl_idx::<1>();
545-
Self::alloc_pte_lvl1(&mut page[idx], vaddr, size)
555+
Self::alloc_pte_lvl1(&mut page[idx], vaddr, size, parent_flags)
546556
}
547557

548558
/// Allocate from level 1 (PDE) down to level 0.
549559
/// Returns at level 1 if `size` is `Huge` (2 MiB page).
550-
fn alloc_pte_lvl1(entry: &mut PTEntry<A>, vaddr: VirtAddr, size: PageSize) -> Mapping<'_, A> {
560+
fn alloc_pte_lvl1(
561+
entry: &mut PTEntry<A>,
562+
vaddr: VirtAddr,
563+
size: PageSize,
564+
parent_flags: A::PTFlags,
565+
) -> Mapping<'_, A> {
551566
let flags = entry.flags();
552567
if size == PageSize::Huge || flags.contains(A::PTFlags::PRESENT) {
553568
return Mapping::new(PageLevel::Level1, entry);
@@ -557,7 +572,7 @@ impl<A: ArchPagingMeta, P: PagingHandler, L: PagingLevel> GenericPageTable<A, P,
557572
return Mapping::new(PageLevel::Level1, entry);
558573
};
559574

560-
entry.set(A::make_private_address(paddr), A::PTFlags::parent_flags());
575+
entry.set(A::make_private_address(paddr), parent_flags);
561576

562577
let idx = vaddr.to_pgtbl_idx::<0>();
563578
Mapping::new(PageLevel::Level0, &mut page[idx])
@@ -567,30 +582,40 @@ impl<A: ArchPagingMeta, P: PagingHandler, L: PagingLevel> GenericPageTable<A, P,
567582
///
568583
/// # Parameters
569584
/// - `vaddr`: The virtual address for which to allocate the PTE.
585+
/// - `parent_flags`: The flags to apply to the allocated page table entries.
586+
///
570587
/// # Returns
571588
/// A `Mapping` representing the allocated or existing PTE for the address.
572-
fn alloc_pte_4k(&mut self, vaddr: VirtAddr) -> Mapping<'_, A> {
589+
fn alloc_pte_4k(&mut self, vaddr: VirtAddr, parent_flags: A::PTFlags) -> Mapping<'_, A> {
573590
let m = self.walk_addr(vaddr);
574591
match m.level {
575592
PageLevel::Level0 => m,
576-
PageLevel::Level1 => Self::alloc_pte_lvl1(m.entry, vaddr, PageSize::Regular),
577-
PageLevel::Level2 => Self::alloc_pte_lvl2(m.entry, vaddr, PageSize::Regular),
578-
PageLevel::Level3 => Self::alloc_pte_lvl3(m.entry, vaddr, PageSize::Regular),
593+
PageLevel::Level1 => {
594+
Self::alloc_pte_lvl1(m.entry, vaddr, PageSize::Regular, parent_flags)
595+
}
596+
PageLevel::Level2 => {
597+
Self::alloc_pte_lvl2(m.entry, vaddr, PageSize::Regular, parent_flags)
598+
}
599+
PageLevel::Level3 => {
600+
Self::alloc_pte_lvl3(m.entry, vaddr, PageSize::Regular, parent_flags)
601+
}
579602
}
580603
}
581604

582605
/// Allocates a 2MB page table entry for a given virtual address.
583606
///
584607
/// # Parameters
585608
/// - `vaddr`: The virtual address for which to allocate the PTE.
609+
/// - `parent_flags`: The flags to apply to the allocated page table entries.
610+
///
586611
/// # Returns
587612
/// A `Mapping` representing the allocated or existing PTE for the address.
588-
fn alloc_pte_2m(&mut self, vaddr: VirtAddr) -> Mapping<'_, A> {
613+
fn alloc_pte_2m(&mut self, vaddr: VirtAddr, parent_flags: A::PTFlags) -> Mapping<'_, A> {
589614
let m = self.walk_addr(vaddr);
590615
match m.level {
591616
PageLevel::Level0 | PageLevel::Level1 => m,
592-
PageLevel::Level2 => Self::alloc_pte_lvl2(m.entry, vaddr, PageSize::Huge),
593-
PageLevel::Level3 => Self::alloc_pte_lvl3(m.entry, vaddr, PageSize::Huge),
617+
PageLevel::Level2 => Self::alloc_pte_lvl2(m.entry, vaddr, PageSize::Huge, parent_flags),
618+
PageLevel::Level3 => Self::alloc_pte_lvl3(m.entry, vaddr, PageSize::Huge, parent_flags),
594619
}
595620
}
596621

@@ -716,16 +741,17 @@ impl<A: ArchPagingMeta, P: PagingHandler, L: PagingLevel> GenericPageTable<A, P,
716741
///
717742
/// # Panics
718743
/// Panics if either `vaddr` or `paddr` is not aligned to a 2MB boundary.
719-
pub fn map_2m(
744+
pub fn map_2m_with_parent_flags(
720745
&mut self,
721746
vaddr: VirtAddr,
722747
paddr: PhysAddr,
723748
flags: A::PTFlags,
724749
shared: bool,
750+
parent_flags: A::PTFlags,
725751
) -> Result<(), PagingError> {
726752
assert!(vaddr.is_aligned(PAGE_SIZE_2M));
727753
assert!(paddr.is_aligned(PAGE_SIZE_2M));
728-
let mapping = self.alloc_pte_2m(vaddr);
754+
let mapping = self.alloc_pte_2m(vaddr, parent_flags);
729755
let addr = if !shared {
730756
A::make_private_address(paddr)
731757
} else {
@@ -744,6 +770,29 @@ impl<A: ArchPagingMeta, P: PagingHandler, L: PagingLevel> GenericPageTable<A, P,
744770
}
745771
}
746772

773+
/// Maps a 2MB page.
774+
///
775+
/// # Parameters
776+
/// - `vaddr`: The virtual address to map.
777+
/// - `paddr`: The physical address to map to.
778+
/// - `flags`: The flags to apply to the mapping.
779+
/// - `shared`: Indicates whether the mapping is shared.
780+
///
781+
/// # Returns
782+
/// A result indicating success or failure ([`PagingError`]).
783+
///
784+
/// # Panics
785+
/// Panics if either `vaddr` or `paddr` is not aligned to a 2MB boundary.
786+
pub fn map_2m(
787+
&mut self,
788+
vaddr: VirtAddr,
789+
paddr: PhysAddr,
790+
flags: A::PTFlags,
791+
shared: bool,
792+
) -> Result<(), PagingError> {
793+
self.map_2m_with_parent_flags(vaddr, paddr, flags, shared, A::PTFlags::parent_flags())
794+
}
795+
747796
/// Unmaps a 2MB page.
748797
///
749798
/// # Parameters
@@ -777,16 +826,19 @@ impl<A: ArchPagingMeta, P: PagingHandler, L: PagingLevel> GenericPageTable<A, P,
777826
/// - `paddr`: The physical address to map to.
778827
/// - `flags`: The flags to apply to the mapping.
779828
/// - `shared`: Indicates whether the mapping is shared.
829+
/// - `parent_flags`: The flags to apply to the allocated parent page table entries.
830+
///
780831
/// # Returns
781832
/// A result indicating success or failure ([`PagingError`]).
782-
pub fn map_4k(
833+
pub fn map_4k_with_parent_flags(
783834
&mut self,
784835
vaddr: VirtAddr,
785836
paddr: PhysAddr,
786837
flags: A::PTFlags,
787838
shared: bool,
839+
parent_flags: A::PTFlags,
788840
) -> Result<(), PagingError> {
789-
let mapping = self.alloc_pte_4k(vaddr);
841+
let mapping = self.alloc_pte_4k(vaddr, parent_flags);
790842
let addr = if !shared {
791843
A::make_private_address(paddr)
792844
} else {
@@ -805,6 +857,26 @@ impl<A: ArchPagingMeta, P: PagingHandler, L: PagingLevel> GenericPageTable<A, P,
805857
}
806858
}
807859

860+
/// Maps a 4KB page.
861+
///
862+
/// # Parameters
863+
/// - `vaddr`: The virtual address to map.
864+
/// - `paddr`: The physical address to map to.
865+
/// - `flags`: The flags to apply to the mapping.
866+
/// - `shared`: Indicates whether the mapping is shared.
867+
///
868+
/// # Returns
869+
/// A result indicating success or failure ([`PagingError`]).
870+
pub fn map_4k(
871+
&mut self,
872+
vaddr: VirtAddr,
873+
paddr: PhysAddr,
874+
flags: A::PTFlags,
875+
shared: bool,
876+
) -> Result<(), PagingError> {
877+
self.map_4k_with_parent_flags(vaddr, paddr, flags, shared, A::PTFlags::parent_flags())
878+
}
879+
808880
/// Unmaps a 4KB page.
809881
///
810882
/// # Parameters

0 commit comments

Comments
 (0)