mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 08:38:45 +02:00 
			
		
		
		
	 9907e1df31
			
		
	
	
		9907e1df31
		
	
	
	
	
		
			
			Update call sites in the mm subsystem to import `ARef` and `AlwaysRefCounted` from `sync::aref` instead of `types`. This aligns with the ongoing effort to move `ARef` and `AlwaysRefCounted` to sync. Link: https://lkml.kernel.org/r/20250716091158.812860-1-shankari.ak0208@gmail.com Signed-off-by: Shankari Anand <shankari.ak0208@gmail.com> Suggested-by: Benno Lossin <lossin@kernel.org> Link: https://github.com/Rust-for-Linux/linux/issues/1173 Acked-by: Alice Ryhl <aliceryhl@google.com> Cc: Alex Gaynor <alex.gaynor@gmail.com> Cc: Andreas Hindborg <a.hindborg@kernel.org> Cc: Björn Roy Baron <bjorn3_gh@protonmail.com> Cc: Boqun Feng <boqun.feng@gmail.com> Cc: Danilo Krummrich <dakr@kernel.org> Cc: Gary Guo <gary@garyguo.net> Cc: Liam Howlett <liam.howlett@oracle.com> Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Cc: Miguel Ojeda <ojeda@kernel.org> Cc: Trevor Gross <tmgross@umich.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
		
			
				
	
	
		
			297 lines
		
	
	
	
		
			9.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
	
		
			9.7 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| 
 | |
| // Copyright (C) 2024 Google LLC.
 | |
| 
 | |
| //! Memory management.
 | |
| //!
 | |
| //! This module deals with managing the address space of userspace processes. Each process has an
 | |
| //! instance of [`Mm`], which keeps track of multiple VMAs (virtual memory areas). Each VMA
 | |
| //! corresponds to a region of memory that the userspace process can access, and the VMA lets you
 | |
| //! control what happens when userspace reads or writes to that region of memory.
 | |
| //!
 | |
| //! C header: [`include/linux/mm.h`](srctree/include/linux/mm.h)
 | |
| 
 | |
| use crate::{
 | |
|     bindings,
 | |
|     sync::aref::{ARef, AlwaysRefCounted},
 | |
|     types::{NotThreadSafe, Opaque},
 | |
| };
 | |
| use core::{ops::Deref, ptr::NonNull};
 | |
| 
 | |
| pub mod virt;
 | |
| use virt::VmaRef;
 | |
| 
 | |
| #[cfg(CONFIG_MMU)]
 | |
| pub use mmput_async::MmWithUserAsync;
 | |
| mod mmput_async;
 | |
| 
 | |
| /// A wrapper for the kernel's `struct mm_struct`.
 | |
| ///
 | |
| /// This represents the address space of a userspace process, so each process has one `Mm`
 | |
| /// instance. It may hold many VMAs internally.
 | |
| ///
 | |
| /// There is a counter called `mm_users` that counts the users of the address space; this includes
 | |
| /// the userspace process itself, but can also include kernel threads accessing the address space.
 | |
| /// Once `mm_users` reaches zero, this indicates that the address space can be destroyed. To access
 | |
| /// the address space, you must prevent `mm_users` from reaching zero while you are accessing it.
 | |
| /// The [`MmWithUser`] type represents an address space where this is guaranteed, and you can
 | |
| /// create one using [`mmget_not_zero`].
 | |
| ///
 | |
| /// The `ARef<Mm>` smart pointer holds an `mmgrab` refcount. Its destructor may sleep.
 | |
| ///
 | |
| /// # Invariants
 | |
| ///
 | |
| /// Values of this type are always refcounted using `mmgrab`.
 | |
| ///
 | |
| /// [`mmget_not_zero`]: Mm::mmget_not_zero
 | |
| #[repr(transparent)]
 | |
| pub struct Mm {
 | |
|     mm: Opaque<bindings::mm_struct>,
 | |
| }
 | |
| 
 | |
| // SAFETY: It is safe to call `mmdrop` on another thread than where `mmgrab` was called.
 | |
| unsafe impl Send for Mm {}
 | |
| // SAFETY: All methods on `Mm` can be called in parallel from several threads.
 | |
| unsafe impl Sync for Mm {}
 | |
| 
 | |
| // SAFETY: By the type invariants, this type is always refcounted.
 | |
| unsafe impl AlwaysRefCounted for Mm {
 | |
|     #[inline]
 | |
|     fn inc_ref(&self) {
 | |
|         // SAFETY: The pointer is valid since self is a reference.
 | |
|         unsafe { bindings::mmgrab(self.as_raw()) };
 | |
|     }
 | |
| 
 | |
|     #[inline]
 | |
|     unsafe fn dec_ref(obj: NonNull<Self>) {
 | |
|         // SAFETY: The caller is giving up their refcount.
 | |
|         unsafe { bindings::mmdrop(obj.cast().as_ptr()) };
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// A wrapper for the kernel's `struct mm_struct`.
 | |
| ///
 | |
| /// This type is like [`Mm`], but with non-zero `mm_users`. It can only be used when `mm_users` can
 | |
| /// be proven to be non-zero at compile-time, usually because the relevant code holds an `mmget`
 | |
| /// refcount. It can be used to access the associated address space.
 | |
| ///
 | |
| /// The `ARef<MmWithUser>` smart pointer holds an `mmget` refcount. Its destructor may sleep.
 | |
| ///
 | |
| /// # Invariants
 | |
| ///
 | |
| /// Values of this type are always refcounted using `mmget`. The value of `mm_users` is non-zero.
 | |
| #[repr(transparent)]
 | |
| pub struct MmWithUser {
 | |
|     mm: Mm,
 | |
| }
 | |
| 
 | |
| // SAFETY: It is safe to call `mmput` on another thread than where `mmget` was called.
 | |
| unsafe impl Send for MmWithUser {}
 | |
| // SAFETY: All methods on `MmWithUser` can be called in parallel from several threads.
 | |
| unsafe impl Sync for MmWithUser {}
 | |
| 
 | |
| // SAFETY: By the type invariants, this type is always refcounted.
 | |
| unsafe impl AlwaysRefCounted for MmWithUser {
 | |
|     #[inline]
 | |
|     fn inc_ref(&self) {
 | |
|         // SAFETY: The pointer is valid since self is a reference.
 | |
|         unsafe { bindings::mmget(self.as_raw()) };
 | |
|     }
 | |
| 
 | |
|     #[inline]
 | |
|     unsafe fn dec_ref(obj: NonNull<Self>) {
 | |
|         // SAFETY: The caller is giving up their refcount.
 | |
|         unsafe { bindings::mmput(obj.cast().as_ptr()) };
 | |
|     }
 | |
| }
 | |
| 
 | |
| // Make all `Mm` methods available on `MmWithUser`.
 | |
| impl Deref for MmWithUser {
 | |
|     type Target = Mm;
 | |
| 
 | |
|     #[inline]
 | |
|     fn deref(&self) -> &Mm {
 | |
|         &self.mm
 | |
|     }
 | |
| }
 | |
| 
 | |
| // These methods are safe to call even if `mm_users` is zero.
 | |
| impl Mm {
 | |
|     /// Returns a raw pointer to the inner `mm_struct`.
 | |
|     #[inline]
 | |
|     pub fn as_raw(&self) -> *mut bindings::mm_struct {
 | |
|         self.mm.get()
 | |
|     }
 | |
| 
 | |
|     /// Obtain a reference from a raw pointer.
 | |
|     ///
 | |
|     /// # Safety
 | |
|     ///
 | |
|     /// The caller must ensure that `ptr` points at an `mm_struct`, and that it is not deallocated
 | |
|     /// during the lifetime 'a.
 | |
|     #[inline]
 | |
|     pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_struct) -> &'a Mm {
 | |
|         // SAFETY: Caller promises that the pointer is valid for 'a. Layouts are compatible due to
 | |
|         // repr(transparent).
 | |
|         unsafe { &*ptr.cast() }
 | |
|     }
 | |
| 
 | |
|     /// Calls `mmget_not_zero` and returns a handle if it succeeds.
 | |
|     #[inline]
 | |
|     pub fn mmget_not_zero(&self) -> Option<ARef<MmWithUser>> {
 | |
|         // SAFETY: The pointer is valid since self is a reference.
 | |
|         let success = unsafe { bindings::mmget_not_zero(self.as_raw()) };
 | |
| 
 | |
|         if success {
 | |
|             // SAFETY: We just created an `mmget` refcount.
 | |
|             Some(unsafe { ARef::from_raw(NonNull::new_unchecked(self.as_raw().cast())) })
 | |
|         } else {
 | |
|             None
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| // These methods require `mm_users` to be non-zero.
 | |
| impl MmWithUser {
 | |
|     /// Obtain a reference from a raw pointer.
 | |
|     ///
 | |
|     /// # Safety
 | |
|     ///
 | |
|     /// The caller must ensure that `ptr` points at an `mm_struct`, and that `mm_users` remains
 | |
|     /// non-zero for the duration of the lifetime 'a.
 | |
|     #[inline]
 | |
|     pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_struct) -> &'a MmWithUser {
 | |
|         // SAFETY: Caller promises that the pointer is valid for 'a. The layout is compatible due
 | |
|         // to repr(transparent).
 | |
|         unsafe { &*ptr.cast() }
 | |
|     }
 | |
| 
 | |
|     /// Attempt to access a vma using the vma read lock.
 | |
|     ///
 | |
|     /// This is an optimistic trylock operation, so it may fail if there is contention. In that
 | |
|     /// case, you should fall back to taking the mmap read lock.
 | |
|     ///
 | |
|     /// When per-vma locks are disabled, this always returns `None`.
 | |
|     #[inline]
 | |
|     pub fn lock_vma_under_rcu(&self, vma_addr: usize) -> Option<VmaReadGuard<'_>> {
 | |
|         #[cfg(CONFIG_PER_VMA_LOCK)]
 | |
|         {
 | |
|             // SAFETY: Calling `bindings::lock_vma_under_rcu` is always okay given an mm where
 | |
|             // `mm_users` is non-zero.
 | |
|             let vma = unsafe { bindings::lock_vma_under_rcu(self.as_raw(), vma_addr) };
 | |
|             if !vma.is_null() {
 | |
|                 return Some(VmaReadGuard {
 | |
|                     // SAFETY: If `lock_vma_under_rcu` returns a non-null ptr, then it points at a
 | |
|                     // valid vma. The vma is stable for as long as the vma read lock is held.
 | |
|                     vma: unsafe { VmaRef::from_raw(vma) },
 | |
|                     _nts: NotThreadSafe,
 | |
|                 });
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Silence warnings about unused variables.
 | |
|         #[cfg(not(CONFIG_PER_VMA_LOCK))]
 | |
|         let _ = vma_addr;
 | |
| 
 | |
|         None
 | |
|     }
 | |
| 
 | |
|     /// Lock the mmap read lock.
 | |
|     #[inline]
 | |
|     pub fn mmap_read_lock(&self) -> MmapReadGuard<'_> {
 | |
|         // SAFETY: The pointer is valid since self is a reference.
 | |
|         unsafe { bindings::mmap_read_lock(self.as_raw()) };
 | |
| 
 | |
|         // INVARIANT: We just acquired the read lock.
 | |
|         MmapReadGuard {
 | |
|             mm: self,
 | |
|             _nts: NotThreadSafe,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /// Try to lock the mmap read lock.
 | |
|     #[inline]
 | |
|     pub fn mmap_read_trylock(&self) -> Option<MmapReadGuard<'_>> {
 | |
|         // SAFETY: The pointer is valid since self is a reference.
 | |
|         let success = unsafe { bindings::mmap_read_trylock(self.as_raw()) };
 | |
| 
 | |
|         if success {
 | |
|             // INVARIANT: We just acquired the read lock.
 | |
|             Some(MmapReadGuard {
 | |
|                 mm: self,
 | |
|                 _nts: NotThreadSafe,
 | |
|             })
 | |
|         } else {
 | |
|             None
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// A guard for the mmap read lock.
 | |
| ///
 | |
| /// # Invariants
 | |
| ///
 | |
| /// This `MmapReadGuard` guard owns the mmap read lock.
 | |
| pub struct MmapReadGuard<'a> {
 | |
|     mm: &'a MmWithUser,
 | |
|     // `mmap_read_lock` and `mmap_read_unlock` must be called on the same thread
 | |
|     _nts: NotThreadSafe,
 | |
| }
 | |
| 
 | |
| impl<'a> MmapReadGuard<'a> {
 | |
|     /// Look up a vma at the given address.
 | |
|     #[inline]
 | |
|     pub fn vma_lookup(&self, vma_addr: usize) -> Option<&virt::VmaRef> {
 | |
|         // SAFETY: By the type invariants we hold the mmap read guard, so we can safely call this
 | |
|         // method. Any value is okay for `vma_addr`.
 | |
|         let vma = unsafe { bindings::vma_lookup(self.mm.as_raw(), vma_addr) };
 | |
| 
 | |
|         if vma.is_null() {
 | |
|             None
 | |
|         } else {
 | |
|             // SAFETY: We just checked that a vma was found, so the pointer references a valid vma.
 | |
|             //
 | |
|             // Furthermore, the returned vma is still under the protection of the read lock guard
 | |
|             // and can be used while the mmap read lock is still held. That the vma is not used
 | |
|             // after the MmapReadGuard gets dropped is enforced by the borrow-checker.
 | |
|             unsafe { Some(virt::VmaRef::from_raw(vma)) }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Drop for MmapReadGuard<'_> {
 | |
|     #[inline]
 | |
|     fn drop(&mut self) {
 | |
|         // SAFETY: We hold the read lock by the type invariants.
 | |
|         unsafe { bindings::mmap_read_unlock(self.mm.as_raw()) };
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// A guard for the vma read lock.
 | |
| ///
 | |
| /// # Invariants
 | |
| ///
 | |
| /// This `VmaReadGuard` guard owns the vma read lock.
 | |
| pub struct VmaReadGuard<'a> {
 | |
|     vma: &'a VmaRef,
 | |
|     // `vma_end_read` must be called on the same thread as where the lock was taken
 | |
|     _nts: NotThreadSafe,
 | |
| }
 | |
| 
 | |
| // Make all `VmaRef` methods available on `VmaReadGuard`.
 | |
| impl Deref for VmaReadGuard<'_> {
 | |
|     type Target = VmaRef;
 | |
| 
 | |
|     #[inline]
 | |
|     fn deref(&self) -> &VmaRef {
 | |
|         self.vma
 | |
|     }
 | |
| }
 | |
| 
 | |
| impl Drop for VmaReadGuard<'_> {
 | |
|     #[inline]
 | |
|     fn drop(&mut self) {
 | |
|         // SAFETY: We hold the read lock by the type invariants.
 | |
|         unsafe { bindings::vma_end_read(self.vma.as_ptr()) };
 | |
|     }
 | |
| }
 |