From nobody Thu May 14 09:08:01 2026 Received: from mail-wr1-f74.google.com (mail-wr1-f74.google.com [209.85.221.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 975CD1D1F4B for ; Wed, 20 Nov 2024 14:56:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114581; cv=none; b=eeJS1Y8IzRD9DwWOyymo69D4vSLmpOamn/OD7Gst99EWAYHpHCTZs2M7T3ay2KPRhYgJRBF0Kfnwp5kP1Sq2vlRgbevG9/dT8KVEqw5PJ2v97Gbo4f7eS4qfRqCMBbgsZT2jjtMVKsR65/3E5TCuT2droG2JLdunrNI7q5BNh7Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114581; c=relaxed/simple; bh=thHW2hYjZXfFchwxaSHY31jS6Gxjf/8txx6XeVPPA40=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=lOl+n0coGCWl08bYBc3YBAjPjgfPg/8pkOhEwTm7q4RoQGpBZhMB5oXjV7J1pK0AT1oaLytpYwJZc8GkUvA1Qp64ODXvFDja1cMyre1oKPgTja75TKfRETUgWFXKIB9WtFXJQDSZ0/C00/2imn48yhd+M5q/mUkKMJgM8lvMVCw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=eybKjgv4; arc=none smtp.client-ip=209.85.221.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="eybKjgv4" Received: by mail-wr1-f74.google.com with SMTP id ffacd0b85a97d-38231e6b4cbso3605219f8f.3 for ; Wed, 20 Nov 2024 06:56:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732114578; x=1732719378; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=iRAvnS0IaCWBMzdRyDGxGfoX2WP3nXVUoH5LBPSc5Qs=; b=eybKjgv4PFc5KfXmZJcVYt1b7hbYiQRDgN1YxYOdacw3hzsoVaEoLpPxmFwNkMpGAj W3LI4u2N6T0EBWnuA0DhIAhmQNc6zPEOdT3ier6Btyz/hgiZcXYFGGR10UU5O7hd2hGw 9d+aGByeAwRdWkPC+yWn7E6+uqknVRPTqMHkBlWsnOW5Ksm1+MIomaumUsKJGbRcOmm0 qeALVYHveqmD2HWze09H0riX3BELXazxg3QLcxx4mWHwhNHVpNBLTn9AMOh50mVgH6AY 18H/Ywu+UhLt/LY/31yumaP+JuU6lXqjO5Vxc2YXXHpGxSABPwNoIW/W3gd+kGy5Tqn5 u00A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732114578; x=1732719378; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=iRAvnS0IaCWBMzdRyDGxGfoX2WP3nXVUoH5LBPSc5Qs=; b=GK4so8EbEWdAOkdCy9LNcRGHUpH8j73LZUlPatL9xglnX9EfKcDpr9pfO+bfYbIOiy /JAKyGPbwyFf8zp82p4S++wE6fBhC2dhXroJtFz39wc7OL52Wm0aq6xK14/SD2IfgmQ3 xKXAX0uhZNL8pPOFbJTCS7q3M9eCUoCXSFxRxGJ88xN6VbIk44W/vAXtVt8Yty7qFETO oRB53hlAqOydpEyhsozQm+878QUtP4yiFi43nGCtLP5mVC0NOvmHyCjFy4j1E9Q4DdfI 2huB+cdOVLjGC3NDKJUE4ZQEi5fAuaMXIHVSv3FX7q24zs9bIS6OCDRwdayM3GLNByQW HDjg== X-Forwarded-Encrypted: i=1; AJvYcCXl8i6SG8jgZaDYPNPHBVBGVVpAha6SsLGR1cnyyEJPVWFns4zDk8Qi066GI6Fm+ThZKc0TgZJ1jCgz6tU=@vger.kernel.org X-Gm-Message-State: AOJu0YyY6W1s5di2CDNmY28w/WAtW8tp5GJ3rxzXVtquiWUlH3rItMgr UJhirl61eWR6qrg84xtS6CLMVxzxDXVU0VnqA7mbcN5kCz+bvv1ueRrwI7VsV3mg/4yewCieXdY /WUX9NBOScBBPvQ== X-Google-Smtp-Source: AGHT+IGq/r3HGbbtFoFVRvHr1EOlzN/Wt8+om4kWd42V+YspQZes17Yps3LGccfMBIlhtc72415J8+GJZmwAm9s= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a05:6000:cf:b0:37d:5467:4008 with SMTP id ffacd0b85a97d-38254b18ad3mr818f8f.5.1732114577963; Wed, 20 Nov 2024 06:56:17 -0800 (PST) Date: Wed, 20 Nov 2024 14:49:55 +0000 In-Reply-To: <20241120-vma-v8-0-eb31425da66b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241120-vma-v8-0-eb31425da66b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=9857; i=aliceryhl@google.com; h=from:subject:message-id; bh=thHW2hYjZXfFchwxaSHY31jS6Gxjf/8txx6XeVPPA40=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnPfiIPfGxtRmuM/beITcG2729I1pZZuD2y71Hm a5hLFdiTyWJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZz34iAAKCRAEWL7uWMY5 RrM9EAChZwI5X5J59zvpP7My8BG3gVmNliYXLaMF7DdF13YYqlfRr6Nw3FK7e+/5u8oyjxwjLDq i3Aerdaf3lQlSYU3T8YKbVn4UKhByCAgIggWEbwvt8y0OPSLqBJ8gzZ8qYHcluaqHVB6En/S47l 7lsU2P1ozQStRB699rZdudrnMkzcxUw7oPTdb4oj33RV6AN3B7WuiPf/9FXT+L99Mz3fDdjhyu/ DZFg5TzMI7PXpxVysdNfctskP27Y+Z/4W/wr534zWMVNHWwURuyfzMFgxpA68y6YgmeIp7jBp80 h2+3Y4/WFCfH7dtvc2a3W7vdheRq8OqP3hIU7j85so4RpYZrLRFWJTsI6ksb8Tx6YatClhaN8xs QqZWzy67zmvq6CD9bNdc8iSGKicFWYqL3CRAK0dPh1iKzItCU/VYo6NDfKDVPKcJGCoeRa1mny2 klw3Ap8CxgCgpmRPo9MKuHZre8uhJo7HBYPJMqNjVqTzWUGkHHap3fIa/pW/02sBXfteKVY4BsY ixHgtqTqQsvDkUGNy7QnWKGvdDAWJel/bBeazpquvJIDptb99myFDl581bVHCit1O/7vW+4egEw CeMAkJ7joMJHpeK7O9KH0ek1UkNOypcg1cM4iLNqxpYvpGAVDO0IA41NZEWF3DyHOy4fl4KJhlt xSzwOusQ+/1n5aA== X-Mailer: b4 0.13.0 Message-ID: <20241120-vma-v8-1-eb31425da66b@google.com> Subject: [PATCH v8 1/7] mm: rust: add abstraction for struct mm_struct From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable These abstractions allow you to reference a `struct mm_struct` using both mmgrab and mmget refcounts. This is done using two Rust types: * Mm - represents an mm_struct where you don't know anything about the value of mm_users. * MmWithUser - represents an mm_struct where you know at compile time that mm_users is non-zero. This allows us to encode in the type system whether a method requires that mm_users is non-zero or not. For instance, you can always call `mmget_not_zero` but you can only call `mmap_read_lock` when mm_users is non-zero. Signed-off-by: Alice Ryhl --- rust/helpers/helpers.c | 1 + rust/helpers/mm.c | 39 +++++++++ rust/kernel/lib.rs | 1 + rust/kernel/mm.rs | 219 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 260 insertions(+) diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 20a0c69d5cc7..60a488eb4efe 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -13,6 +13,7 @@ #include "build_bug.c" #include "err.c" #include "kunit.c" +#include "mm.c" #include "mutex.c" #include "page.c" #include "rbtree.c" diff --git a/rust/helpers/mm.c b/rust/helpers/mm.c new file mode 100644 index 000000000000..7201747a5d31 --- /dev/null +++ b/rust/helpers/mm.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +void rust_helper_mmgrab(struct mm_struct *mm) +{ + mmgrab(mm); +} + +void rust_helper_mmdrop(struct mm_struct *mm) +{ + mmdrop(mm); +} + +void rust_helper_mmget(struct mm_struct *mm) +{ + mmget(mm); +} + +bool rust_helper_mmget_not_zero(struct mm_struct *mm) +{ + return mmget_not_zero(mm); +} + +void rust_helper_mmap_read_lock(struct mm_struct *mm) +{ + mmap_read_lock(mm); +} + +bool rust_helper_mmap_read_trylock(struct mm_struct *mm) +{ + return mmap_read_trylock(mm); +} + +void rust_helper_mmap_read_unlock(struct mm_struct *mm) +{ + mmap_read_unlock(mm); +} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 66f5cde7f322..cc1963510cdf 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -43,6 +43,7 @@ pub mod kunit; pub mod list; pub mod miscdevice; +pub mod mm; #[cfg(CONFIG_NET)] pub mod net; pub mod page; diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs new file mode 100644 index 000000000000..84cba581edaa --- /dev/null +++ b/rust/kernel/mm.rs @@ -0,0 +1,219 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (C) 2024 Google LLC. + +//! Memory management. +//! +//! C header: [`include/linux/mm.h`](srctree/include/linux/mm.h) + +use crate::{ + bindings, + types::{ARef, AlwaysRefCounted, NotThreadSafe, Opaque}, +}; +use core::{ops::Deref, ptr::NonNull}; + +/// A wrapper for the kernel's `struct mm_struct`. +/// +/// Since `mm_users` may be zero, the associated address space may not exi= st anymore. You can use +/// [`mmget_not_zero`] to be able to access the address space. +/// +/// The `ARef` smart pointer holds an `mmgrab` refcount. Its destructo= r 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, +} + +// SAFETY: It is safe to call `mmdrop` on another thread than where `mmgra= b` was called. +unsafe impl Send for Mm {} +// SAFETY: All methods on `Mm` can be called in parallel from several thre= ads. +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) { + // 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` smart pointer holds an `mmget` refcount. Its de= structor 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 seve= ral 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) { + // 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 =3D Mm; + + #[inline] + fn deref(&self) -> &Mm { + &self.mm + } +} + +// These methods are safe to call even if `mm_users` is zero. +impl Mm { + /// Call `mmgrab` on `current.mm`. + #[inline] + pub fn mmgrab_current() -> Option> { + // SAFETY: It's safe to get the `mm` field from current. + let mm =3D unsafe { + let current =3D bindings::get_current(); + (*current).mm + }; + + if mm.is_null() { + return None; + } + + // SAFETY: The value of `current->mm` is guaranteed to be null or = a valid `mm_struct`. We + // just checked that it's not null. Furthermore, the returned `&Mm= ` is valid only for the + // duration of this function, and `current->mm` will stay valid fo= r that long. + let mm =3D unsafe { Mm::from_raw(mm) }; + + // This increments the refcount using `mmgrab`. + Some(ARef::from(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 th= at 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. Layou= ts 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> { + // SAFETY: The pointer is valid since self is a reference. + let success =3D 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_ra= w().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 th= at `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 MmW= ithUser { + // SAFETY: Caller promises that the pointer is valid for 'a. The l= ayout is compatible due + // to repr(transparent). + unsafe { &*ptr.cast() } + } + + /// 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> { + // SAFETY: The pointer is valid since self is a reference. + let success =3D 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 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()) }; + } +} --=20 2.47.0.371.ga323438b13-goog From nobody Thu May 14 09:08:01 2026 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 742671D460B for ; Wed, 20 Nov 2024 14:56:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114584; cv=none; b=Z2WKjr8Tc7Nwr5LbUCUodPYLEkPW9xO4YMEEOqXzxSs4AHXhhr09VBqxfXs+z8HKx753bKal+wex1MsT4hv0VlVZHHDuSLSfxTLslad2zO/Tv+rWcmkK+oJWh8FpWpZKpkRaSj2RXAw1+hfvxkevhcE/J5RoMyOqNP94c7bNo4k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114584; c=relaxed/simple; bh=Xqhb993p62ucfXpgqmTAzwF8zVU/iTXacAc64i+hvXs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=YXZBRNxo6Z0dSO13X7dXS2Cl7K+uFnsp9jyCiZ3hbjkuyRpVGU1c33vVxS+zWl5Xe6hE25VIw8dZgNPkZaxJuzlub+iIWLtFUFIuzB4wdwQemSpfzOxmIXco/f+GvuWclQSFVk/tVOrexkohi0pPnpOOFNRCD3kpzb0ask222nE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=0rJ7HrJL; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="0rJ7HrJL" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-6ee484ec18aso42867947b3.2 for ; Wed, 20 Nov 2024 06:56:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732114580; x=1732719380; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=hUP5pKIRXgXTZOS13MJMWQ9DFpxOfGZ7r+UgNJvVuSI=; b=0rJ7HrJLBN3h3gCT51daqKjsnmC0ebM0JccG86UFWwtUG/Y+RBcPonIYVf87eA7w5z IJ1D745TImrQwdEX1cpuUIX4ABW98J5A9FXiFd5rOgt3YzRSOirmZXXtr/B9E1SuNQfL 3xk1nhUHP77TTvQBT9EzBAOvv4sj1PZcaFge7CaGcmy/6wf96djPIkdTr5onjuPqG5jb 5swAlYphJV5wAC4E3jTZck7yzRUl92unpcj4HKAakQEn6+21vb6MBoi9CaR1v/ffbeym 7GwrGCXEWi6gKlSL9QCkVmcSgQ4SJAqBnNGOzpQEUOluHjY3zPI8zz+Td5sU+IWP9ZvJ upuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732114580; x=1732719380; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=hUP5pKIRXgXTZOS13MJMWQ9DFpxOfGZ7r+UgNJvVuSI=; b=lBkiipdEhjR6reFXIg2nx1/xYku4NkSmqyp5bIO32YJ89per+WU9+QwAmC+jyuqiHc /iri0qk+n2muovUfihYzzopR6F23J9CicV8C/Pl3njsomqu61qvjsesf3JLmABEWeaMS yB1qyLN0GhS0AD+fR+cwgSGUoggqx8xHJDI5PYM/pTPD/SNp4PkOdB5kY+l9sN08e9lt 3fgIVFH7lWdLEfdsx0gn7JEmfInPPwjkzD3WUQEIDsmseWQD6MaZnke1GcyjSyIlwRrN dkhUF9zzAY++x2rP4j528neOr6s/9FOpWk5BrOqLzuNWL54Ed+Ph4JrwmmoF4pVwfOKe o4nQ== X-Forwarded-Encrypted: i=1; AJvYcCU6Gb665BhXDVpXVLBY5UtQOfWLD53Hbw6MM5VyHmgh8fcjy2hqVtzxeV/7pLKF4WV7ncueL+/G3clK52c=@vger.kernel.org X-Gm-Message-State: AOJu0Yz88JQ4NYxS/xm2JG5mGhAUVF70hSTOHFkxMJE3VxWtOTp3tMiP GyoErz0GiwUYDhVwEX9aWX71s0iMw5aYEs9exSfMCy4rDDUq6Mh0TMbF3lgFPXOOZtUCOu2ZkX3 Nx3yXVyDxyM9g3Q== X-Google-Smtp-Source: AGHT+IEG9WEVO32XNJycTeJbJu48vAwd8yZZDgjUr+05hjT6U66t/ondGMQmQEA/GIQ+PsqbB1I6Xqu/GnabS+U= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a05:690c:5781:b0:6e2:ad08:4924 with SMTP id 00721157ae682-6eebd296195mr14787b3.4.1732114580372; Wed, 20 Nov 2024 06:56:20 -0800 (PST) Date: Wed, 20 Nov 2024 14:49:56 +0000 In-Reply-To: <20241120-vma-v8-0-eb31425da66b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241120-vma-v8-0-eb31425da66b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=8694; i=aliceryhl@google.com; h=from:subject:message-id; bh=Xqhb993p62ucfXpgqmTAzwF8zVU/iTXacAc64i+hvXs=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnPfiJtZ8e3RVRA+k2lDQWtngvEf9QEVRA3KEln +zY498BKQmJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZz34iQAKCRAEWL7uWMY5 RpOaD/4yxq12q8wgIfSEmCve+/+Os+hqeA6WaIrFWW5ionzJ0gIAJ9cftQLGZTKFI8+rvupF8Lp dR1pbVHaU8sw+3jpSLHyp0jNLFTOL5gbGW1yFUHsGIjzxw9ZghQPcX+3vola7oY+NRtH0UmDDSf 8SHI4Dgs+ykt3Kxa09hTFwnho5mhAtnRKj2ngOcwoqWbTMeGi7vSEbENMrrIyTRmnN4JMfdtNSM w/yYL/NWvnBcoEgwTBvK3Nb1UOFaXc0Qbqs3Bjv0y9q/0WFl6Pflj7UA/Fnoy7ic1VZsxQUDmvs TqskcSB6vHZBhIne4/8r2NYal0rmG9qtI0u1O51X9qF+udqdWZtRJBrFDnWI9oEIWUaNE+THgG0 5/kSBR40GPZYjpwSdwM4HiyBlgxx74DpP9La+cyScGLvbsTOqG/8VkQLtlSus1MsYrElbH1Owqh fFYUr9RuGgxgFZVRxAnc0bIBTam6l6qUBZkUWO/Oa9wbwgq9laxBOwXXDAjr18IFTGblGKLyeCW 1YOxkDN0nbIADD4637WxbTL4l2wYEaDiGA1W5ZMdFdJugTmNZodJxoye7vDLMjEOx5d+dvf2/t7 gFm838Bm4GUkNA1Dm/Pjvht0d8hg0e9hRZx3uqJnRZIXU2Lt6DznOKYGva8smnLR0ySkWip8guU k0h7uXIHYMJyYWA== X-Mailer: b4 0.13.0 Message-ID: <20241120-vma-v8-2-eb31425da66b@google.com> Subject: [PATCH v8 2/7] mm: rust: add vm_area_struct methods that require read access From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable This adds a type called VmAreaRef which is used when referencing a vma that you have read access to. Here, read access means that you hold either the mmap read lock or the vma read lock (or stronger). Additionally, a vma_lookup method is added to the mmap read guard, which enables you to obtain a &VmAreaRef in safe Rust code. Signed-off-by: Alice Ryhl Acked-by: Lorenzo Stoakes (for mm bits) --- rust/helpers/mm.c | 6 ++ rust/kernel/mm.rs | 21 ++++++ rust/kernel/mm/virt.rs | 171 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 198 insertions(+) diff --git a/rust/helpers/mm.c b/rust/helpers/mm.c index 7201747a5d31..7b72eb065a3e 100644 --- a/rust/helpers/mm.c +++ b/rust/helpers/mm.c @@ -37,3 +37,9 @@ void rust_helper_mmap_read_unlock(struct mm_struct *mm) { mmap_read_unlock(mm); } + +struct vm_area_struct *rust_helper_vma_lookup(struct mm_struct *mm, + unsigned long addr) +{ + return vma_lookup(mm, addr); +} diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs index 84cba581edaa..ace8e7d57afe 100644 --- a/rust/kernel/mm.rs +++ b/rust/kernel/mm.rs @@ -12,6 +12,8 @@ }; use core::{ops::Deref, ptr::NonNull}; =20 +pub mod virt; + /// A wrapper for the kernel's `struct mm_struct`. /// /// Since `mm_users` may be zero, the associated address space may not exi= st anymore. You can use @@ -210,6 +212,25 @@ pub struct MmapReadGuard<'a> { _nts: NotThreadSafe, } =20 +impl<'a> MmapReadGuard<'a> { + /// Look up a vma at the given address. + #[inline] + pub fn vma_lookup(&self, vma_addr: usize) -> Option<&virt::VmAreaRef> { + // SAFETY: We hold a reference to the mm, so the pointer must be v= alid. Any value is okay + // for `vma_addr`. + let vma =3D unsafe { bindings::vma_lookup(self.mm.as_raw(), vma_ad= dr as _) }; + + if vma.is_null() { + None + } else { + // SAFETY: We just checked that a vma was found, so the pointe= r is valid. Furthermore, + // the returned area will borrow from this read lock guard, so= it can only be used + // while the mmap read lock is still held. + unsafe { Some(virt::VmAreaRef::from_raw(vma)) } + } + } +} + impl Drop for MmapReadGuard<'_> { #[inline] fn drop(&mut self) { diff --git a/rust/kernel/mm/virt.rs b/rust/kernel/mm/virt.rs new file mode 100644 index 000000000000..1e755dca46dd --- /dev/null +++ b/rust/kernel/mm/virt.rs @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (C) 2024 Google LLC. + +//! Virtual memory. + +use crate::{bindings, types::Opaque}; + +/// A wrapper for the kernel's `struct vm_area_struct` with read access. +/// +/// It represents an area of virtual memory. +/// +/// # Invariants +/// +/// The caller must hold the mmap read lock or the vma read lock. +#[repr(transparent)] +pub struct VmAreaRef { + vma: Opaque, +} + +// Methods you can call when holding the mmap or vma read lock (or strong)= . They must be usable no +// matter what the vma flags are. +impl VmAreaRef { + /// Access a virtual memory area given a raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that `vma` is valid for the duration of 'a, an= d that the mmap read lock + /// (or stronger) is held for at least the duration of 'a. + #[inline] + pub unsafe fn from_raw<'a>(vma: *const bindings::vm_area_struct) -> &'= a Self { + // SAFETY: The caller ensures that the invariants are satisfied fo= r the duration of 'a. + unsafe { &*vma.cast() } + } + + /// Returns a raw pointer to this area. + #[inline] + pub fn as_ptr(&self) -> *mut bindings::vm_area_struct { + self.vma.get() + } + + /// Returns the flags associated with the virtual memory area. + /// + /// The possible flags are a combination of the constants in [`flags`]. + #[inline] + pub fn flags(&self) -> vm_flags_t { + // SAFETY: By the type invariants, the caller holds at least the m= map read lock, so this + // access is not a data race. + unsafe { (*self.as_ptr()).__bindgen_anon_2.vm_flags as _ } + } + + /// Returns the start address of the virtual memory area. + #[inline] + pub fn start(&self) -> usize { + // SAFETY: By the type invariants, the caller holds at least the m= map read lock, so this + // access is not a data race. + unsafe { (*self.as_ptr()).__bindgen_anon_1.__bindgen_anon_1.vm_sta= rt as _ } + } + + /// Returns the end address of the virtual memory area. + #[inline] + pub fn end(&self) -> usize { + // SAFETY: By the type invariants, the caller holds at least the m= map read lock, so this + // access is not a data race. + unsafe { (*self.as_ptr()).__bindgen_anon_1.__bindgen_anon_1.vm_end= as _ } + } + + /// Unmap pages in the given page range. + #[inline] + pub fn zap_page_range_single(&self, address: usize, size: usize) { + // SAFETY: By the type invariants, the caller has read access to t= his VMA, which is + // sufficient for this method call. This method has no requirement= s on the vma flags. Any + // value of `address` and `size` is allowed. + unsafe { + bindings::zap_page_range_single( + self.as_ptr(), + address as _, + size as _, + core::ptr::null_mut(), + ) + }; + } +} + +/// The integer type used for vma flags. +#[doc(inline)] +pub use bindings::vm_flags_t; + +/// All possible flags for [`VmAreaRef`]. +pub mod flags { + use super::vm_flags_t; + use crate::bindings; + + /// No flags are set. + pub const NONE: vm_flags_t =3D bindings::VM_NONE as _; + + /// Mapping allows reads. + pub const READ: vm_flags_t =3D bindings::VM_READ as _; + + /// Mapping allows writes. + pub const WRITE: vm_flags_t =3D bindings::VM_WRITE as _; + + /// Mapping allows execution. + pub const EXEC: vm_flags_t =3D bindings::VM_EXEC as _; + + /// Mapping is shared. + pub const SHARED: vm_flags_t =3D bindings::VM_SHARED as _; + + /// Mapping may be updated to allow reads. + pub const MAYREAD: vm_flags_t =3D bindings::VM_MAYREAD as _; + + /// Mapping may be updated to allow writes. + pub const MAYWRITE: vm_flags_t =3D bindings::VM_MAYWRITE as _; + + /// Mapping may be updated to allow execution. + pub const MAYEXEC: vm_flags_t =3D bindings::VM_MAYEXEC as _; + + /// Mapping may be updated to be shared. + pub const MAYSHARE: vm_flags_t =3D bindings::VM_MAYSHARE as _; + + /// Page-ranges managed without `struct page`, just pure PFN. + pub const PFNMAP: vm_flags_t =3D bindings::VM_PFNMAP as _; + + /// Memory mapped I/O or similar. + pub const IO: vm_flags_t =3D bindings::VM_IO as _; + + /// Do not copy this vma on fork. + pub const DONTCOPY: vm_flags_t =3D bindings::VM_DONTCOPY as _; + + /// Cannot expand with mremap(). + pub const DONTEXPAND: vm_flags_t =3D bindings::VM_DONTEXPAND as _; + + /// Lock the pages covered when they are faulted in. + pub const LOCKONFAULT: vm_flags_t =3D bindings::VM_LOCKONFAULT as _; + + /// Is a VM accounted object. + pub const ACCOUNT: vm_flags_t =3D bindings::VM_ACCOUNT as _; + + /// should the VM suppress accounting. + pub const NORESERVE: vm_flags_t =3D bindings::VM_NORESERVE as _; + + /// Huge TLB Page VM. + pub const HUGETLB: vm_flags_t =3D bindings::VM_HUGETLB as _; + + /// Synchronous page faults. + pub const SYNC: vm_flags_t =3D bindings::VM_SYNC as _; + + /// Architecture-specific flag. + pub const ARCH_1: vm_flags_t =3D bindings::VM_ARCH_1 as _; + + /// Wipe VMA contents in child.. + pub const WIPEONFORK: vm_flags_t =3D bindings::VM_WIPEONFORK as _; + + /// Do not include in the core dump. + pub const DONTDUMP: vm_flags_t =3D bindings::VM_DONTDUMP as _; + + /// Not soft dirty clean area. + pub const SOFTDIRTY: vm_flags_t =3D bindings::VM_SOFTDIRTY as _; + + /// Can contain `struct page` and pure PFN pages. + pub const MIXEDMAP: vm_flags_t =3D bindings::VM_MIXEDMAP as _; + + /// MADV_HUGEPAGE marked this vma. + pub const HUGEPAGE: vm_flags_t =3D bindings::VM_HUGEPAGE as _; + + /// MADV_NOHUGEPAGE marked this vma. + pub const NOHUGEPAGE: vm_flags_t =3D bindings::VM_NOHUGEPAGE as _; + + /// KSM may merge identical pages. + pub const MERGEABLE: vm_flags_t =3D bindings::VM_MERGEABLE as _; +} --=20 2.47.0.371.ga323438b13-goog From nobody Thu May 14 09:08:01 2026 Received: from mail-wm1-f74.google.com (mail-wm1-f74.google.com [209.85.128.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A90041D6DA5 for ; Wed, 20 Nov 2024 14:56:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114586; cv=none; b=Jpd1tsaiZHhruftoCL2QWg7TCJQ23Bb/gMj56zLWy5616SfuU4kLWr33qAs3rITFAHH51X8NRrFyUHujX7fCl1cLO10iiUVwndZ6z9GwH/lrfUdG7KaUQ7DaVHX6kg8mBcswQZBBXw6VZD8373ieXJZnTewuMXy6daj4zA4sARI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114586; c=relaxed/simple; bh=gZT3Euh+ZEaMLQWKLqbms6nTrYufOG/3Vrmil72vUnw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=UB7+aGTJBgppN7epPiYAwwzcZwlX/51kzM1Bxb4de2lVJ/mHxSwdc+jVO9jL6r283pCn/H+RNVr1IgcZQXzZe0Uk4DwPXHqZ8adIxc2ECwsEooH3oQ9qa7zWWacbvdY0E1Eaq6f1m/655HRcEDlkNHSCwo5KThbBZm0gxfuju9s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=OHXeT6TJ; arc=none smtp.client-ip=209.85.128.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="OHXeT6TJ" Received: by mail-wm1-f74.google.com with SMTP id 5b1f17b1804b1-4316e350d6aso32255325e9.3 for ; Wed, 20 Nov 2024 06:56:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732114583; x=1732719383; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=/SZjxNKVJkWvdCYwLH30w19SxbpLmf+zpgo7doX1isE=; b=OHXeT6TJSiqKNEk320URvAjq7vlSh8fHmUeljlLpecMvEyKiW+HD6cOotxgm3x9pHY aXxLc0K+cZjFksykgDZmeb4RuHXKsnAvrVHQGNSgeTmwyTDugldCWL2o2OhzO9sPtaaX Gfgt1bZmToyBkNadIdGrSQgoOL2Zbq8kIYFaHIv+ExmoVN5cnr7QhH6QkX5e3QTJKGv3 mTYCZfFS/y3u1ECh3w0tviHNQbC1l85cuynumPP58qzYfnPcs8wM7IKaCnXIfEUF0VZe a3otFNpO3GalxHfQcLl07sWR9fjRcXUutBbE5/a4cjvd5j0N9JBcFBbaCQANxy5qlJF1 4SPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732114583; x=1732719383; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=/SZjxNKVJkWvdCYwLH30w19SxbpLmf+zpgo7doX1isE=; b=JmGrvK+9RoseykOeIYuOQFhmZI7wCcrRsLa+5qp2YrODmb36vHPM9xYYdhNwTk7FEt RRwCr6zVri42AEaJi1tcejBGYLTWmTNdv++Xx4olK3CZCTCxZl2/Dxaw3oHv7DZG2xIV mZs/8DFAHoMg7lBMv+JQbm1xC1sqRot8H1DL1T3FiSpGWI+lwlrburRRWF1MT+t/hPAe 3xyfzr5FqliXM7q08MPAWenuHb29LfG3cZs2Hw+pHDZilJA9cfo4kRCm5WA025cLLWVV HVlsX5mKO2m7xMAbF0SytlYwShWpGHVULmSvaK3sAzfN9y1lMwFV5a+6kTXm7y+4q+tR iwDw== X-Forwarded-Encrypted: i=1; AJvYcCWo3bvTaxahkcr1zxVb/lN8SYiFOnQaBcIdJoLH27fXVQvhdYPFE/KU29vwPqb5G3H53C95SJpsI0FWhXE=@vger.kernel.org X-Gm-Message-State: AOJu0Ywgw5CXPNLtvpkEKpszjRw1kcuu2m0NcJNGhfx9gDWfcJI5eOYU FthvyVBu5s4ra3nxNOdU5uF1e7n70pOzafzhpH28h2tw9kFgWFLVFzbE4bNfi6WgEWtJaResyTA 5okDxXLzi4AxDzw== X-Google-Smtp-Source: AGHT+IGmCoJh8WJ6CU35nHCj5+WORiCwN3sPF8aj+A+iomLA9SMFPrHheiwvgUQFi0TxoH+VHwHP38URGnqozCI= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a05:600c:291:b0:430:576d:fa96 with SMTP id 5b1f17b1804b1-4334f030b13mr22415e9.8.1732114582861; Wed, 20 Nov 2024 06:56:22 -0800 (PST) Date: Wed, 20 Nov 2024 14:49:57 +0000 In-Reply-To: <20241120-vma-v8-0-eb31425da66b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241120-vma-v8-0-eb31425da66b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=3530; i=aliceryhl@google.com; h=from:subject:message-id; bh=gZT3Euh+ZEaMLQWKLqbms6nTrYufOG/3Vrmil72vUnw=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnPfiKOwSyo7JZVYh7YZMMMLf6ReyTAFr9kcbzi p/IU6JooYKJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZz34igAKCRAEWL7uWMY5 Rp/hEACkypxgG72GpLru5x4sBEqUUSeMGsryVWgYsYHX2gV20DtgtGdbhI1rzgBZqgt+qeNUxKa +ZqyVHTkBTnPYPLFAr9lPYrudJCUj8BDDafGZb+R3ZEAQm3GgJIj3brJJaWnZ2gcpJ1xte+7JW7 4wXomI/PzSy8EbV4uymi+uJnrbBW4R5lGKnbhLpm+jKGrT+a8UygKm2/leDm6uWVtXcHSnNJGBo hrCEeUQDK4mrPR26HDv9wPPyjMyxEx7c+RdZGUgsqoX+hHs70KkQG4gL1AIaFdKtukvC6rGeo1Y X+TDHMayeCyz/XicGqQlwtFFirz/q38j3ujbouHa1D8Tsnsjc/7Tb852JpeYOMseuqAu0GWjUjX HtnkNoHi27j51fs7YgQ9epYxBO60wsqoM9Expkj8UmYvqm1t0oySIQQd1MU3MkMue17DuL7Jy9b NR3zufrHk5jbpQUFeWV1HfVbUMPFGvVtI3/2gqlKHN7fP7l9s6KJqTMpwVcNE8ygUl4lbHX1o5o 2RnaPaR0WzuP4QRUTJlMWM2Weu0unpvmONfEAW0DwvB1QbnJjalRjlcylwhi6RhZn1ELTX/9/xr qpYh6hRmWsct3nWWD9jBaJqiGAZvEWm1rFG5H9qPHIKjYQPogidLCRRS1NKy/Gu/foPpu3RjHhD uzSBNpYqoDIgXVw== X-Mailer: b4 0.13.0 Message-ID: <20241120-vma-v8-3-eb31425da66b@google.com> Subject: [PATCH v8 3/7] mm: rust: add vm_insert_page From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The vm_insert_page method is only usable on vmas with the VM_MIXEDMAP flag, so we introduce a new type to keep track of such vmas. The approach used in this patch assumes that we will not need to encode many flag combinations in the type. I don't think we need to encode more than VM_MIXEDMAP and VM_PFNMAP as things are now. However, if that becomes necessary, using generic parameters in a single type would scale better as the number of flags increases. Signed-off-by: Alice Ryhl Acked-by: Lorenzo Stoakes (for mm bits) --- rust/kernel/mm/virt.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/rust/kernel/mm/virt.rs b/rust/kernel/mm/virt.rs index 1e755dca46dd..de7f2338810a 100644 --- a/rust/kernel/mm/virt.rs +++ b/rust/kernel/mm/virt.rs @@ -4,7 +4,14 @@ =20 //! Virtual memory. =20 -use crate::{bindings, types::Opaque}; +use crate::{ + bindings, + error::{to_result, Result}, + page::Page, + types::Opaque, +}; + +use core::ops::Deref; =20 /// A wrapper for the kernel's `struct vm_area_struct` with read access. /// @@ -80,6 +87,65 @@ pub fn zap_page_range_single(&self, address: usize, size= : usize) { ) }; } + + /// Check whether the `VM_MIXEDMAP` flag is set. + #[inline] + pub fn check_mixedmap(&self) -> Option<&VmAreaMixedMap> { + if self.flags() & flags::MIXEDMAP !=3D 0 { + // SAFETY: We just checked that `VM_MIXEDMAP` is set. All othe= r requirements are + // satisfied by the type invariants of `VmAreaRef`. + Some(unsafe { VmAreaMixedMap::from_raw(self.as_ptr()) }) + } else { + None + } + } +} + +/// A wrapper for the kernel's `struct vm_area_struct` with read access an= d `VM_MIXEDMAP` set. +/// +/// It represents an area of virtual memory. +/// +/// # Invariants +/// +/// The caller must hold the mmap read lock or the vma read lock. The `VM_= MIXEDMAP` flag must be +/// set. +#[repr(transparent)] +pub struct VmAreaMixedMap { + vma: VmAreaRef, +} + +// Make all `VmAreaRef` methods available on `VmAreaMixedMap`. +impl Deref for VmAreaMixedMap { + type Target =3D VmAreaRef; + + #[inline] + fn deref(&self) -> &VmAreaRef { + &self.vma + } +} + +impl VmAreaMixedMap { + /// Access a virtual memory area given a raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that `vma` is valid for the duration of 'a, an= d that the mmap read lock + /// (or stronger) is held for at least the duration of 'a. The `VM_MIX= EDMAP` flag must be set. + #[inline] + pub unsafe fn from_raw<'a>(vma: *const bindings::vm_area_struct) -> &'= a Self { + // SAFETY: The caller ensures that the invariants are satisfied fo= r the duration of 'a. + unsafe { &*vma.cast() } + } + + /// Maps a single page at the given address within the virtual memory = area. + /// + /// This operation does not take ownership of the page. + #[inline] + pub fn vm_insert_page(&self, address: usize, page: &Page) -> Result { + // SAFETY: The caller has read access and has verified that `VM_MI= XEDMAP` is set. The page + // is order 0. The address is checked on the C side so it can take= any value. + to_result(unsafe { bindings::vm_insert_page(self.as_ptr(), address= as _, page.as_ptr()) }) + } } =20 /// The integer type used for vma flags. --=20 2.47.0.371.ga323438b13-goog From nobody Thu May 14 09:08:01 2026 Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E275F1D7E4E for ; Wed, 20 Nov 2024 14:56:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114589; cv=none; b=IraYDDgFRunVqc6iLeQjE4zHPOuoGbZxKBsMQKQIuuwf7uU/lLA/99NdW9RosFWP5NBqJRxBOH9za+5s8FLSpjw0LLzyuMBTCcFevL77B+YeeNBXWWUxnRUrJkrJXghGCGKFG5++JMTMed+I/4XOISGkBdiQTW+tl3Xt3JFit+c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114589; c=relaxed/simple; bh=B1j9P1BH0bxfU/zafa6FVQxd9ysL+wMPMIqevg6Rsd4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Mn6JQ2+IgLAgIU2RT8Iqok/meGErE/tH0ZpwUtFRbzkU8RHVaCd2cfBA6XYhs+BNFKBpHYuvbEUd7/n0HAOgq9QB7FE1mXkuKUpa5Ryk8jrFK1Uc15A/0hEy8Bb0VYnavgQZ3C6edubIoQo2azlcEJVx9f0mSRyMbHFpKeYVeJo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=lw70bLx9; arc=none smtp.client-ip=209.85.128.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="lw70bLx9" Received: by mail-wm1-f73.google.com with SMTP id 5b1f17b1804b1-4316300bb15so16581315e9.2 for ; Wed, 20 Nov 2024 06:56:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732114585; x=1732719385; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=aoiANS11czrxWVbduQfnhGruCAXv4HeO9pq8nZpI/0M=; b=lw70bLx9BueIGk+NNdHKfZJiCDpTRlqE/Qvjq8nOAdNhHYO3HYKGAqyAER9/Zgz/9X HvcmtH0+7UxZoconMzzHdAXU2zDT5iWzrAqQC0SpSpt/e52V7vqnl4uGgLhYbDaeza11 feONvutOQN5By8iwP7ar4OnuWdm+SzRVTMLLx2tsKoAIaYy2QFrhugZnvcC+Yv/TJ/jd Vr5tnsnYigiCn3dwaxJDboBjc8ZUrCGGlEETxyGOelbabEHw6aUjOPoX/rVfphVfbV6V lhb8EPaBB8RGydlRRiFO9n75JDorw+fXkjI7ulmzQu64LM9TtXhG05ZH7VuHnQub8SBt MzLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732114585; x=1732719385; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=aoiANS11czrxWVbduQfnhGruCAXv4HeO9pq8nZpI/0M=; b=wmtpc4Df8VQN2+tHe9jhdMDBWlJXYLtKoRWTiNy4dVEK7cTt9tnsC6mVPuNyLu4VnZ 2BVBE6OAQSPrZ2+Jt8C6FDKKWRssFA/iSn42eZMXL6ug3hw3cX5EMlsHZbey07VHOebU YE7t6uB4bK1ftYyLmuWCl0jJn9/I6MgB0iKa2QHZ4+tkQQwNWqsrGBAPajzsyXsVhYbp 6F6LaSvSJkqaQQMVlzanfwH3IbFx01HHi9ZXQuwuwkLADJ7cJXIL0UpeZqjOsxNgq/31 D4AicJlfq5bipi3t7pb3qt0DqsXo4BFOdkbe5d9DSgWL4dPXW9sT0T8v8U5377XpwVcA RXog== X-Forwarded-Encrypted: i=1; AJvYcCWlAXtCtThkUEK8Uy6N6hOEQTvBJ5eNoTCSIVogDXh8N2u4orD2UytSBKnApCOCNqLEnFmYtT/KKjUk93g=@vger.kernel.org X-Gm-Message-State: AOJu0Ywxu6CZlM75ffQKldyXXxyxoRSLPg4Y9H3lybBTgEEigC2B7nNC 6MWpFBzbfmdGYYZyFMnpIAa51CqWj8HfdNnOmtEk55cHRIP4cdx2ZFg36Q6BvSoYqOBugfsy5z0 QYVd8i9G0Ucke1Q== X-Google-Smtp-Source: AGHT+IE6KZ4EvG2+AyBS7X0AsuANcRIXcFSazw3+PxVfaxNaYxLQx8x02Y7MetgM2m0JyIIKmjeIwnAHQKtRbjc= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a05:600c:46d0:b0:431:4162:6adf with SMTP id 5b1f17b1804b1-4334890546fmr124315e9.0.1732114585303; Wed, 20 Nov 2024 06:56:25 -0800 (PST) Date: Wed, 20 Nov 2024 14:49:58 +0000 In-Reply-To: <20241120-vma-v8-0-eb31425da66b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241120-vma-v8-0-eb31425da66b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=3357; i=aliceryhl@google.com; h=from:subject:message-id; bh=B1j9P1BH0bxfU/zafa6FVQxd9ysL+wMPMIqevg6Rsd4=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnPfiKB1ELULsXYa5P1N0NhjBWmvy5M6u0nsExs po7gAjq23aJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZz34igAKCRAEWL7uWMY5 RtPwD/kBvIn5klKFHqApPc2S/WCAcomjz5SYvwUslE6FeJGQvZfkTdXTuEoZJq0lsxJmNbs6Hp5 Q9oxbRPey0lnHYyCJQ/nry7A6FNxk3n9Y8GhK4ctlNZr0glylb7YifGxTYNJhuEoFjnoYOvnlfb RZ5yfmziAthnvy/QooPSnoRzSB9L+hyK/vtg+ReOZ06qfImvN6lBFkaAyNklhP/zbjpFSClY2sy vNCOingHCvMKFKWxfGQhiVkonR4nQYVisrQZQRpkq2OJu+V9CMKBsR4tYGX/8bfJKXABOyYKV2X 7cxgf984gDAZfBzM/7VQAret1qyVxQh/R4Pb1Dc4hrXanMJy7Y1yp4nzlP3Q7P0iU6hfY/L01eQ YL6kMdNVuU+FIFSUEIP4qVOlcWZcQ9c+nJANEx1d6x4M7gXDzvusU6N1pBRXaqMS1Ll3aP1CvC5 sfIAd93vWwYZNuZ2yfoIxT/uXDmoVCG04mfKN1RpM8vGzcnonzACkX7DimqwXqGtZZhF/tHSsyu ze2wduW0hjSyD49/eZMEaNrlmxBFaxs9uZqjJUim+WJzRPNbzhgcbtSPUp3iw4RrqTVREicitdr 41uVHMtohgbKannriawy40MiB6pUjr6QUYmB+ljpC2gJ54cbV8uFiZ2Dl2vm7BAEwxR2NRTgesh 2OzPc8WMU/3D7Lg== X-Mailer: b4 0.13.0 Message-ID: <20241120-vma-v8-4-eb31425da66b@google.com> Subject: [PATCH v8 4/7] mm: rust: add lock_vma_under_rcu From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable All of Rust Binder's existing calls to `vm_insert_page` could be optimized to first attempt to use `lock_vma_under_rcu`. This patch provides an abstraction to enable that. Signed-off-by: Alice Ryhl Acked-by: Lorenzo Stoakes (for mm bits) --- rust/helpers/mm.c | 5 +++++ rust/kernel/mm.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 61 insertions(+) diff --git a/rust/helpers/mm.c b/rust/helpers/mm.c index 7b72eb065a3e..81b510c96fd2 100644 --- a/rust/helpers/mm.c +++ b/rust/helpers/mm.c @@ -43,3 +43,8 @@ struct vm_area_struct *rust_helper_vma_lookup(struct mm_s= truct *mm, { return vma_lookup(mm, addr); } + +void rust_helper_vma_end_read(struct vm_area_struct *vma) +{ + vma_end_read(vma); +} diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs index ace8e7d57afe..a15acb546f68 100644 --- a/rust/kernel/mm.rs +++ b/rust/kernel/mm.rs @@ -13,6 +13,7 @@ use core::{ops::Deref, ptr::NonNull}; =20 pub mod virt; +use virt::VmAreaRef; =20 /// A wrapper for the kernel's `struct mm_struct`. /// @@ -170,6 +171,32 @@ pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_st= ruct) -> &'a MmWithUser { unsafe { &*ptr.cast() } } =20 + /// Try to lock the vma read lock under rcu. + /// + /// If this operation fails, the vma may still exist. In that case, yo= u should take the mmap + /// read lock and try to use `vma_lookup` instead. + /// + /// When per-vma locks are disabled, this always returns `None`. + #[inline] + pub fn lock_vma_under_rcu(&self, vma_addr: usize) -> Option> { + #[cfg(CONFIG_PER_VMA_LOCK)] + { + // SAFETY: Calling `bindings::lock_vma_under_rcu` is always ok= ay given an mm where + // `mm_users` is non-zero. + let vma =3D unsafe { bindings::lock_vma_under_rcu(self.as_raw(= ), vma_addr as _) }; + 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 { VmAreaRef::from_raw(vma) }, + _nts: NotThreadSafe, + }); + } + } + + None + } + /// Lock the mmap read lock. #[inline] pub fn mmap_read_lock(&self) -> MmapReadGuard<'_> { @@ -238,3 +265,32 @@ fn drop(&mut self) { 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 VmAreaRef, + // `vma_end_read` must be called on the same thread as where the lock = was taken + _nts: NotThreadSafe, +} + +// Make all `VmAreaRef` methods available on `VmaReadGuard`. +impl Deref for VmaReadGuard<'_> { + type Target =3D VmAreaRef; + + #[inline] + fn deref(&self) -> &VmAreaRef { + 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()) }; + } +} --=20 2.47.0.371.ga323438b13-goog From nobody Thu May 14 09:08:01 2026 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 199621DE4C3 for ; Wed, 20 Nov 2024 14:56:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114590; cv=none; b=mY1O+XXixCVZUj8rTTZQpGaFXoegqS2qMAvf5E1ATXwQxXg8wB7baq5TdhoTFYG7r+kE18wMnjEfmhgTDLxY7uiwY8lv5msLrHV2JyTTbM9sSD5R6CBM6YZEW4MGxenwF93ol3w6M8hmmau4gd6GJOreJcSDivsUOQ8te7El0NA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114590; c=relaxed/simple; bh=zMBEVvavLox9MacZywaW5TO54AiJm41R1sgIdY4Cj4c=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ZxKDwBEWgP8NkK2JbAZY+Z0k1YKB1t+/rf0ONjU0PGKJn1PgXiFYcJ25fvWgI/g+nTmLV45Jh6Lm+Lzi6KHL/AZgRhEFVKGHfyw6SFTq6mhMRz+f9/LI8m+CLVs6Wc8Ku+LXUQWQuZsJmJqDAwGjbgA+EC/ZUd9AA+DT8KqdQ2I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Hqxl74QF; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Hqxl74QF" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-6ee86f21b2cso39539937b3.0 for ; Wed, 20 Nov 2024 06:56:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732114588; x=1732719388; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=B1qhmYZFewino7xIAVBLotqrei4FahWNdMxHocqLM/I=; b=Hqxl74QFh7YYvC4yARol1cTc20A5A09l77FyWn7ngpNU7+SCgwRDf/6J3hp7m7LlY4 CwdF508A4XqqyP0MPgBAAs4BME+McWrrPy0NP9wEf4PNcGhwc4EK2Cq4O/7aw/RpRStC 3vyo9eQ3kKSZ2x5RHHCI+NuMH3MJGjQG6ErNRbkIW1bTgAAEZ3ZKpD9COu4ZtpBWXyRc A4oyy9ldYFPW0ImDx+kd1yjn/2tq6OFt7cchi4dbjHnrWofL4Oj/5hzPgn0Gic7HOlDZ YUZ2x3OR1B4Sf4obTfY7Nop6nTmYOQ4q9lvUFdWiJ5gx0WML9w8MJdFqhgxQSQHkBL1j dspw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732114588; x=1732719388; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=B1qhmYZFewino7xIAVBLotqrei4FahWNdMxHocqLM/I=; b=mP3SAAVqiNfSZZPsHdIlGY4c+5otprwz8+B0G2w1BGxuriH/xBfxQgphzBZHGqLY65 m5eWlMu2lh9VNeopbk3UvZA+OfmKYikQ1AlSnlYx6ZoK7RyLCY3KAqjFboLV2SrpEF0W yLG/N8umQ/FCfDdiwUnvh8SKsmHwZ8FlJtjN/QgMvxKQo3aaWBnRHS0UjGpLS/fBUw/F yhvizvQpJ7NjYwXX+epOUg+pm6CVbq8u9+gBTCC/1FdUsitCeOPFnVmwdp42V8kkfpnv JEsbzJCtG1frDDH6k6jGsp4jP9Vt2ay8NEAx+1cls5SM/6K3mnJaBXqpBSem3P8i9EHv K/Qw== X-Forwarded-Encrypted: i=1; AJvYcCVk/54KaGjvnrFiaxdFgV+CxNiniUW5V+p6HLSl0MSFpeE+MYMJddRfyj4z0eZvPXC6QEI0wDzTTErNLgg=@vger.kernel.org X-Gm-Message-State: AOJu0Yw6AIga61b8Ng/+ZLRuoTF5i+rEIs6RCb7nGdmD8brElCuOE4Mv Wf5INv0tgTtBcBAczRaljdxldCJRkJ102VKJ+mENLm6wGtLQB3HIBXoFzwhRvzxto+HS2OeM41V Eb/w5BgbJ2Pt9kw== X-Google-Smtp-Source: AGHT+IF/fEeF7RZo4n1G/IhIgluwurThfGhJ8HHwALNv+tngK6vv1K4wFovn4nEL5pwq1i5uR+Y80sYHZ33r9Rg= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a25:abee:0:b0:e38:bdf2:17f2 with SMTP id 3f1490d57ef6-e38cb73348emr3963276.10.1732114587698; Wed, 20 Nov 2024 06:56:27 -0800 (PST) Date: Wed, 20 Nov 2024 14:49:59 +0000 In-Reply-To: <20241120-vma-v8-0-eb31425da66b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241120-vma-v8-0-eb31425da66b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=3012; i=aliceryhl@google.com; h=from:subject:message-id; bh=zMBEVvavLox9MacZywaW5TO54AiJm41R1sgIdY4Cj4c=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnPfiLa5bb5Royej/gvacnIe/2ZvajVUxGyAgMa dNsj+onQTmJAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZz34iwAKCRAEWL7uWMY5 RumNEACU95kezGcsO/Br+P6owGa2xELObLK9zCf/u/XtIn3c8FNg85uhnzJziaGAaAd2cYqUpzy RwmIPH+7ZyFBtfJpVKn7NLRLtdVo+klyy9JVT2z6vKZBJr9VJUJSDEG6gC3gRxqE6UgrRlWd2Ys wIWtHMXp4KouQyAZWtSablEJ5spRaujZDuYaA8KD9UICei4ceVZAkgpluSWANS9W7P/465YuKd6 kV+/4zDJVskpsK+bllZ8ONgS6OImPjDavA+ZBLXqGtcpBGVPfVQ71N25J8y0YjUgksmvXzoB6/7 93aKzR2oaK6rWaCZbzQvh1UWQoJZe606PiqvMHGKvngM1Z8RA+d71ce0Cf2n4r1EyHyzAeU6WJL cOW3Ru9xOnLlGfECNblgdzVjOzhFqAuukhuzo54ZhUVmkpCwOdmXRUlOke5rCDEE5cJ5Qqd7Wak tAvR5mkY4rG3zy2C174XQRFs95SBBQmOs4YrEDCXnIUgB6ZB3hVwUmLlU8TJNsnFRxKLa/zgdI5 6cQislthRO7rqBODUOhHBjizlWYGcoFwRkxjjS+nT7oRo8DpxZcCQ2tGV5z9cQbX3QEp1KuxDe4 dGYcwM0fgLH1M09SIqdoGE3bIMWuplVaerFAXZKqKpYgC4by/xXMkwXkE0WGAKavS4c4MVBip4d lLCXPgjMMTYXRCg== X-Mailer: b4 0.13.0 Message-ID: <20241120-vma-v8-5-eb31425da66b@google.com> Subject: [PATCH v8 5/7] mm: rust: add mmput_async support From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Adds an MmWithUserAsync type that uses mmput_async when dropped but is otherwise identical to MmWithUser. This has to be done using a separate type because the thing we are changing is the destructor. Rust Binder needs this to avoid a certain deadlock. See commit 9a9ab0d96362 ("binder: fix race between mmput() and do_exit()") for details. It's also needed in the shrinker to avoid cleaning up the mm in the shrinker's context. Signed-off-by: Alice Ryhl Acked-by: Lorenzo Stoakes (for mm bits) --- rust/kernel/mm.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs index a15acb546f68..f800b6c244cd 100644 --- a/rust/kernel/mm.rs +++ b/rust/kernel/mm.rs @@ -98,6 +98,48 @@ fn deref(&self) -> &Mm { } } =20 +/// A wrapper for the kernel's `struct mm_struct`. +/// +/// This type is identical to `MmWithUser` except that it uses `mmput_asyn= c` when dropping a +/// refcount. This means that the destructor of `ARef` is= safe to call in atomic +/// context. +/// +/// # Invariants +/// +/// Values of this type are always refcounted using `mmget`. The value of = `mm_users` is non-zero. +#[repr(transparent)] +pub struct MmWithUserAsync { + mm: MmWithUser, +} + +// SAFETY: It is safe to call `mmput_async` on another thread than where `= mmget` was called. +unsafe impl Send for MmWithUserAsync {} +// SAFETY: All methods on `MmWithUserAsync` can be called in parallel from= several threads. +unsafe impl Sync for MmWithUserAsync {} + +// SAFETY: By the type invariants, this type is always refcounted. +unsafe impl AlwaysRefCounted for MmWithUserAsync { + fn inc_ref(&self) { + // SAFETY: The pointer is valid since self is a reference. + unsafe { bindings::mmget(self.as_raw()) }; + } + + unsafe fn dec_ref(obj: NonNull) { + // SAFETY: The caller is giving up their refcount. + unsafe { bindings::mmput_async(obj.cast().as_ptr()) }; + } +} + +// Make all `MmWithUser` methods available on `MmWithUserAsync`. +impl Deref for MmWithUserAsync { + type Target =3D MmWithUser; + + #[inline] + fn deref(&self) -> &MmWithUser { + &self.mm + } +} + // These methods are safe to call even if `mm_users` is zero. impl Mm { /// Call `mmgrab` on `current.mm`. @@ -171,6 +213,13 @@ pub unsafe fn from_raw<'a>(ptr: *const bindings::mm_st= ruct) -> &'a MmWithUser { unsafe { &*ptr.cast() } } =20 + /// Use `mmput_async` when dropping this refcount. + #[inline] + pub fn use_mmput_async(me: ARef) -> ARef { + // SAFETY: The layouts and invariants are compatible. + unsafe { ARef::from_raw(ARef::into_raw(me).cast()) } + } + /// Try to lock the vma read lock under rcu. /// /// If this operation fails, the vma may still exist. In that case, yo= u should take the mmap --=20 2.47.0.371.ga323438b13-goog From nobody Thu May 14 09:08:01 2026 Received: from mail-wr1-f74.google.com (mail-wr1-f74.google.com [209.85.221.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 052011DE882 for ; Wed, 20 Nov 2024 14:56:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114593; cv=none; b=TtX7WlL8LgmV5Ei2xmlWIClrnFojTYgeiCrFTpV8wpncZGDxyOdcxXGExAijHpQsGgbetHW5OejQNJ4myENsJg/nuseLBpR7k9xCq+5eVuFzDy7jfmWct4hCJ3frhsbEIq36GUIlUA8PPjJUR7WHWYHZ4VrAWSWJCL+rYkX/shE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114593; c=relaxed/simple; bh=GxeBG0VLgiYY7aoOP2RaPrBmc8r79aoXtEJ4vi7OY7A=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=BosgE8zUFNpsdqmg0nvxt+uTnpUJY2kj23vES8Q2x4oR4tGRIExbv6qJUiG2PDpEYRSG3TdTKZmCe8nIjug8c57kESnNHEN4/+2MNN5wIpWIyQwaXlH6XYBUccvc8cNkYSvvifT9ApnOmuunptPDVyPwC8MKkMOpiPrHJ/VXK5M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=jXHgzK+1; arc=none smtp.client-ip=209.85.221.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="jXHgzK+1" Received: by mail-wr1-f74.google.com with SMTP id ffacd0b85a97d-382440c1f83so511539f8f.1 for ; Wed, 20 Nov 2024 06:56:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732114590; x=1732719390; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=UwChOJ9zAIfe8IedX9D+YlgaCTQORbfAqxOhT4faXfc=; b=jXHgzK+1Ojn0bGoExBGeXSSh/lw5SP1NuDHWyD2dEB2BkkTT1UBEbybBuMgD8TFOMl pfky7K1nTYuj3nJjsDS4wwLBZ1Ty7xsY2+Q8jgmYbzyEw9K0D5gNapOScW04Ss+6y3ks Do8W90Sc7jtXFuR/dJn8Lx2eehQ9pe+lZhRgELpdXlBWTkci8bz5sTl66QRHbuH6BpCU dO1whBJdULMmULw5xqMDzwBr5doe9sAX+qFTBTN9t0f6TBsOTrF6vr3otIzzCt2+KbK9 zLEIdmQb2h5aejyRLsdXSvjR8mQeoItw1LKKdBWDpp25EFDtWbPcdQJhOQdugJgS49WA Ikgw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732114590; x=1732719390; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=UwChOJ9zAIfe8IedX9D+YlgaCTQORbfAqxOhT4faXfc=; b=qNyEVzt3UFLnaHmAcH+t93ZqolQVURoiQFSDJqiykmvptYtooqUXldgvFHs1c7oPjk kI3XK/45A8evihxTGZ4byyoaF2mMD6BGJqxFYfbSZJcBee6QuNPNsp1cwubHbsShjIPt 20nroZRRWeAcqMK0T11wxZuARBh4cDM0QWWUtfwK4RQ1cjlfyXKuMRdIGLzsKrqaGGM0 OoArz5u/+g9HtURL31xy1QLJvcS4e3g8k4yBlZl3hFT0com5X4O0vj+RqQtEM62a2bZd YOdWyADgIitwuI/9sT8IObyZZHkXpd3nfsJly57aGy1jdH0WaJhu8SnTlzw3u9rRL1E+ dTYA== X-Forwarded-Encrypted: i=1; AJvYcCUkdA/hdjegy+XG/GGfdlHLW8nHqr4L43CoEAZE9/vbF1egwQ0OaO/WfcKfvAneTP4T/tophV3MzKGa+N4=@vger.kernel.org X-Gm-Message-State: AOJu0YxbQbrSaWcDtr8EBJYWOGOQyX1qupFCKKrsO0S49VquHwqPhrZX SheZTox4F8v9LXV5GJ7+gsXXHScnjAoNAcmP3WO66qz3uGQ43fmcUU+QipxjUnuZLeEtBzcE7OH vqURJhrAtkIToBg== X-Google-Smtp-Source: AGHT+IHXbdV8HAQ4+Suef2mPnmtDgGLMdzhu1f1M8BZUgtuk+G0K3LivSZuvpPIt1xjcvlwyptBDB6mRFKUQlaU= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a5d:444b:0:b0:382:3b1a:1870 with SMTP id ffacd0b85a97d-382544b5d4bmr1125f8f.2.1732114590361; Wed, 20 Nov 2024 06:56:30 -0800 (PST) Date: Wed, 20 Nov 2024 14:50:00 +0000 In-Reply-To: <20241120-vma-v8-0-eb31425da66b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241120-vma-v8-0-eb31425da66b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=7325; i=aliceryhl@google.com; h=from:subject:message-id; bh=GxeBG0VLgiYY7aoOP2RaPrBmc8r79aoXtEJ4vi7OY7A=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnPfiLpdbSAArUzD356S1Rdhs5xf34Ng/4olKS2 zZLQlqEVN6JAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZz34iwAKCRAEWL7uWMY5 RihJEACjPpazX+vyEm1GGkDxAIjC2Z0e2x4wQhJDGkGfba15BJ7OdktI8JOyxO4017dJv7XCJE2 OK+70me6wb/vPIGBpARjasmBRsFqaWj33HTt1PEH+AHdNRkVxswHxI5VMyAqQptj05zDgBFlLA+ pELHaN5ryoaVBTyMbpNCl5l3L3mMgagvMJupYAsGhl/NuPbLAzrAcTJpklnovug1YMbz2qXblbO kZQq818LxO5ybuOlDxESimOZvwO/0X8dqnBHHB6RSgzsbH2WBwpTUjasTqFEFJAAdcjYwYGRPyy yDGqkIDT4zK+A1mvjaTbYEexaoFbkmVufawcJ+sJlPsyfJOJmaW1zqteMwMUHZTpgHqWaDoU2El 6/Cnz20ExMDZSdITnhC4No7JB2fyu6VSmp2Aor9F7uLIdVIU2DeBjq8dkTovFnTS+TGtrMlSMj/ Ci9+qIFkfEOc1w8OBPZFbg1CVnuL3zWzP5c3Z7E845AFM557AtWKQqKNFglOOn1CXmskiZEPWsM y2lk0A+cmA/1wgD04mcczeJqeAL733Oyea4JeEwhAlod49osPNU5t2OxdO/MUB+wWy7BDcEKpyj /CZlEDcP/JoXoioDlwssN3+EJNhN88t5exP5y3//5S1kP4i1ip5KuZWp9yhkc9cLDxjERVAQHCB eDHl3Ean9iBRSrQ== X-Mailer: b4 0.13.0 Message-ID: <20241120-vma-v8-6-eb31425da66b@google.com> Subject: [PATCH v8 6/7] mm: rust: add VmAreaNew From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable When setting up a new vma in an mmap call, you have a bunch of extra permissions that you normally don't have. This introduces a new VmAreaNew type that is used for this case. To avoid setting invalid flag values, the methods for clearing VM_MAYWRITE and similar involve a check of VM_WRITE, and return an error if VM_WRITE is set. Trying to use `try_clear_maywrite` without checking the return value results in a compilation error because the `Result` type is marked #[must_use]. For now, there's only a method for VM_MIXEDMAP and not VM_PFNMAP. When we add a VM_PFNMAP method, we will need some way to prevent you from setting both VM_MIXEDMAP and VM_PFNMAP on the same vma. Signed-off-by: Alice Ryhl --- rust/kernel/mm/virt.rs | 169 +++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 168 insertions(+), 1 deletion(-) diff --git a/rust/kernel/mm/virt.rs b/rust/kernel/mm/virt.rs index de7f2338810a..22aff8e77854 100644 --- a/rust/kernel/mm/virt.rs +++ b/rust/kernel/mm/virt.rs @@ -6,7 +6,7 @@ =20 use crate::{ bindings, - error::{to_result, Result}, + error::{code::EINVAL, to_result, Result}, page::Page, types::Opaque, }; @@ -148,6 +148,173 @@ pub fn vm_insert_page(&self, address: usize, page: &P= age) -> Result { } } =20 +/// A builder for setting up a vma in an `mmap` call. +/// +/// # Invariants +/// +/// For the duration of 'a, the referenced vma must be undergoing initiali= zation. +pub struct VmAreaNew { + vma: VmAreaRef, +} + +// Make all `VmAreaRef` methods available on `VmAreaNew`. +impl Deref for VmAreaNew { + type Target =3D VmAreaRef; + + #[inline] + fn deref(&self) -> &VmAreaRef { + &self.vma + } +} + +impl VmAreaNew { + /// Access a virtual memory area given a raw pointer. + /// + /// # Safety + /// + /// Callers must ensure that `vma` is undergoing initial vma setup for= the duration of 'a. + #[inline] + pub unsafe fn from_raw<'a>(vma: *const bindings::vm_area_struct) -> &'= a Self { + // SAFETY: The caller ensures that the invariants are satisfied fo= r the duration of 'a. + unsafe { &*vma.cast() } + } + + /// Internal method for updating the vma flags. + /// + /// # Safety + /// + /// This must not be used to set the flags to an invalid value. + #[inline] + unsafe fn update_flags(&self, set: vm_flags_t, unset: vm_flags_t) { + let mut flags =3D self.flags(); + flags |=3D set; + flags &=3D !unset; + + // SAFETY: This is not a data race: the vma is undergoing initial = setup, so it's not yet + // shared. Additionally, `VmAreaNew` is `!Sync`, so it cannot be u= sed to write in parallel. + // The caller promises that this does not set the flags to an inva= lid value. + unsafe { (*self.as_ptr()).__bindgen_anon_2.vm_flags =3D flags }; + } + + /// Set the `VM_MIXEDMAP` flag on this vma. + /// + /// This enables the vma to contain both `struct page` and pure PFN pa= ges. Returns a reference + /// that can be used to call `vm_insert_page` on the vma. + #[inline] + pub fn set_mixedmap(&self) -> &VmAreaMixedMap { + // SAFETY: We don't yet provide a way to set VM_PFNMAP, so this ca= nnot put the flags in an + // invalid state. + unsafe { self.update_flags(flags::MIXEDMAP, 0) }; + + // SAFETY: We just set `VM_MIXEDMAP` on the vma. + unsafe { VmAreaMixedMap::from_raw(self.vma.as_ptr()) } + } + + /// Set the `VM_IO` flag on this vma. + /// + /// This marks the vma as being a memory-mapped I/O region. + #[inline] + pub fn set_io(&self) { + // SAFETY: Setting the VM_IO flag is always okay. + unsafe { self.update_flags(flags::IO, 0) }; + } + + /// Set the `VM_DONTEXPAND` flag on this vma. + /// + /// This prevents the vma from being expanded with `mremap()`. + #[inline] + pub fn set_dontexpand(&self) { + // SAFETY: Setting the VM_DONTEXPAND flag is always okay. + unsafe { self.update_flags(flags::DONTEXPAND, 0) }; + } + + /// Set the `VM_DONTCOPY` flag on this vma. + /// + /// This prevents the vma from being copied on fork. This option is on= ly permanent if `VM_IO` + /// is set. + #[inline] + pub fn set_dontcopy(&self) { + // SAFETY: Setting the VM_DONTCOPY flag is always okay. + unsafe { self.update_flags(flags::DONTCOPY, 0) }; + } + + /// Set the `VM_DONTDUMP` flag on this vma. + /// + /// This prevents the vma from being included in core dumps. This opti= on is only permanent if + /// `VM_IO` is set. + #[inline] + pub fn set_dontdump(&self) { + // SAFETY: Setting the VM_DONTDUMP flag is always okay. + unsafe { self.update_flags(flags::DONTDUMP, 0) }; + } + + /// Returns whether `VM_READ` is set. + /// + /// This flag indicates whether userspace is mapping this vma as reada= ble. + #[inline] + pub fn get_read(&self) -> bool { + (self.flags() & flags::READ) !=3D 0 + } + + /// Try to clear the `VM_MAYREAD` flag, failing if `VM_READ` is set. + /// + /// This flag indicates whether userspace is allowed to make this vma = readable with + /// `mprotect()`. + #[inline] + pub fn try_clear_mayread(&self) -> Result { + if self.get_read() { + return Err(EINVAL); + } + // SAFETY: Clearing `VM_MAYREAD` is okay when `VM_READ` is not set. + unsafe { self.update_flags(0, flags::MAYREAD) }; + Ok(()) + } + + /// Returns whether `VM_WRITE` is set. + /// + /// This flag indicates whether userspace is mapping this vma as writa= ble. + #[inline] + pub fn get_write(&self) -> bool { + (self.flags() & flags::WRITE) !=3D 0 + } + + /// Try to clear the `VM_MAYWRITE` flag, failing if `VM_WRITE` is set. + /// + /// This flag indicates whether userspace is allowed to make this vma = writable with + /// `mprotect()`. + #[inline] + pub fn try_clear_maywrite(&self) -> Result { + if self.get_write() { + return Err(EINVAL); + } + // SAFETY: Clearing `VM_MAYWRITE` is okay when `VM_WRITE` is not s= et. + unsafe { self.update_flags(0, flags::MAYWRITE) }; + Ok(()) + } + + /// Returns whether `VM_EXEC` is set. + /// + /// This flag indicates whether userspace is mapping this vma as execu= table. + #[inline] + pub fn get_exec(&self) -> bool { + (self.flags() & flags::EXEC) !=3D 0 + } + + /// Try to clear the `VM_MAYEXEC` flag, failing if `VM_EXEC` is set. + /// + /// This flag indicates whether userspace is allowed to make this vma = executable with + /// `mprotect()`. + #[inline] + pub fn try_clear_mayexec(&self) -> Result { + if self.get_exec() { + return Err(EINVAL); + } + // SAFETY: Clearing `VM_MAYEXEC` is okay when `VM_EXEC` is not set. + unsafe { self.update_flags(0, flags::MAYEXEC) }; + Ok(()) + } +} + /// The integer type used for vma flags. #[doc(inline)] pub use bindings::vm_flags_t; --=20 2.47.0.371.ga323438b13-goog From nobody Thu May 14 09:08:01 2026 Received: from mail-wr1-f73.google.com (mail-wr1-f73.google.com [209.85.221.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5DCC31DE8AA for ; Wed, 20 Nov 2024 14:56:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114596; cv=none; b=HkNldJBwh57P59fMP+egFQ8w7z2SuE8E/LzR+/yOtN8v7P8f59mLtrWBX5GbZTir4gbLIUB/2wZOtSw4q0Cb9MML84EEOpvSIIdOb7h94K1jA4XBpSPdFgK6XD0XyiIqkWeznHq2lr/cqJQ7k2a67TdSlMv6/M+PHYbqHvqjdMo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732114596; c=relaxed/simple; bh=GSw09bqyA6K1PcCK8gagOT2XwF7uH8Q/0z1wyixcHDs=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=WfSFc68JHUxCkxX1imOn3f8bMlGGpYTR5QYF44ZkXSVOtYNMFw8QKJORyiwBDO7YD5/0uj1Fm3aLsrhevAFoCI0BFx2+pSVC9FRZCgiqUWJmez9flIYvSstpZJ1nxwDhqb8dBTkmRTwzddj+nQShxFd9U6XDtawNJkxI8eg1ick= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=u2FNQqq9; arc=none smtp.client-ip=209.85.221.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--aliceryhl.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="u2FNQqq9" Received: by mail-wr1-f73.google.com with SMTP id ffacd0b85a97d-382412f3e62so2043042f8f.3 for ; Wed, 20 Nov 2024 06:56:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1732114593; x=1732719393; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=aBJMJ0qYrky91mwQ0u5syokhvobq81rvT/hL+9f8jt4=; b=u2FNQqq9bZTA3zzHIX9y/qMMAYIC1agoD2biJiFH/RJh4wDWrLYlK5ncZ5H2R7dJzT HkEzkjqR1U3i7yD9I0rO6/FqZFsOUuT1od8YS4SQAAbzttsZeXIsy2Dwf2qQZY6gHA9a kDo4uJkP8GRzfwqcKzn9OH3ZNSjwSXvaIZYC9qFVdPPP62B2nVfa9VO/YhKHnE5oSi4/ iDTz+4fe6WSfT2yzZFMCBL8eCahI0K+5vzidvaTVnEvDmu6ywiLFmpHjVPTB8bFjZdwS zOuyKNocKhkVsXzp5AFFgJExdJiRHSaW1JEpsXT9caZ6dgyNOAcbDaLddfg1+ix8bfYE qi7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732114593; x=1732719393; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=aBJMJ0qYrky91mwQ0u5syokhvobq81rvT/hL+9f8jt4=; b=dFK66g35SpmyAa2Yz7Tbx+FAPoYxWCRfUDUf2r5IiAs92n45yPgUa0yeO+2rSajgvK 574ZM5o2CnAWHVfMedEiLHSeLDSKMEKXiSxZtk6E3yz9S6FsvvO8TYNHVWckBWlMNLr9 tsSQ9+7XUO8Uka6nuFjJg5UVG+xQHNDwSLrmotjgdGn/I3BBGMYiufQ+2QBIm3OasYiC c7xsFvbN0PpiI07XzuO544hLW3M+knJZMf52LbedJBzkccvGZOcWZvQ8XAQxzcJkgh2J A/Va5LQ5AkCt9YJGrYM8OsrVojHb35/Mox9uJ+YbswKmCkxcoZaJF3CTTQCOpuzomC3L gEyg== X-Forwarded-Encrypted: i=1; AJvYcCXYPAiglszNGJh9ztU++I/h9Kpqebwp/iC/qfRoER7mX33Q6elr2G2SbD9AdHpY5QbPrhQKtoRA7NPSaGg=@vger.kernel.org X-Gm-Message-State: AOJu0YwEr+I8sWwzKLlpICS5T98TJxfhKjxWX6DNm7IeDoACS59eB5zt 98mOEvTlYOhARLrrvitXjoiO8R7eH9CKoBRlIign/Y0YYapC9HNdhTQrfD8fmAsBrk2lALQYhZ9 AKWONPhibD4R+dA== X-Google-Smtp-Source: AGHT+IHg6gC2fHXTfoa8HybdbCejL4Hw2wCXFWVyfLSy/FMj3wKsyFBkjC9iLS8+VOnYGq57+fL7fZy03dC8naI= X-Received: from aliceryhl.c.googlers.com ([fda3:e722:ac3:cc00:68:fe9:ac10:f29e]) (user=aliceryhl job=sendgmr) by 2002:a05:6000:148:b0:382:3745:e843 with SMTP id ffacd0b85a97d-38254a8593dmr859f8f.0.1732114592756; Wed, 20 Nov 2024 06:56:32 -0800 (PST) Date: Wed, 20 Nov 2024 14:50:01 +0000 In-Reply-To: <20241120-vma-v8-0-eb31425da66b@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20241120-vma-v8-0-eb31425da66b@google.com> X-Developer-Key: i=aliceryhl@google.com; a=openpgp; fpr=49F6C1FAA74960F43A5B86A1EE7A392FDE96209F X-Developer-Signature: v=1; a=openpgp-sha256; l=2667; i=aliceryhl@google.com; h=from:subject:message-id; bh=GSw09bqyA6K1PcCK8gagOT2XwF7uH8Q/0z1wyixcHDs=; b=owEBbQKS/ZANAwAKAQRYvu5YxjlGAcsmYgBnPfiM46FQ43oKCfz0YbqQO2Vr66Kdgk66Jo5tx JPUulsyfy+JAjMEAAEKAB0WIQSDkqKUTWQHCvFIvbIEWL7uWMY5RgUCZz34jAAKCRAEWL7uWMY5 RkXqEACEB7yn2mFW0lgsKxYBQ4qe2+54UutRvkGiIwc8wfu0WgQ+1KUd04XtaEmpyHADZ+itLu4 w1PUr+Qf3HccuAeWtsE12ckyvdIacsnpDEl73ajj1jGwJsZwDgM27DJB3Pe9OaB8FTOZAPbaLEZ JOmLqMLXCULYc26n3q9/Yb/FMwV41XYcxFPovNlq16vpbsQ0PTY9A//QKAhhINkxA+HD6etiNf+ bMN7aL4D5wJW9KHNeA+ubufEouX8yDKZF21ft/+ZyGHSs2bL6qlhwG2ZUly0H8wtI6G0XHciaNh xe2agSElixu2sn+THcpulk9QebWT0nAW3alVucVH8TVZPzXB04MQdA1cMzSxg8yHCSlRdWdCtAi jJfO979h+KcrnKE2+KMi6YV1lr9SEcLHt8q12IeUWIZDUD7Bb8JAC9zi5B67xB11hl2HA4kfdZm jo5jJp9K3lAgAmFrxIhr5PhOpPUauxswnhtFQLl40gmlHRUFh6eOngHO/oMoCLRqKY3hRlw8nv2 MIK9KFyNCYT2SFWifeBNJ575bVLcsnE9ESTUpSgsQU1V1SfWI+UENNWsPrxUd+sIY4rYkGrSTn4 1ptpfZuhqYA6ZNOY9B2j2hhTh0rf1jOBrWFkm0AuSio6VJCdcqB3J4dmzMR4zSY6VslhXm/+yV+ q10Bd9/rJyXui7A== X-Mailer: b4 0.13.0 Message-ID: <20241120-vma-v8-7-eb31425da66b@google.com> Subject: [PATCH v8 7/7] rust: miscdevice: add mmap support From: Alice Ryhl To: Miguel Ojeda , Matthew Wilcox , Lorenzo Stoakes , Vlastimil Babka , John Hubbard , "Liam R. Howlett" , Andrew Morton , Greg Kroah-Hartman , Arnd Bergmann , Christian Brauner Cc: Alex Gaynor , Boqun Feng , Gary Guo , "=?utf-8?q?Bj=C3=B6rn_Roy_Baron?=" , Benno Lossin , linux-kernel@vger.kernel.org, linux-mm@kvack.org, rust-for-linux@vger.kernel.org, Alice Ryhl , Andreas Hindborg Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Using the vma support introduced by the previous commit, introduce mmap support for miscdevices. The mmap call is given a vma that is undergoing initial setup, so the VmAreaNew type is used. Signed-off-by: Alice Ryhl Acked-by: Lorenzo Stoakes (for mm bits) --- rust/kernel/miscdevice.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs index 7e2a79b3ae26..4e4b9476e092 100644 --- a/rust/kernel/miscdevice.rs +++ b/rust/kernel/miscdevice.rs @@ -11,6 +11,7 @@ use crate::{ bindings, error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR}, + mm::virt::VmAreaNew, prelude::*, str::CStr, types::{ForeignOwnable, Opaque}, @@ -110,6 +111,11 @@ fn release(device: Self::Ptr) { drop(device); } =20 + /// Handle for mmap. + fn mmap(_device: ::Borrowed<'_>, _vma: &V= mAreaNew) -> Result { + kernel::build_error(VTABLE_DEFAULT_ERROR) + } + /// Handler for ioctls. /// /// The `cmd` argument is usually manipulated using the utilties in [`= kernel::ioctl`]. @@ -156,6 +162,7 @@ impl VtableHelper { const VTABLE: bindings::file_operations =3D bindings::file_operati= ons { open: Some(fops_open::), release: Some(fops_release::), + mmap: maybe_fn(T::HAS_MMAP, fops_mmap::), unlocked_ioctl: maybe_fn(T::HAS_IOCTL, fops_ioctl::), #[cfg(CONFIG_COMPAT)] compat_ioctl: if T::HAS_COMPAT_IOCTL { @@ -216,6 +223,27 @@ impl VtableHelper { 0 } =20 +/// # Safety +/// +/// `file` must be a valid file that is associated with a `MiscDeviceRegis= tration`. +/// `vma` must be a vma that is currently being mmap'ed with this file. +unsafe extern "C" fn fops_mmap( + file: *mut bindings::file, + vma: *mut bindings::vm_area_struct, +) -> c_int { + // SAFETY: The mmap call of a file can access the private data. + let private =3D unsafe { (*file).private_data }; + // SAFETY: Mmap calls can borrow the private data of the file. + let device =3D unsafe { ::borrow(private) }; + // SAFETY: The caller provides a vma that is undergoing initial VMA se= tup. + let area =3D unsafe { VmAreaNew::from_raw(vma) }; + + match T::mmap(device, area) { + Ok(()) =3D> 0, + Err(err) =3D> err.to_errno() as c_int, + } +} + /// # Safety /// /// `file` must be a valid file that is associated with a `MiscDeviceRegis= tration`. --=20 2.47.0.371.ga323438b13-goog