xref: /linux/rust/kernel/mm.rs (revision fd1f8473503e5bf897bd3e8efe3545c0352954e6)
15bb9ed6cSAlice Ryhl // SPDX-License-Identifier: GPL-2.0
25bb9ed6cSAlice Ryhl 
35bb9ed6cSAlice Ryhl // Copyright (C) 2024 Google LLC.
45bb9ed6cSAlice Ryhl 
55bb9ed6cSAlice Ryhl //! Memory management.
65bb9ed6cSAlice Ryhl //!
75bb9ed6cSAlice Ryhl //! This module deals with managing the address space of userspace processes. Each process has an
85bb9ed6cSAlice Ryhl //! instance of [`Mm`], which keeps track of multiple VMAs (virtual memory areas). Each VMA
95bb9ed6cSAlice Ryhl //! corresponds to a region of memory that the userspace process can access, and the VMA lets you
105bb9ed6cSAlice Ryhl //! control what happens when userspace reads or writes to that region of memory.
115bb9ed6cSAlice Ryhl //!
125bb9ed6cSAlice Ryhl //! C header: [`include/linux/mm.h`](srctree/include/linux/mm.h)
135bb9ed6cSAlice Ryhl 
145bb9ed6cSAlice Ryhl use crate::{
155bb9ed6cSAlice Ryhl     bindings,
165bb9ed6cSAlice Ryhl     types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque},
175bb9ed6cSAlice Ryhl };
185bb9ed6cSAlice Ryhl use core::{ops::Deref, ptr::NonNull};
195bb9ed6cSAlice Ryhl 
20040f404bSAlice Ryhl pub mod virt;
213105f8f3SAlice Ryhl use virt::VmaRef;
22040f404bSAlice Ryhl 
23*5a789772SAlice Ryhl #[cfg(CONFIG_MMU)]
24*5a789772SAlice Ryhl pub use mmput_async::MmWithUserAsync;
25*5a789772SAlice Ryhl mod mmput_async;
26*5a789772SAlice Ryhl 
275bb9ed6cSAlice Ryhl /// A wrapper for the kernel's `struct mm_struct`.
285bb9ed6cSAlice Ryhl ///
295bb9ed6cSAlice Ryhl /// This represents the address space of a userspace process, so each process has one `Mm`
305bb9ed6cSAlice Ryhl /// instance. It may hold many VMAs internally.
315bb9ed6cSAlice Ryhl ///
325bb9ed6cSAlice Ryhl /// There is a counter called `mm_users` that counts the users of the address space; this includes
335bb9ed6cSAlice Ryhl /// the userspace process itself, but can also include kernel threads accessing the address space.
345bb9ed6cSAlice Ryhl /// Once `mm_users` reaches zero, this indicates that the address space can be destroyed. To access
355bb9ed6cSAlice Ryhl /// the address space, you must prevent `mm_users` from reaching zero while you are accessing it.
365bb9ed6cSAlice Ryhl /// The [`MmWithUser`] type represents an address space where this is guaranteed, and you can
375bb9ed6cSAlice Ryhl /// create one using [`mmget_not_zero`].
385bb9ed6cSAlice Ryhl ///
395bb9ed6cSAlice Ryhl /// The `ARef<Mm>` smart pointer holds an `mmgrab` refcount. Its destructor may sleep.
405bb9ed6cSAlice Ryhl ///
415bb9ed6cSAlice Ryhl /// # Invariants
425bb9ed6cSAlice Ryhl ///
435bb9ed6cSAlice Ryhl /// Values of this type are always refcounted using `mmgrab`.
445bb9ed6cSAlice Ryhl ///
455bb9ed6cSAlice Ryhl /// [`mmget_not_zero`]: Mm::mmget_not_zero
465bb9ed6cSAlice Ryhl #[repr(transparent)]
475bb9ed6cSAlice Ryhl pub struct Mm {
485bb9ed6cSAlice Ryhl     mm: Opaque<bindings::mm_struct>,
495bb9ed6cSAlice Ryhl }
505bb9ed6cSAlice Ryhl 
515bb9ed6cSAlice Ryhl // SAFETY: It is safe to call `mmdrop` on another thread than where `mmgrab` was called.
525bb9ed6cSAlice Ryhl unsafe impl Send for Mm {}
535bb9ed6cSAlice Ryhl // SAFETY: All methods on `Mm` can be called in parallel from several threads.
545bb9ed6cSAlice Ryhl unsafe impl Sync for Mm {}
555bb9ed6cSAlice Ryhl 
565bb9ed6cSAlice Ryhl // SAFETY: By the type invariants, this type is always refcounted.
575bb9ed6cSAlice Ryhl unsafe impl AlwaysRefCounted for Mm {
585bb9ed6cSAlice Ryhl     #[inline]
595bb9ed6cSAlice Ryhl     fn inc_ref(&self) {
605bb9ed6cSAlice Ryhl         // SAFETY: The pointer is valid since self is a reference.
615bb9ed6cSAlice Ryhl         unsafe { bindings::mmgrab(self.as_raw()) };
625bb9ed6cSAlice Ryhl     }
635bb9ed6cSAlice Ryhl 
645bb9ed6cSAlice Ryhl     #[inline]
655bb9ed6cSAlice Ryhl     unsafe fn dec_ref(obj: NonNull<Self>) {
665bb9ed6cSAlice Ryhl         // SAFETY: The caller is giving up their refcount.
675bb9ed6cSAlice Ryhl         unsafe { bindings::mmdrop(obj.cast().as_ptr()) };
685bb9ed6cSAlice Ryhl     }
695bb9ed6cSAlice Ryhl }
705bb9ed6cSAlice Ryhl 
715bb9ed6cSAlice Ryhl /// A wrapper for the kernel's `struct mm_struct`.
725bb9ed6cSAlice Ryhl ///
735bb9ed6cSAlice Ryhl /// This type is like [`Mm`], but with non-zero `mm_users`. It can only be used when `mm_users` can
745bb9ed6cSAlice Ryhl /// be proven to be non-zero at compile-time, usually because the relevant code holds an `mmget`
755bb9ed6cSAlice Ryhl /// refcount. It can be used to access the associated address space.
765bb9ed6cSAlice Ryhl ///
775bb9ed6cSAlice Ryhl /// The `ARef<MmWithUser>` smart pointer holds an `mmget` refcount. Its destructor may sleep.
785bb9ed6cSAlice Ryhl ///
795bb9ed6cSAlice Ryhl /// # Invariants
805bb9ed6cSAlice Ryhl ///
815bb9ed6cSAlice Ryhl /// Values of this type are always refcounted using `mmget`. The value of `mm_users` is non-zero.
825bb9ed6cSAlice Ryhl #[repr(transparent)]
835bb9ed6cSAlice Ryhl pub struct MmWithUser {
845bb9ed6cSAlice Ryhl     mm: Mm,
855bb9ed6cSAlice Ryhl }
865bb9ed6cSAlice Ryhl 
875bb9ed6cSAlice Ryhl // SAFETY: It is safe to call `mmput` on another thread than where `mmget` was called.
885bb9ed6cSAlice Ryhl unsafe impl Send for MmWithUser {}
895bb9ed6cSAlice Ryhl // SAFETY: All methods on `MmWithUser` can be called in parallel from several threads.
905bb9ed6cSAlice Ryhl unsafe impl Sync for MmWithUser {}
915bb9ed6cSAlice Ryhl 
925bb9ed6cSAlice Ryhl // SAFETY: By the type invariants, this type is always refcounted.
935bb9ed6cSAlice Ryhl unsafe impl AlwaysRefCounted for MmWithUser {
945bb9ed6cSAlice Ryhl     #[inline]
955bb9ed6cSAlice Ryhl     fn inc_ref(&self) {
965bb9ed6cSAlice Ryhl         // SAFETY: The pointer is valid since self is a reference.
975bb9ed6cSAlice Ryhl         unsafe { bindings::mmget(self.as_raw()) };
985bb9ed6cSAlice Ryhl     }
995bb9ed6cSAlice Ryhl 
1005bb9ed6cSAlice Ryhl     #[inline]
1015bb9ed6cSAlice Ryhl     unsafe fn dec_ref(obj: NonNull<Self>) {
1025bb9ed6cSAlice Ryhl         // SAFETY: The caller is giving up their refcount.
1035bb9ed6cSAlice Ryhl         unsafe { bindings::mmput(obj.cast().as_ptr()) };
1045bb9ed6cSAlice Ryhl     }
1055bb9ed6cSAlice Ryhl }
1065bb9ed6cSAlice Ryhl 
1075bb9ed6cSAlice Ryhl // Make all `Mm` methods available on `MmWithUser`.
1085bb9ed6cSAlice Ryhl impl Deref for MmWithUser {
1095bb9ed6cSAlice Ryhl     type Target = Mm;
1105bb9ed6cSAlice Ryhl 
1115bb9ed6cSAlice Ryhl     #[inline]
1125bb9ed6cSAlice Ryhl     fn deref(&self) -> &Mm {
1135bb9ed6cSAlice Ryhl         &self.mm
1145bb9ed6cSAlice Ryhl     }
1155bb9ed6cSAlice Ryhl }
1165bb9ed6cSAlice Ryhl 
1175bb9ed6cSAlice Ryhl // These methods are safe to call even if `mm_users` is zero.
1185bb9ed6cSAlice Ryhl impl Mm {
1195bb9ed6cSAlice Ryhl     /// Returns a raw pointer to the inner `mm_struct`.
1205bb9ed6cSAlice Ryhl     #[inline]
1215bb9ed6cSAlice Ryhl     pub fn as_raw(&self) -> *mut bindings::mm_struct {
1225bb9ed6cSAlice Ryhl         self.mm.get()
1235bb9ed6cSAlice Ryhl     }
1245bb9ed6cSAlice Ryhl 
1255bb9ed6cSAlice Ryhl     /// Obtain a reference from a raw pointer.
1265bb9ed6cSAlice Ryhl     ///
1275bb9ed6cSAlice Ryhl     /// # Safety
1285bb9ed6cSAlice Ryhl     ///
1295bb9ed6cSAlice Ryhl     /// The caller must ensure that `ptr` points at an `mm_struct`, and that it is not deallocated
1305bb9ed6cSAlice Ryhl     /// during the lifetime 'a.
1315bb9ed6cSAlice Ryhl     #[inline]
1325bb9ed6cSAlice Ryhl     pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_struct) -> &'a Mm {
1335bb9ed6cSAlice Ryhl         // SAFETY: Caller promises that the pointer is valid for 'a. Layouts are compatible due to
1345bb9ed6cSAlice Ryhl         // repr(transparent).
1355bb9ed6cSAlice Ryhl         unsafe { &*ptr.cast() }
1365bb9ed6cSAlice Ryhl     }
1375bb9ed6cSAlice Ryhl 
1385bb9ed6cSAlice Ryhl     /// Calls `mmget_not_zero` and returns a handle if it succeeds.
1395bb9ed6cSAlice Ryhl     #[inline]
1405bb9ed6cSAlice Ryhl     pub fn mmget_not_zero(&self) -> Option<ARef<MmWithUser>> {
1415bb9ed6cSAlice Ryhl         // SAFETY: The pointer is valid since self is a reference.
1425bb9ed6cSAlice Ryhl         let success = unsafe { bindings::mmget_not_zero(self.as_raw()) };
1435bb9ed6cSAlice Ryhl 
1445bb9ed6cSAlice Ryhl         if success {
1455bb9ed6cSAlice Ryhl             // SAFETY: We just created an `mmget` refcount.
1465bb9ed6cSAlice Ryhl             Some(unsafe { ARef::from_raw(NonNull::new_unchecked(self.as_raw().cast())) })
1475bb9ed6cSAlice Ryhl         } else {
1485bb9ed6cSAlice Ryhl             None
1495bb9ed6cSAlice Ryhl         }
1505bb9ed6cSAlice Ryhl     }
1515bb9ed6cSAlice Ryhl }
1525bb9ed6cSAlice Ryhl 
1535bb9ed6cSAlice Ryhl // These methods require `mm_users` to be non-zero.
1545bb9ed6cSAlice Ryhl impl MmWithUser {
1555bb9ed6cSAlice Ryhl     /// Obtain a reference from a raw pointer.
1565bb9ed6cSAlice Ryhl     ///
1575bb9ed6cSAlice Ryhl     /// # Safety
1585bb9ed6cSAlice Ryhl     ///
1595bb9ed6cSAlice Ryhl     /// The caller must ensure that `ptr` points at an `mm_struct`, and that `mm_users` remains
1605bb9ed6cSAlice Ryhl     /// non-zero for the duration of the lifetime 'a.
1615bb9ed6cSAlice Ryhl     #[inline]
1625bb9ed6cSAlice Ryhl     pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_struct) -> &'a MmWithUser {
1635bb9ed6cSAlice Ryhl         // SAFETY: Caller promises that the pointer is valid for 'a. The layout is compatible due
1645bb9ed6cSAlice Ryhl         // to repr(transparent).
1655bb9ed6cSAlice Ryhl         unsafe { &*ptr.cast() }
1665bb9ed6cSAlice Ryhl     }
1675bb9ed6cSAlice Ryhl 
1683105f8f3SAlice Ryhl     /// Attempt to access a vma using the vma read lock.
1693105f8f3SAlice Ryhl     ///
1703105f8f3SAlice Ryhl     /// This is an optimistic trylock operation, so it may fail if there is contention. In that
1713105f8f3SAlice Ryhl     /// case, you should fall back to taking the mmap read lock.
1723105f8f3SAlice Ryhl     ///
1733105f8f3SAlice Ryhl     /// When per-vma locks are disabled, this always returns `None`.
1743105f8f3SAlice Ryhl     #[inline]
1753105f8f3SAlice Ryhl     pub fn lock_vma_under_rcu(&self, vma_addr: usize) -> Option<VmaReadGuard<'_>> {
1763105f8f3SAlice Ryhl         #[cfg(CONFIG_PER_VMA_LOCK)]
1773105f8f3SAlice Ryhl         {
1783105f8f3SAlice Ryhl             // SAFETY: Calling `bindings::lock_vma_under_rcu` is always okay given an mm where
1793105f8f3SAlice Ryhl             // `mm_users` is non-zero.
1803105f8f3SAlice Ryhl             let vma = unsafe { bindings::lock_vma_under_rcu(self.as_raw(), vma_addr) };
1813105f8f3SAlice Ryhl             if !vma.is_null() {
1823105f8f3SAlice Ryhl                 return Some(VmaReadGuard {
1833105f8f3SAlice Ryhl                     // SAFETY: If `lock_vma_under_rcu` returns a non-null ptr, then it points at a
1843105f8f3SAlice Ryhl                     // valid vma. The vma is stable for as long as the vma read lock is held.
1853105f8f3SAlice Ryhl                     vma: unsafe { VmaRef::from_raw(vma) },
1863105f8f3SAlice Ryhl                     _nts: NotThreadSafe,
1873105f8f3SAlice Ryhl                 });
1883105f8f3SAlice Ryhl             }
1893105f8f3SAlice Ryhl         }
1903105f8f3SAlice Ryhl 
1913105f8f3SAlice Ryhl         // Silence warnings about unused variables.
1923105f8f3SAlice Ryhl         #[cfg(not(CONFIG_PER_VMA_LOCK))]
1933105f8f3SAlice Ryhl         let _ = vma_addr;
1943105f8f3SAlice Ryhl 
1953105f8f3SAlice Ryhl         None
1963105f8f3SAlice Ryhl     }
1973105f8f3SAlice Ryhl 
1985bb9ed6cSAlice Ryhl     /// Lock the mmap read lock.
1995bb9ed6cSAlice Ryhl     #[inline]
2005bb9ed6cSAlice Ryhl     pub fn mmap_read_lock(&self) -> MmapReadGuard<'_> {
2015bb9ed6cSAlice Ryhl         // SAFETY: The pointer is valid since self is a reference.
2025bb9ed6cSAlice Ryhl         unsafe { bindings::mmap_read_lock(self.as_raw()) };
2035bb9ed6cSAlice Ryhl 
2045bb9ed6cSAlice Ryhl         // INVARIANT: We just acquired the read lock.
2055bb9ed6cSAlice Ryhl         MmapReadGuard {
2065bb9ed6cSAlice Ryhl             mm: self,
2075bb9ed6cSAlice Ryhl             _nts: NotThreadSafe,
2085bb9ed6cSAlice Ryhl         }
2095bb9ed6cSAlice Ryhl     }
2105bb9ed6cSAlice Ryhl 
2115bb9ed6cSAlice Ryhl     /// Try to lock the mmap read lock.
2125bb9ed6cSAlice Ryhl     #[inline]
2135bb9ed6cSAlice Ryhl     pub fn mmap_read_trylock(&self) -> Option<MmapReadGuard<'_>> {
2145bb9ed6cSAlice Ryhl         // SAFETY: The pointer is valid since self is a reference.
2155bb9ed6cSAlice Ryhl         let success = unsafe { bindings::mmap_read_trylock(self.as_raw()) };
2165bb9ed6cSAlice Ryhl 
2175bb9ed6cSAlice Ryhl         if success {
2185bb9ed6cSAlice Ryhl             // INVARIANT: We just acquired the read lock.
2195bb9ed6cSAlice Ryhl             Some(MmapReadGuard {
2205bb9ed6cSAlice Ryhl                 mm: self,
2215bb9ed6cSAlice Ryhl                 _nts: NotThreadSafe,
2225bb9ed6cSAlice Ryhl             })
2235bb9ed6cSAlice Ryhl         } else {
2245bb9ed6cSAlice Ryhl             None
2255bb9ed6cSAlice Ryhl         }
2265bb9ed6cSAlice Ryhl     }
2275bb9ed6cSAlice Ryhl }
2285bb9ed6cSAlice Ryhl 
2295bb9ed6cSAlice Ryhl /// A guard for the mmap read lock.
2305bb9ed6cSAlice Ryhl ///
2315bb9ed6cSAlice Ryhl /// # Invariants
2325bb9ed6cSAlice Ryhl ///
2335bb9ed6cSAlice Ryhl /// This `MmapReadGuard` guard owns the mmap read lock.
2345bb9ed6cSAlice Ryhl pub struct MmapReadGuard<'a> {
2355bb9ed6cSAlice Ryhl     mm: &'a MmWithUser,
2365bb9ed6cSAlice Ryhl     // `mmap_read_lock` and `mmap_read_unlock` must be called on the same thread
2375bb9ed6cSAlice Ryhl     _nts: NotThreadSafe,
2385bb9ed6cSAlice Ryhl }
2395bb9ed6cSAlice Ryhl 
240040f404bSAlice Ryhl impl<'a> MmapReadGuard<'a> {
241040f404bSAlice Ryhl     /// Look up a vma at the given address.
242040f404bSAlice Ryhl     #[inline]
243040f404bSAlice Ryhl     pub fn vma_lookup(&self, vma_addr: usize) -> Option<&virt::VmaRef> {
244040f404bSAlice Ryhl         // SAFETY: By the type invariants we hold the mmap read guard, so we can safely call this
245040f404bSAlice Ryhl         // method. Any value is okay for `vma_addr`.
246040f404bSAlice Ryhl         let vma = unsafe { bindings::vma_lookup(self.mm.as_raw(), vma_addr) };
247040f404bSAlice Ryhl 
248040f404bSAlice Ryhl         if vma.is_null() {
249040f404bSAlice Ryhl             None
250040f404bSAlice Ryhl         } else {
251040f404bSAlice Ryhl             // SAFETY: We just checked that a vma was found, so the pointer references a valid vma.
252040f404bSAlice Ryhl             //
253040f404bSAlice Ryhl             // Furthermore, the returned vma is still under the protection of the read lock guard
254040f404bSAlice Ryhl             // and can be used while the mmap read lock is still held. That the vma is not used
255040f404bSAlice Ryhl             // after the MmapReadGuard gets dropped is enforced by the borrow-checker.
256040f404bSAlice Ryhl             unsafe { Some(virt::VmaRef::from_raw(vma)) }
257040f404bSAlice Ryhl         }
258040f404bSAlice Ryhl     }
259040f404bSAlice Ryhl }
260040f404bSAlice Ryhl 
2615bb9ed6cSAlice Ryhl impl Drop for MmapReadGuard<'_> {
2625bb9ed6cSAlice Ryhl     #[inline]
2635bb9ed6cSAlice Ryhl     fn drop(&mut self) {
2645bb9ed6cSAlice Ryhl         // SAFETY: We hold the read lock by the type invariants.
2655bb9ed6cSAlice Ryhl         unsafe { bindings::mmap_read_unlock(self.mm.as_raw()) };
2665bb9ed6cSAlice Ryhl     }
2675bb9ed6cSAlice Ryhl }
2683105f8f3SAlice Ryhl 
2693105f8f3SAlice Ryhl /// A guard for the vma read lock.
2703105f8f3SAlice Ryhl ///
2713105f8f3SAlice Ryhl /// # Invariants
2723105f8f3SAlice Ryhl ///
2733105f8f3SAlice Ryhl /// This `VmaReadGuard` guard owns the vma read lock.
2743105f8f3SAlice Ryhl pub struct VmaReadGuard<'a> {
2753105f8f3SAlice Ryhl     vma: &'a VmaRef,
2763105f8f3SAlice Ryhl     // `vma_end_read` must be called on the same thread as where the lock was taken
2773105f8f3SAlice Ryhl     _nts: NotThreadSafe,
2783105f8f3SAlice Ryhl }
2793105f8f3SAlice Ryhl 
2803105f8f3SAlice Ryhl // Make all `VmaRef` methods available on `VmaReadGuard`.
2813105f8f3SAlice Ryhl impl Deref for VmaReadGuard<'_> {
2823105f8f3SAlice Ryhl     type Target = VmaRef;
2833105f8f3SAlice Ryhl 
2843105f8f3SAlice Ryhl     #[inline]
2853105f8f3SAlice Ryhl     fn deref(&self) -> &VmaRef {
2863105f8f3SAlice Ryhl         self.vma
2873105f8f3SAlice Ryhl     }
2883105f8f3SAlice Ryhl }
2893105f8f3SAlice Ryhl 
2903105f8f3SAlice Ryhl impl Drop for VmaReadGuard<'_> {
2913105f8f3SAlice Ryhl     #[inline]
2923105f8f3SAlice Ryhl     fn drop(&mut self) {
2933105f8f3SAlice Ryhl         // SAFETY: We hold the read lock by the type invariants.
2943105f8f3SAlice Ryhl         unsafe { bindings::vma_end_read(self.vma.as_ptr()) };
2953105f8f3SAlice Ryhl     }
2963105f8f3SAlice Ryhl }
297