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}