xref: /linux/rust/kernel/mm.rs (revision 9907e1df31c0f4bdcebe16de809121baa754e5b5)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 // Copyright (C) 2024 Google LLC.
4 
5 //! Memory management.
6 //!
7 //! This module deals with managing the address space of userspace processes. Each process has an
8 //! instance of [`Mm`], which keeps track of multiple VMAs (virtual memory areas). Each VMA
9 //! corresponds to a region of memory that the userspace process can access, and the VMA lets you
10 //! control what happens when userspace reads or writes to that region of memory.
11 //!
12 //! C header: [`include/linux/mm.h`](srctree/include/linux/mm.h)
13 
14 use crate::{
15     bindings,
16     sync::aref::{ARef, AlwaysRefCounted},
17     types::{NotThreadSafe, Opaque},
18 };
19 use core::{ops::Deref, ptr::NonNull};
20 
21 pub mod virt;
22 use virt::VmaRef;
23 
24 #[cfg(CONFIG_MMU)]
25 pub use mmput_async::MmWithUserAsync;
26 mod mmput_async;
27 
28 /// A wrapper for the kernel's `struct mm_struct`.
29 ///
30 /// This represents the address space of a userspace process, so each process has one `Mm`
31 /// instance. It may hold many VMAs internally.
32 ///
33 /// There is a counter called `mm_users` that counts the users of the address space; this includes
34 /// the userspace process itself, but can also include kernel threads accessing the address space.
35 /// Once `mm_users` reaches zero, this indicates that the address space can be destroyed. To access
36 /// the address space, you must prevent `mm_users` from reaching zero while you are accessing it.
37 /// The [`MmWithUser`] type represents an address space where this is guaranteed, and you can
38 /// create one using [`mmget_not_zero`].
39 ///
40 /// The `ARef<Mm>` smart pointer holds an `mmgrab` refcount. Its destructor may sleep.
41 ///
42 /// # Invariants
43 ///
44 /// Values of this type are always refcounted using `mmgrab`.
45 ///
46 /// [`mmget_not_zero`]: Mm::mmget_not_zero
47 #[repr(transparent)]
48 pub struct Mm {
49     mm: Opaque<bindings::mm_struct>,
50 }
51 
52 // SAFETY: It is safe to call `mmdrop` on another thread than where `mmgrab` was called.
53 unsafe impl Send for Mm {}
54 // SAFETY: All methods on `Mm` can be called in parallel from several threads.
55 unsafe impl Sync for Mm {}
56 
57 // SAFETY: By the type invariants, this type is always refcounted.
58 unsafe impl AlwaysRefCounted for Mm {
59     #[inline]
60     fn inc_ref(&self) {
61         // SAFETY: The pointer is valid since self is a reference.
62         unsafe { bindings::mmgrab(self.as_raw()) };
63     }
64 
65     #[inline]
66     unsafe fn dec_ref(obj: NonNull<Self>) {
67         // SAFETY: The caller is giving up their refcount.
68         unsafe { bindings::mmdrop(obj.cast().as_ptr()) };
69     }
70 }
71 
72 /// A wrapper for the kernel's `struct mm_struct`.
73 ///
74 /// This type is like [`Mm`], but with non-zero `mm_users`. It can only be used when `mm_users` can
75 /// be proven to be non-zero at compile-time, usually because the relevant code holds an `mmget`
76 /// refcount. It can be used to access the associated address space.
77 ///
78 /// The `ARef<MmWithUser>` smart pointer holds an `mmget` refcount. Its destructor may sleep.
79 ///
80 /// # Invariants
81 ///
82 /// Values of this type are always refcounted using `mmget`. The value of `mm_users` is non-zero.
83 #[repr(transparent)]
84 pub struct MmWithUser {
85     mm: Mm,
86 }
87 
88 // SAFETY: It is safe to call `mmput` on another thread than where `mmget` was called.
89 unsafe impl Send for MmWithUser {}
90 // SAFETY: All methods on `MmWithUser` can be called in parallel from several threads.
91 unsafe impl Sync for MmWithUser {}
92 
93 // SAFETY: By the type invariants, this type is always refcounted.
94 unsafe impl AlwaysRefCounted for MmWithUser {
95     #[inline]
96     fn inc_ref(&self) {
97         // SAFETY: The pointer is valid since self is a reference.
98         unsafe { bindings::mmget(self.as_raw()) };
99     }
100 
101     #[inline]
102     unsafe fn dec_ref(obj: NonNull<Self>) {
103         // SAFETY: The caller is giving up their refcount.
104         unsafe { bindings::mmput(obj.cast().as_ptr()) };
105     }
106 }
107 
108 // Make all `Mm` methods available on `MmWithUser`.
109 impl Deref for MmWithUser {
110     type Target = Mm;
111 
112     #[inline]
113     fn deref(&self) -> &Mm {
114         &self.mm
115     }
116 }
117 
118 // These methods are safe to call even if `mm_users` is zero.
119 impl Mm {
120     /// Returns a raw pointer to the inner `mm_struct`.
121     #[inline]
122     pub fn as_raw(&self) -> *mut bindings::mm_struct {
123         self.mm.get()
124     }
125 
126     /// Obtain a reference from a raw pointer.
127     ///
128     /// # Safety
129     ///
130     /// The caller must ensure that `ptr` points at an `mm_struct`, and that it is not deallocated
131     /// during the lifetime 'a.
132     #[inline]
133     pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_struct) -> &'a Mm {
134         // SAFETY: Caller promises that the pointer is valid for 'a. Layouts are compatible due to
135         // repr(transparent).
136         unsafe { &*ptr.cast() }
137     }
138 
139     /// Calls `mmget_not_zero` and returns a handle if it succeeds.
140     #[inline]
141     pub fn mmget_not_zero(&self) -> Option<ARef<MmWithUser>> {
142         // SAFETY: The pointer is valid since self is a reference.
143         let success = unsafe { bindings::mmget_not_zero(self.as_raw()) };
144 
145         if success {
146             // SAFETY: We just created an `mmget` refcount.
147             Some(unsafe { ARef::from_raw(NonNull::new_unchecked(self.as_raw().cast())) })
148         } else {
149             None
150         }
151     }
152 }
153 
154 // These methods require `mm_users` to be non-zero.
155 impl MmWithUser {
156     /// Obtain a reference from a raw pointer.
157     ///
158     /// # Safety
159     ///
160     /// The caller must ensure that `ptr` points at an `mm_struct`, and that `mm_users` remains
161     /// non-zero for the duration of the lifetime 'a.
162     #[inline]
163     pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_struct) -> &'a MmWithUser {
164         // SAFETY: Caller promises that the pointer is valid for 'a. The layout is compatible due
165         // to repr(transparent).
166         unsafe { &*ptr.cast() }
167     }
168 
169     /// Attempt to access a vma using the vma read lock.
170     ///
171     /// This is an optimistic trylock operation, so it may fail if there is contention. In that
172     /// case, you should fall back to taking the mmap read lock.
173     ///
174     /// When per-vma locks are disabled, this always returns `None`.
175     #[inline]
176     pub fn lock_vma_under_rcu(&self, vma_addr: usize) -> Option<VmaReadGuard<'_>> {
177         #[cfg(CONFIG_PER_VMA_LOCK)]
178         {
179             // SAFETY: Calling `bindings::lock_vma_under_rcu` is always okay given an mm where
180             // `mm_users` is non-zero.
181             let vma = unsafe { bindings::lock_vma_under_rcu(self.as_raw(), vma_addr) };
182             if !vma.is_null() {
183                 return Some(VmaReadGuard {
184                     // SAFETY: If `lock_vma_under_rcu` returns a non-null ptr, then it points at a
185                     // valid vma. The vma is stable for as long as the vma read lock is held.
186                     vma: unsafe { VmaRef::from_raw(vma) },
187                     _nts: NotThreadSafe,
188                 });
189             }
190         }
191 
192         // Silence warnings about unused variables.
193         #[cfg(not(CONFIG_PER_VMA_LOCK))]
194         let _ = vma_addr;
195 
196         None
197     }
198 
199     /// Lock the mmap read lock.
200     #[inline]
201     pub fn mmap_read_lock(&self) -> MmapReadGuard<'_> {
202         // SAFETY: The pointer is valid since self is a reference.
203         unsafe { bindings::mmap_read_lock(self.as_raw()) };
204 
205         // INVARIANT: We just acquired the read lock.
206         MmapReadGuard {
207             mm: self,
208             _nts: NotThreadSafe,
209         }
210     }
211 
212     /// Try to lock the mmap read lock.
213     #[inline]
214     pub fn mmap_read_trylock(&self) -> Option<MmapReadGuard<'_>> {
215         // SAFETY: The pointer is valid since self is a reference.
216         let success = unsafe { bindings::mmap_read_trylock(self.as_raw()) };
217 
218         if success {
219             // INVARIANT: We just acquired the read lock.
220             Some(MmapReadGuard {
221                 mm: self,
222                 _nts: NotThreadSafe,
223             })
224         } else {
225             None
226         }
227     }
228 }
229 
230 /// A guard for the mmap read lock.
231 ///
232 /// # Invariants
233 ///
234 /// This `MmapReadGuard` guard owns the mmap read lock.
235 pub struct MmapReadGuard<'a> {
236     mm: &'a MmWithUser,
237     // `mmap_read_lock` and `mmap_read_unlock` must be called on the same thread
238     _nts: NotThreadSafe,
239 }
240 
241 impl<'a> MmapReadGuard<'a> {
242     /// Look up a vma at the given address.
243     #[inline]
244     pub fn vma_lookup(&self, vma_addr: usize) -> Option<&virt::VmaRef> {
245         // SAFETY: By the type invariants we hold the mmap read guard, so we can safely call this
246         // method. Any value is okay for `vma_addr`.
247         let vma = unsafe { bindings::vma_lookup(self.mm.as_raw(), vma_addr) };
248 
249         if vma.is_null() {
250             None
251         } else {
252             // SAFETY: We just checked that a vma was found, so the pointer references a valid vma.
253             //
254             // Furthermore, the returned vma is still under the protection of the read lock guard
255             // and can be used while the mmap read lock is still held. That the vma is not used
256             // after the MmapReadGuard gets dropped is enforced by the borrow-checker.
257             unsafe { Some(virt::VmaRef::from_raw(vma)) }
258         }
259     }
260 }
261 
262 impl Drop for MmapReadGuard<'_> {
263     #[inline]
264     fn drop(&mut self) {
265         // SAFETY: We hold the read lock by the type invariants.
266         unsafe { bindings::mmap_read_unlock(self.mm.as_raw()) };
267     }
268 }
269 
270 /// A guard for the vma read lock.
271 ///
272 /// # Invariants
273 ///
274 /// This `VmaReadGuard` guard owns the vma read lock.
275 pub struct VmaReadGuard<'a> {
276     vma: &'a VmaRef,
277     // `vma_end_read` must be called on the same thread as where the lock was taken
278     _nts: NotThreadSafe,
279 }
280 
281 // Make all `VmaRef` methods available on `VmaReadGuard`.
282 impl Deref for VmaReadGuard<'_> {
283     type Target = VmaRef;
284 
285     #[inline]
286     fn deref(&self) -> &VmaRef {
287         self.vma
288     }
289 }
290 
291 impl Drop for VmaReadGuard<'_> {
292     #[inline]
293     fn drop(&mut self) {
294         // SAFETY: We hold the read lock by the type invariants.
295         unsafe { bindings::vma_end_read(self.vma.as_ptr()) };
296     }
297 }
298