kernel/
mm.rs

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