From 5a78977262f47dd52a4880689a2ca3d21dbf149a Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Fri, 16 May 2025 19:32:19 +0000 Subject: mm: rust: make CONFIG_MMU ifdefs more narrow Currently the entire kernel::mm module is ifdef'd out when CONFIG_MMU=n. However, there are some downstream users of the module in rust/kernel/task.rs and rust/kernel/miscdevice.rs. Thus, update the cfgs so that only MmWithUserAsync is removed with CONFIG_MMU=n. The code is moved into a new file, since the #[cfg()] annotation otherwise has to be duplicated several times. Link: https://lkml.kernel.org/r/20250516193219.2987032-1-aliceryhl@google.com Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202505071753.kldNHYVQ-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202505072116.eSYC8igT-lkp@intel.com/ Fixes: 5bb9ed6cdfeb ("mm: rust: add abstraction for struct mm_struct") Signed-off-by: Alice Ryhl Reviewed-by: Boqun Feng Cc: Boqun Feng Cc: Liam Howlett Cc: Lorenzo Stoakes Signed-off-by: Andrew Morton --- rust/kernel/mm.rs | 56 +++-------------------------------- rust/kernel/mm/mmput_async.rs | 68 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 52 deletions(-) create mode 100644 rust/kernel/mm/mmput_async.rs (limited to 'rust') diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs index 615907a0f3b4..43f525c0d16c 100644 --- a/rust/kernel/mm.rs +++ b/rust/kernel/mm.rs @@ -10,7 +10,6 @@ //! control what happens when userspace reads or writes to that region of memory. //! //! C header: [`include/linux/mm.h`](srctree/include/linux/mm.h) -#![cfg(CONFIG_MMU)] use crate::{ bindings, @@ -21,6 +20,10 @@ 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` @@ -111,50 +114,6 @@ impl Deref for MmWithUser { } } -/// A wrapper for the kernel's `struct mm_struct`. -/// -/// This type is identical to `MmWithUser` except that it uses `mmput_async` 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 { - #[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_async(obj.cast().as_ptr()) }; - } -} - -// Make all `MmWithUser` methods available on `MmWithUserAsync`. -impl Deref for MmWithUserAsync { - type Target = MmWithUser; - - #[inline] - fn deref(&self) -> &MmWithUser { - &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`. @@ -206,13 +165,6 @@ impl MmWithUser { unsafe { &*ptr.cast() } } - /// Use `mmput_async` when dropping this refcount. - #[inline] - pub fn into_mmput_async(me: ARef) -> ARef { - // SAFETY: The layouts and invariants are compatible. - unsafe { ARef::from_raw(ARef::into_raw(me).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 diff --git a/rust/kernel/mm/mmput_async.rs b/rust/kernel/mm/mmput_async.rs new file mode 100644 index 000000000000..9289e05f7a67 --- /dev/null +++ b/rust/kernel/mm/mmput_async.rs @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 + +// Copyright (C) 2024 Google LLC. + +//! Version of `MmWithUser` using `mmput_async`. +//! +//! This is a separate file from `mm.rs` due to the dependency on `CONFIG_MMU=y`. +#![cfg(CONFIG_MMU)] + +use crate::{ + bindings, + mm::MmWithUser, + types::{ARef, AlwaysRefCounted}, +}; +use core::{ops::Deref, ptr::NonNull}; + +/// A wrapper for the kernel's `struct mm_struct`. +/// +/// This type is identical to `MmWithUser` except that it uses `mmput_async` 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 { + #[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_async(obj.cast().as_ptr()) }; + } +} + +// Make all `MmWithUser` methods available on `MmWithUserAsync`. +impl Deref for MmWithUserAsync { + type Target = MmWithUser; + + #[inline] + fn deref(&self) -> &MmWithUser { + &self.mm + } +} + +impl MmWithUser { + /// Use `mmput_async` when dropping this refcount. + #[inline] + pub fn into_mmput_async(me: ARef) -> ARef { + // SAFETY: The layouts and invariants are compatible. + unsafe { ARef::from_raw(ARef::into_raw(me).cast()) } + } +} -- cgit v1.2.3 From 3bf67171e98272c918a41b899070e6e86741adc8 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Thu, 1 May 2025 12:16:16 +0000 Subject: kcov: rust: add flags for KCOV with Rust MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rust code is currently not instrumented properly when KCOV is enabled. Thus, add the relevant flags to perform instrumentation correctly. This is necessary for efficient fuzzing of Rust code. The sanitizer-coverage features of LLVM have existed for long enough that they are available on any LLVM version supported by rustc, so we do not need any Kconfig feature detection. The coverage level is set to 3, as that is the level needed by trace-pc. We do not instrument `core` since when we fuzz the kernel, we are looking for bugs in the kernel, not the Rust stdlib. Link: https://lkml.kernel.org/r/20250501-rust-kcov-v2-1-b71e83e9779f@google.com Signed-off-by: Alice Ryhl Co-developed-by: Matthew Maurer Signed-off-by: Matthew Maurer Reviewed-by: Alexander Potapenko Tested-by: Aleksandr Nogikh Acked-by: Miguel Ojeda Cc: Andreas Hindborg Cc: Andrey Konovalov Cc: Benno Lossin Cc: Bill Wendling Cc: Björn Roy Baron Cc: Boqun Feng Cc: Danilo Krummrich Cc: Dmitriy Vyukov Cc: Gary Guo Cc: Justin Stitt Cc: Masahiro Yamada Cc: Nathan Chancellor Cc: Trevor Gross Signed-off-by: Andrew Morton --- rust/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'rust') diff --git a/rust/Makefile b/rust/Makefile index 3aca903a7d08..80c84749d734 100644 --- a/rust/Makefile +++ b/rust/Makefile @@ -492,6 +492,7 @@ $(obj)/core.o: $(RUST_LIB_SRC)/core/src/lib.rs \ ifneq ($(or $(CONFIG_X86_64),$(CONFIG_X86_32)),) $(obj)/core.o: scripts/target.json endif +KCOV_INSTRUMENT_core.o := n $(obj)/compiler_builtins.o: private skip_gendwarfksyms = 1 $(obj)/compiler_builtins.o: private rustc_objcopy = -w -W '__*' -- cgit v1.2.3