Skip to content

Commit 817a88f

Browse files
committed
Add more extensive docs on safety to map_to
1 parent 88547ef commit 817a88f

File tree

1 file changed

+30
-4
lines changed
  • src/structures/paging/mapper

1 file changed

+30
-4
lines changed

src/structures/paging/mapper/mod.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,34 @@ pub trait Mapper<S: PageSize> {
8383
/// This function might need additional physical frames to create new page tables. These
8484
/// frames are allocated from the `allocator` argument. At most three frames are required.
8585
///
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.
88114
unsafe fn map_to<A>(
89115
&mut self,
90116
page: Page<S>,
@@ -118,8 +144,8 @@ pub trait Mapper<S: PageSize> {
118144
///
119145
/// ## Safety
120146
///
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.
123149
#[inline]
124150
unsafe fn identity_map<A>(
125151
&mut self,

0 commit comments

Comments
 (0)