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}