Skip to main content

ostd/mm/
mod.rs

1// SPDX-License-Identifier: MPL-2.0
2
3//! Virtual memory (VM).
4
5#![cfg_attr(
6    any(
7        target_arch = "riscv64",
8        target_arch = "loongarch64",
9        target_arch = "aarch64"
10    ),
11    expect(unused_imports)
12)]
13
14pub mod dma;
15pub mod fault;
16pub mod frame;
17pub mod heap;
18pub mod io;
19pub(crate) mod kspace;
20pub(crate) mod mem_obj;
21pub(crate) mod page_prop;
22pub(crate) mod page_table;
23pub mod tlb;
24pub mod vm_space;
25
26#[cfg(ktest)]
27mod test;
28
29use core::fmt::Debug;
30
31pub use self::{
32    frame::{
33        Frame,
34        allocator::FrameAllocOptions,
35        segment::{Segment, USegment},
36        unique::UniqueFrame,
37        untyped::{AnyUFrameMeta, UFrame},
38    },
39    io::{
40        Fallible, FallibleVmRead, FallibleVmWrite, Infallible, PodAtomic, PodOnce, VmIo, VmIoFill,
41        VmIoOnce, VmReader, VmWriter,
42    },
43    kspace::{KERNEL_VADDR_RANGE, MAX_USERSPACE_VADDR},
44    mem_obj::{HasDaddr, HasPaddr, HasPaddrRange, HasSize, Split},
45    page_prop::{CachePolicy, PageFlags, PageProperty},
46    vm_space::VmSpace,
47};
48pub(crate) use self::{
49    kspace::paddr_to_vaddr,
50    page_prop::{PageTableFlags, PrivilegedPageFlags},
51    page_table::PageTable,
52};
53use crate::arch::mm::PagingConsts;
54
55/// Virtual addresses.
56pub type Vaddr = usize;
57
58/// Physical addresses.
59pub type Paddr = usize;
60
61/// Device addresses.
62pub type Daddr = usize;
63
64/// Returns whether `vaddr` and `len` specify a user-space virtual address range.
65pub fn is_in_user_space(vaddr: Vaddr, len: usize) -> bool {
66    vaddr.saturating_add(len) <= MAX_USERSPACE_VADDR
67}
68
69/// The level of a page table node or a frame.
70pub type PagingLevel = u8;
71
72/// A minimal set of constants that determines the paging system.
73/// This provides an abstraction over most paging modes in common architectures.
74pub(crate) trait PagingConstsTrait: Clone + Debug + Send + Sync + 'static {
75    /// The smallest page size.
76    /// This is also the page size at level 1 page tables.
77    const BASE_PAGE_SIZE: usize;
78
79    /// The number of levels in the page table.
80    /// The numbering of levels goes from deepest node to the root node. For example,
81    /// the level 1 to 5 on AMD64 corresponds to Page Tables, Page Directory Tables,
82    /// Page Directory Pointer Tables, Page-Map Level-4 Table, and Page-Map Level-5
83    /// Table, respectively.
84    const NR_LEVELS: PagingLevel;
85
86    /// The highest level that a PTE can be directly used to translate a VA.
87    /// This affects the the largest page size supported by the page table.
88    const HIGHEST_TRANSLATION_LEVEL: PagingLevel;
89
90    /// The size of a PTE.
91    const PTE_SIZE: usize;
92
93    /// The address width may be BASE_PAGE_SIZE.ilog2() + NR_LEVELS * IN_FRAME_INDEX_BITS.
94    /// If it is shorter than that, the higher bits in the highest level are ignored.
95    const ADDRESS_WIDTH: usize;
96
97    /// Whether virtual addresses are sign-extended.
98    ///
99    /// The sign bit of a [`Vaddr`] is the bit at index [`PagingConstsTrait::ADDRESS_WIDTH`] - 1.
100    /// If this constant is `true`, bits in [`Vaddr`] that are higher than the sign bit must be
101    /// equal to the sign bit. If an address violates this rule, both the hardware and OSTD
102    /// should reject it.
103    ///
104    /// Otherwise, if this constant is `false`, higher bits must be zero.
105    ///
106    /// Regardless of sign extension, [`Vaddr`] is always not signed upon calculation.
107    /// That means, `0xffff_ffff_ffff_0000 < 0xffff_ffff_ffff_0001` is `true`.
108    const VA_SIGN_EXT: bool;
109}
110
111/// The page size
112pub const PAGE_SIZE: usize = page_size::<PagingConsts>(1);
113
114/// The page size at a given level.
115pub(crate) const fn page_size<C: PagingConstsTrait>(level: PagingLevel) -> usize {
116    C::BASE_PAGE_SIZE << (nr_subpage_per_huge::<C>().ilog2() as usize * (level as usize - 1))
117}
118
119/// The number of sub pages in a huge page.
120pub(crate) const fn nr_subpage_per_huge<C: PagingConstsTrait>() -> usize {
121    C::BASE_PAGE_SIZE / C::PTE_SIZE
122}
123
124/// The number of base pages in a huge page at a given level.
125#[expect(dead_code)]
126pub(crate) const fn nr_base_per_page<C: PagingConstsTrait>(level: PagingLevel) -> usize {
127    page_size::<C>(level) / C::BASE_PAGE_SIZE
128}