@@ -83,8 +83,34 @@ pub trait Mapper<S: PageSize> {
83
83
/// This function might need additional physical frames to create new page tables. These
84
84
/// frames are allocated from the `allocator` argument. At most three frames are required.
85
85
///
86
- /// This function is unsafe because the caller must guarantee that passed `frame` is
87
- /// unused, i.e. not used for any other mappings.
86
+ /// ## Safety
87
+ ///
88
+ /// Creating page table mappings is a fundamentally unsafe operation because
89
+ /// there are various ways to break memory safety through it. For example,
90
+ /// re-mapping an in-use page to a different frame changes and invalidates
91
+ /// all values stored in that page, resulting in undefined behavior on the
92
+ /// next use.
93
+ ///
94
+ /// The caller must ensure that no undefined behavior or memory safety
95
+ /// violations can occur through the new mapping. Among other things, the
96
+ /// caller must prevent the following:
97
+ ///
98
+ /// - Aliasing of `&mut` references, i.e. two `&mut` references that point to
99
+ /// the same physical address. This is undefined behavior in Rust.
100
+ /// - This can be ensured by mapping each page to an individual physical
101
+ /// frame that is not mapped anywhere else.
102
+ /// - Creating uninitalized or invalid values: Rust requires that all values
103
+ /// have a correct memory layout. For example, a `bool` must be either a 0
104
+ /// or a 1 in memory, but not a 3 or 4. An exception is the `MaybeUninit`
105
+ /// wrapper type, which abstracts over possibly uninitialized memory.
106
+ /// - This is only a problem when re-mapping pages to different physical
107
+ /// frames. Mapping a page that is not in use yet is fine.
108
+ ///
109
+ /// Special care must be taken when sharing pages with other address spaces,
110
+ /// e.g. by setting the `GLOBAL` flag. For example, a global mapping must be
111
+ /// the same in all address spaces, otherwise undefined behavior can occur
112
+ /// because of TLB races. It's worth noting that all the above requirements
113
+ /// also apply to shared mappings, including the aliasing requirements.
88
114
unsafe fn map_to < A > (
89
115
& mut self ,
90
116
page : Page < S > ,
@@ -118,8 +144,8 @@ pub trait Mapper<S: PageSize> {
118
144
///
119
145
/// ## Safety
120
146
///
121
- /// This function is unsafe because the caller must guarantee that the passed `frame` is
122
- /// unused, i.e. not used for any other mappings .
147
+ /// This is a convencience function that invokes [`map_to`] internally, so
148
+ /// all safety requirements of it also apply for this function .
123
149
#[ inline]
124
150
unsafe fn identity_map < A > (
125
151
& mut self ,
0 commit comments