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