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