pub struct PageTable<T: TableMeta, A: FrameAllocator> { /* private fields */ }Implementations§
Source§impl<T: TableMeta, A: FrameAllocator> PageTable<T, A>
impl<T: TableMeta, A: FrameAllocator> PageTable<T, A>
pub const VALID_BITS: usize = Frame<T, A>::PT_VALID_BITS
Sourcepub fn new(allocator: A) -> PagingResult<Self>
pub fn new(allocator: A) -> PagingResult<Self>
创建一个新的页表
pub const fn root_paddr(&self) -> PhysAddr
Preallocates and retains the root directories covering range.
This is the page-table analogue of Linux preallocating the vmalloc directory levels before process roots copy the kernel half. A process root may subsequently borrow these entries once; all later mappings are published below the stable shared directories.
Callers must finish this operation before sharing the affected root entries or otherwise publishing this page table. Allocation failure may leave a prefix installed, but that private prefix remains owned by this page table and is reclaimed by its normal destructor.
Sourcepub unsafe fn detach(&mut self, release: impl FnMut(DetachedPageTableFrame<A>))
pub unsafe fn detach(&mut self, release: impl FnMut(DetachedPageTableFrame<A>))
Detaches every page-table frame owned by this table and transfers the
release capability to release. Mapped data frames are never touched.
§Safety
The caller must have stopped all page-table users and completed the
required local/remote TLB invalidations before reclaiming the returned
tokens. The table is unusable after this call; its Drop implementation
intentionally skips frame release to prevent a double free.
Sourcepub unsafe fn deallocate(&mut self)
pub unsafe fn deallocate(&mut self)
Releases all page-table frames and permanently invalidates this owning table. Calling it more than once is harmless; the detached bit makes the operation idempotent for teardown/recovery code.
§Safety
No CPU or walker may still use the table when this method is called.
Sourcepub unsafe fn destroy(self)
pub unsafe fn destroy(self)
Consumes the owning table after releasing its page-table frames. Mapped data frames are intentionally left to the mapping owner.
§Safety
The caller must establish the same quiescence requirements as
Self::deallocate.
Sourcepub fn leak(&mut self)
pub fn leak(&mut self)
Abandons the allocator capability for this table without attempting a fallible teardown.
This is intentionally an explicit leak used only when an owning
address-space destructor discovers that mappings or a TLB quarantine
are still live. Drop must not reclaim page-table frames in that
state: doing so could let a stale CPU walk a frame that has already
been reused. The caller must retain an out-of-band repair record if
those frames are to be reclaimed after the missing quiescence is fixed.
Sourcepub fn map_linear_pages(
&mut self,
start_vaddr: VirtAddr,
start_paddr: PhysAddr,
size: usize,
config: PteConfigOf<T>,
allow_huge: bool,
) -> PagingResult
pub fn map_linear_pages( &mut self, start_vaddr: VirtAddr, start_paddr: PhysAddr, size: usize, config: PteConfigOf<T>, allow_huge: bool, ) -> PagingResult
Convenience wrapper for a VA→PA mapping. The endpoint arithmetic is checked before any PTE is written. Contiguous ranges may use block descriptors; sparse/device ranges are represented by base-page leaves.
Sourcepub fn clone_missing_root_entries_from(
&mut self,
other: &PageTableRef<T, A>,
start_vaddr: VirtAddr,
size: usize,
) -> PagingResult
pub fn clone_missing_root_entries_from( &mut self, other: &PageTableRef<T, A>, start_vaddr: VirtAddr, size: usize, ) -> PagingResult
Deep-copies source root entries that are absent from this page table.
Leaf mappings keep referring to the same physical memory, while every copied intermediate page-table frame is independently owned by this page table. Existing destination root entries are left unchanged.
If allocation fails, entries copied before the failure remain installed and are reclaimed normally when this page table is dropped.
§Errors
Returns an error if the range overflows or wraps around the root table, or if an intermediate page-table frame cannot be allocated.
Methods from Deref<Target = PageTableRef<T, A>>§
Sourcepub fn map_page(
&mut self,
vaddr: VirtAddr,
paddr: PhysAddr,
page_size: usize,
config: PteConfigOf<T>,
) -> PagingResult
pub fn map_page( &mut self, vaddr: VirtAddr, paddr: PhysAddr, page_size: usize, config: PteConfigOf<T>, ) -> PagingResult
Maps one page with the requested page size.
Sourcepub fn map_region(
&mut self,
start_vaddr: VirtAddr,
get_paddr: impl Fn(VirtAddr) -> PhysAddr,
size: usize,
config: PteConfigOf<T>,
) -> PagingResult
pub fn map_region( &mut self, start_vaddr: VirtAddr, get_paddr: impl Fn(VirtAddr) -> PhysAddr, size: usize, config: PteConfigOf<T>, ) -> PagingResult
Maps a virtual region from a per-base-page physical resolver.
The resolver may return a non-contiguous physical page sequence, so this
API deliberately installs only base-page leaves. Use
[Self::map_linear_pages] when the physical range is known to be
contiguous and block mappings are allowed.
Mappings installed by this call are rolled back if a later page fails. TLB invalidation is deferred and batched until the region has been updated.
Sourcepub fn map_region_checked(
&mut self,
start_vaddr: VirtAddr,
get_paddr: impl FnMut(VirtAddr) -> PagingResult<PhysAddr>,
size: usize,
config: PteConfigOf<T>,
) -> PagingResult
pub fn map_region_checked( &mut self, start_vaddr: VirtAddr, get_paddr: impl FnMut(VirtAddr) -> PagingResult<PhysAddr>, size: usize, config: PteConfigOf<T>, ) -> PagingResult
Maps a virtual region using a fallible physical-address resolver.
The resolver is evaluated before each PTE write. If it rejects a later page, mappings already installed by this invocation are rolled back and the resolver error is returned. This is the capability used by allocation-backed or sparse device mappings: address resolution must remain checked all the way through the page-table walker. Because the resolver does not prove contiguity, this API uses base-page leaves.
Sourcepub fn unmap_page(
&mut self,
vaddr: VirtAddr,
) -> PagingResult<(PhysAddr, PteConfigOf<T>, usize)>
pub fn unmap_page( &mut self, vaddr: VirtAddr, ) -> PagingResult<(PhysAddr, PteConfigOf<T>, usize)>
Unmaps one page and returns its physical address, flags, and page size.
Sourcepub fn unmap_page_deferred(
&mut self,
vaddr: VirtAddr,
) -> PagingResult<(PhysAddr, PteConfigOf<T>, usize, DeferredPageTableFrames<A>)>
pub fn unmap_page_deferred( &mut self, vaddr: VirtAddr, ) -> PagingResult<(PhysAddr, PteConfigOf<T>, usize, DeferredPageTableFrames<A>)>
Unmaps one occupied leaf without reclaiming detached intermediate page-table frames.
The returned ownership token must be retained by the stage-1 TLB gather until every CPU that could use this page table confirms invalidation. This method performs no TLB invalidation itself.
Sourcepub fn peek_huge_block(
&self,
vaddr: VirtAddr,
) -> Option<(PhysAddr, PteConfigOf<T>, usize)>
pub fn peek_huge_block( &self, vaddr: VirtAddr, ) -> Option<(PhysAddr, PteConfigOf<T>, usize)>
Returns the huge block covering vaddr without changing the table.
Retained non-present blocks are reported when the PTE format preserves
their descriptor state.
Sourcepub fn plan_map_page(
&self,
vaddr: VirtAddr,
page_size: usize,
) -> PagingResult<PageTableMapPlan<T, A>>
pub fn plan_map_page( &self, vaddr: VirtAddr, page_size: usize, ) -> PagingResult<PageTableMapPlan<T, A>>
Captures the existing page-table prefix for one currently absent leaf.
This operation performs no allocation. The returned plan owns only an
allocator capability and copyable identity data, so a caller can drop
its page-table lock before PageTableMapPlan::prepare allocates the
missing suffix. Apply rewalks the prefix and rejects a stale plan.
Sourcepub fn try_map_page_with(
&mut self,
deposit: PageTableMapDeposit<T, A>,
) -> Result<(), PageTableMapApplyError<T, A>>
pub fn try_map_page_with( &mut self, deposit: PageTableMapDeposit<T, A>, ) -> Result<(), PageTableMapApplyError<T, A>>
Installs one fully prepared leaf without allocating or releasing memory.
On failure the move-only deposit is returned to the caller, which must drop it after leaving any non-sleeping page-table critical section. A successful apply publishes an already initialized suffix with one release-ordered parent store, then transfers every reserved frame to the live page-table tree.
Sourcepub fn try_install_map_path(
&mut self,
deposit: PageTablePathDeposit<T, A>,
) -> Result<(), PageTablePathApplyError<T, A>>
pub fn try_install_map_path( &mut self, deposit: PageTablePathDeposit<T, A>, ) -> Result<(), PageTablePathApplyError<T, A>>
Publishes a prepared, empty page-table suffix.
The operation only revalidates the captured prefix and performs one release-ordered parent-entry store. It never allocates, frees, or flushes; a failed apply returns the detached suffix to its caller.
Sourcepub fn plan_unmap_page(
&self,
vaddr: VirtAddr,
) -> PagingResult<PageTableLeafPlan<T>>
pub fn plan_unmap_page( &self, vaddr: VirtAddr, ) -> PagingResult<PageTableLeafPlan<T>>
Captures the exact occupied leaf covering vaddr without allocating.
Sourcepub fn plan_move_page(
&self,
source_vaddr: VirtAddr,
destination_vaddr: VirtAddr,
) -> PagingResult<PageTableMovePlan<T, A>>
pub fn plan_move_page( &self, source_vaddr: VirtAddr, destination_vaddr: VirtAddr, ) -> PagingResult<PageTableMovePlan<T, A>>
Captures one source leaf and the destination state for a later batch move. The destination hierarchy must already exist when it is vacant.
Sourcepub fn try_unmap_page_with(
&mut self,
plan: PageTableLeafPlan<T>,
) -> PagingResult<(PhysAddr, PteConfigOf<T>, usize)>where
PteConfigOf<T>: PartialEq,
pub fn try_unmap_page_with(
&mut self,
plan: PageTableLeafPlan<T>,
) -> PagingResult<(PhysAddr, PteConfigOf<T>, usize)>where
PteConfigOf<T>: PartialEq,
Clears one previously planned leaf without pruning directories or performing a TLB flush.
The caller retains ownership of the mapped data frame and must attach a later TLB obligation before releasing it. Empty page-table directories remain owned by this page table and can be reused by a subsequent fault.
Sourcepub fn try_move_pages_with(
&mut self,
plans: &[PageTableMovePlan<T, A>],
) -> PagingResult<usize>where
PteConfigOf<T>: PartialEq,
pub fn try_move_pages_with(
&mut self,
plans: &[PageTableMovePlan<T, A>],
) -> PagingResult<usize>where
PteConfigOf<T>: PartialEq,
Applies a sorted batch of page moves after validating every preimage.
No descriptor is changed until the whole slice passes validation. The
apply phase then consists only of PTE clears/stores: it cannot allocate,
free, flush, or fail. Source directories are intentionally retained,
matching Linux’s PTE move before free_pgtables() handles the detached
source VMA.
Sourcepub fn prepare_huge_split(
&self,
vaddr: VirtAddr,
) -> PagingResult<HugeSplitDeposit<T, A>>
pub fn prepare_huge_split( &self, vaddr: VirtAddr, ) -> PagingResult<HugeSplitDeposit<T, A>>
Allocates a pre-zeroed child table and binds it to the currently observed huge leaf.
The returned deposit may be stored by a mapping owner until a future partial operation needs to split the leaf. Apply revalidates the root, virtual range, physical frame, configuration, and size before touching any descriptor.
Sourcepub fn split_huge_page_with(
&mut self,
deposit: HugeSplitDeposit<T, A>,
) -> PagingResult<InstalledHugeSplit<T>>where
PteConfigOf<T>: PartialEq,
pub fn split_huge_page_with(
&mut self,
deposit: HugeSplitDeposit<T, A>,
) -> PagingResult<InstalledHugeSplit<T>>where
PteConfigOf<T>: PartialEq,
Consumes a bound deposit and splits its huge block into inherited finer leaves. No allocation occurs during apply.
Sourcepub fn try_split_huge_page_with(
&mut self,
deposit: HugeSplitDeposit<T, A>,
) -> Result<InstalledHugeSplit<T>, HugeSplitApplyError<T, A>>where
PteConfigOf<T>: PartialEq,
pub fn try_split_huge_page_with(
&mut self,
deposit: HugeSplitDeposit<T, A>,
) -> Result<InstalledHugeSplit<T>, HugeSplitApplyError<T, A>>where
PteConfigOf<T>: PartialEq,
Transactional variant of Self::split_huge_page_with. On failure the
caller receives the still-owned deposit and can put it back into its
mapping slot without allocating during recovery.
Sourcepub fn split_huge_block_to_empty_table(
&mut self,
deposit: HugeSplitDeposit<T, A>,
) -> PagingResult<InstalledHugeSplit<T>>where
PteConfigOf<T>: PartialEq,
pub fn split_huge_block_to_empty_table(
&mut self,
deposit: HugeSplitDeposit<T, A>,
) -> PagingResult<InstalledHugeSplit<T>>where
PteConfigOf<T>: PartialEq,
Splits a huge block and installs an empty child table for a caller that will materialize non-contiguous finer leaves under the same mutation domain. The old block metadata is returned for rollback/accounting.
Sourcepub fn restore_huge_split(
&mut self,
installed: InstalledHugeSplit<T>,
) -> PagingResult<HugeSplitDeposit<T, A>>
pub fn restore_huge_split( &mut self, installed: InstalledHugeSplit<T>, ) -> PagingResult<HugeSplitDeposit<T, A>>
Rolls an installed split back to the exact huge descriptor captured by its receipt and returns ownership of the withdrawn child table.
No allocation occurs. The returned deposit is bound to the restored
block and can either be retained for a retry or dropped to release the
now-unpublished page-table frame. This is the inverse of
Self::split_huge_page_with used by unpublished transaction aborts.
Sourcepub fn split_huge_page(&mut self, vaddr: VirtAddr) -> PagingResult<usize>where
PteConfigOf<T>: PartialEq,
pub fn split_huge_page(&mut self, vaddr: VirtAddr) -> PagingResult<usize>where
PteConfigOf<T>: PartialEq,
Prepares and performs an inherited huge split. Transactional callers
should retain HugeSplitDeposit from Self::prepare_huge_split
before entering their mutation critical section.
Sourcepub fn protect_page(
&mut self,
vaddr: VirtAddr,
config: PteConfigOf<T>,
) -> PagingResult<usize>
pub fn protect_page( &mut self, vaddr: VirtAddr, config: PteConfigOf<T>, ) -> PagingResult<usize>
Changes one existing mapping’s flags and returns its page size.
Sourcepub fn protect_region(
&mut self,
start_vaddr: VirtAddr,
size: usize,
config: PteConfigOf<T>,
) -> PagingResult
pub fn protect_region( &mut self, start_vaddr: VirtAddr, size: usize, config: PteConfigOf<T>, ) -> PagingResult
Changes flags for a region. Unmapped base pages are skipped.
Sourcepub fn remap_page(
&mut self,
vaddr: VirtAddr,
paddr: PhysAddr,
config: PteConfigOf<T>,
) -> PagingResult<usize>
pub fn remap_page( &mut self, vaddr: VirtAddr, paddr: PhysAddr, config: PteConfigOf<T>, ) -> PagingResult<usize>
Remaps one existing mapping and returns its page size.
Sourcepub fn query(
&self,
vaddr: VirtAddr,
) -> PagingResult<(PhysAddr, PteConfigOf<T>, usize)>
pub fn query( &self, vaddr: VirtAddr, ) -> PagingResult<(PhysAddr, PteConfigOf<T>, usize)>
Queries one mapping and returns the translated physical address, flags, and page size.
Sourcepub fn query_occupied(&self, vaddr: VirtAddr) -> PagingResult<(T::P, usize)>
pub fn query_occupied(&self, vaddr: VirtAddr) -> PagingResult<(T::P, usize)>
Queries one occupied leaf, including a non-present software mapping.
Unlike Self::query, this method distinguishes an unused entry from
a leaf whose descriptor is retained while address translation is
disabled. It is intended for ownership, rollback, and destructive
page-table operations. Callers must not use a successful result as
proof that the virtual address is currently accessible.
Sourcepub fn map(&mut self, config: &MapConfig<PteConfigOf<T>>) -> PagingResult
pub fn map(&mut self, config: &MapConfig<PteConfigOf<T>>) -> PagingResult
映射虚拟地址范围到物理地址范围
Sourcepub fn unmap_with_config(&mut self, config: &UnmapConfig) -> PagingResult<()>
pub fn unmap_with_config(&mut self, config: &UnmapConfig) -> PagingResult<()>
使用配置对象取消映射
Sourcepub fn walk_all(&self, config: WalkConfig) -> PageTableWalker<'_, T, A> ⓘ
pub fn walk_all(&self, config: WalkConfig) -> PageTableWalker<'_, T, A> ⓘ
创建页表遍历迭代器
pub fn walk( &self, start_vaddr: VirtAddr, end_vaddr: VirtAddr, ) -> impl Iterator<Item = PteInfo<T::P>> + '_
Sourcepub fn walk_valid(&self) -> impl Iterator<Item = PteInfo<T::P>> + '_
pub fn walk_valid(&self) -> impl Iterator<Item = PteInfo<T::P>> + '_
遍历所有有效的最终映射页表项(过滤掉无效项和中间级别的页表指针)
Sourcepub fn walk_occupied(&self) -> impl Iterator<Item = PteInfo<T::P>> + '_
pub fn walk_occupied(&self) -> impl Iterator<Item = PteInfo<T::P>> + '_
Walks every occupied final leaf, including retained non-present leaves.
Rollback and quarantine code must distinguish an empty page-table slot from a descriptor that still owns a physical mapping but has had its access permissions removed. The walk scales with allocated page-table frames rather than with the represented virtual address span.
Sourcepub fn walk_occupied_range(
&self,
start_vaddr: VirtAddr,
end_vaddr: VirtAddr,
) -> impl Iterator<Item = PteInfo<T::P>> + '_
pub fn walk_occupied_range( &self, start_vaddr: VirtAddr, end_vaddr: VirtAddr, ) -> impl Iterator<Item = PteInfo<T::P>> + '_
Walks occupied final leaves whose represented range overlaps
[start_vaddr, end_vaddr).
Unlike probing every base page, this follows only allocated page-table paths that intersect the requested range. Retained non-present leaves remain visible so rollback can keep PTE and software ownership in sync.
Sourcepub fn mapping_size_for_level(&self, level: usize) -> Option<usize>
pub fn mapping_size_for_level(&self, level: usize) -> Option<usize>
Returns the mapping size represented by one page-table level.
Sourcepub fn translate_with_level(
&self,
vaddr: VirtAddr,
) -> PagingResult<(PhysAddr, T::P, usize)>
pub fn translate_with_level( &self, vaddr: VirtAddr, ) -> PagingResult<(PhysAddr, T::P, usize)>
Translates a virtual address and returns the matched PTE level.
Sourcepub fn translate_phys(&self, vaddr: VirtAddr) -> PagingResult<PhysAddr>
pub fn translate_phys(&self, vaddr: VirtAddr) -> PagingResult<PhysAddr>
Sourcepub fn root_paddr(&self) -> PhysAddr
pub fn root_paddr(&self) -> PhysAddr
获取页表的根帧物理地址