Skip to main content

ax_memory_set/
backend.rs

1use ax_memory_addr::MemoryAddr;
2
3/// Underlying operations to do when manipulating mappings within the specific
4/// [`MemoryArea`](crate::MemoryArea).
5///
6/// The backend can be different for different memory areas. e.g., for linear
7/// mappings, the target physical address is known when it is added to the page
8/// table. For lazy mappings, an empty mapping needs to be added to the page
9/// table to trigger a page fault.
10pub trait MappingBackend: Clone {
11    /// The address type used in the memory area.
12    type Addr: MemoryAddr;
13    /// The flags type used in the memory area.
14    type Flags: Copy;
15    /// Per-mutation state that must be shared by all page-table operations in
16    /// one logical mapping transaction.
17    type MutationContext;
18    /// The page table type used in the memory area.
19    type PageTable;
20
21    /// What to do when mapping a region within the area with the given flags.
22    fn map(
23        &self,
24        start: Self::Addr,
25        size: usize,
26        flags: Self::Flags,
27        context: &mut Self::MutationContext,
28        page_table: &mut Self::PageTable,
29    ) -> bool;
30
31    /// Read-only validation for a mapping operation.  Backends that can
32    /// inspect conflicts or allocation requirements should override this
33    /// hook.  `MemorySet` invokes it before an overlapping `MAP_FIXED`
34    /// operation removes the old mapping, so a rejected request has no
35    /// externally visible side effect.
36    fn validate_map(
37        &self,
38        _start: Self::Addr,
39        _size: usize,
40        _flags: Self::Flags,
41        _page_table: &Self::PageTable,
42    ) -> bool {
43        true
44    }
45
46    /// What to do when unmaping a memory region within the area.
47    fn unmap(
48        &self,
49        start: Self::Addr,
50        size: usize,
51        context: &mut Self::MutationContext,
52        page_table: &mut Self::PageTable,
53    ) -> bool;
54
55    /// Preflights mapping shape and resource ownership for [`Self::unmap`].
56    ///
57    /// The page table is not mutated between this preflight and commit. A
58    /// backend that can predict rejection from mapping shape or owned
59    /// resources must override this method. The commit can still fail because
60    /// of concurrent external state or resource pressure; in that case earlier
61    /// disjoint subranges may already be unmapped, while `MemorySet` retains
62    /// all area metadata and backend owners so the caller can quarantine and
63    /// retry the published mutation.
64    fn validate_unmap(
65        &self,
66        _start: Self::Addr,
67        _size: usize,
68        _page_table: &Self::PageTable,
69    ) -> bool {
70        true
71    }
72
73    /// Validate a protection update before applying it.  This mirrors
74    /// [`Self::validate_unmap`] and is optional for legacy backends.
75    fn validate_protect(
76        &self,
77        _start: Self::Addr,
78        _size: usize,
79        _new_flags: Self::Flags,
80        _page_table: &Self::PageTable,
81    ) -> bool {
82        true
83    }
84
85    /// What to do when changing access flags.
86    fn protect(
87        &self,
88        start: Self::Addr,
89        size: usize,
90        new_flags: Self::Flags,
91        context: &mut Self::MutationContext,
92        page_table: &mut Self::PageTable,
93    ) -> bool;
94
95    /// Splits the backend into two backends at the given alignment difference.
96    fn split(&mut self, align_diff: usize) -> Option<Self>;
97
98    /// Shrinks the backend from the left by the given size.
99    ///
100    /// The backend start address is increased by `shrink_size`.
101    fn shrink_left(&mut self, _shrink_size: usize) -> bool {
102        true
103    }
104
105    /// Shrinks the backend from the right by the given size.
106    ///
107    /// The backend end address is decreased by `shrink_size`.
108    fn shrink_right(&mut self, _shrink_size: usize) -> bool {
109        true
110    }
111}