From 5ae65bdcb867555540169ef57876658262a67d87 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Thu, 16 Oct 2025 17:08:14 -0400 Subject: Partially revert "rust: drm: gem: Implement AlwaysRefCounted for all gem objects automatically" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently in order to implement AlwaysRefCounted for gem objects, we use a blanket implementation: unsafe impl AlwaysRefCounted for T { … } While this technically works, it comes with the rather unfortunate downside that attempting to create a similar blanket implementation in any other kernel crate will now fail in a rather confusing way. Using an example from the (not yet upstream) rust DRM KMS bindings, if we were to add: unsafe impl AlwaysRefCounted for T { … } Then the moment that both blanket implementations are present in the same kernel tree, compilation fails with the following: error[E0119]: conflicting implementations of trait `types::AlwaysRefCounted` --> rust/kernel/drm/kms.rs:504:1 | 504 | unsafe impl AlwaysRefCounted for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation | ::: rust/kernel/drm/gem/mod.rs:97:1 | 97 | unsafe impl AlwaysRefCounted for T { | ---------------------------------------------------- first implementation here So, revert these changes for now. The proper fix for this is to introduce a macro for copy/pasting the same implementation of AlwaysRefCounted around. This reverts commit 38cb08c3fcd3f3b1d0225dcec8ae50fab5751549. Signed-off-by: Lyude Paul Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20251016210955.2813186-2-lyude@redhat.com --- rust/kernel/drm/gem/mod.rs | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) (limited to 'rust/kernel') diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index 30c853988b94..20c2769a8c9d 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -55,26 +55,6 @@ pub trait IntoGEMObject: Sized + super::private::Sealed + AlwaysRefCounted { unsafe fn from_raw<'a>(self_ptr: *mut bindings::drm_gem_object) -> &'a Self; } -// SAFETY: All gem objects are refcounted. -unsafe impl AlwaysRefCounted for T { - fn inc_ref(&self) { - // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. - unsafe { bindings::drm_gem_object_get(self.as_raw()) }; - } - - unsafe fn dec_ref(obj: NonNull) { - // SAFETY: We either hold the only refcount on `obj`, or one of many - meaning that no one - // else could possibly hold a mutable reference to `obj` and thus this immutable reference - // is safe. - let obj = unsafe { obj.as_ref() }.as_raw(); - - // SAFETY: - // - The safety requirements guarantee that the refcount is non-zero. - // - We hold no references to `obj` now, making it safe for us to potentially deallocate it. - unsafe { bindings::drm_gem_object_put(obj) }; - } -} - extern "C" fn open_callback( raw_obj: *mut bindings::drm_gem_object, raw_file: *mut bindings::drm_file, @@ -273,6 +253,22 @@ impl Object { } } +// SAFETY: Instances of `Object` are always reference-counted. +unsafe impl crate::types::AlwaysRefCounted for Object { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. + unsafe { bindings::drm_gem_object_get(self.as_raw()) }; + } + + unsafe fn dec_ref(obj: NonNull) { + // SAFETY: `obj` is a valid pointer to an `Object`. + let obj = unsafe { obj.as_ref() }; + + // SAFETY: The safety requirements guarantee that the refcount is non-zero. + unsafe { bindings::drm_gem_object_put(obj.as_raw()) } + } +} + impl super::private::Sealed for Object {} impl Deref for Object { -- cgit From d3917368ebc5cd89d7d08eab4673e5c4c73ff42f Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Tue, 21 Oct 2025 13:21:36 -0400 Subject: rust: drm/gem: Remove Object.dev I noticed by chance that there's actually already a pointer to this in struct drm_gem_object. So, no use in carrying this around! Signed-off-by: Lyude Paul Acked-by: Danilo Krummrich Reviewed-by: Alice Ryhl Link: https://lore.kernel.org/r/20251021172220.252558-1-lyude@redhat.com --- rust/kernel/drm/gem/mod.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'rust/kernel') diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index 20c2769a8c9d..eb5f3feac890 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -167,12 +167,10 @@ impl BaseObject for T {} /// Invariants /// /// - `self.obj` is a valid instance of a `struct drm_gem_object`. -/// - `self.dev` is always a valid pointer to a `struct drm_device`. #[repr(C)] #[pin_data] pub struct Object { obj: Opaque, - dev: NonNull>, #[pin] data: T, } @@ -202,9 +200,6 @@ impl Object { try_pin_init!(Self { obj: Opaque::new(bindings::drm_gem_object::default()), data <- T::new(dev, size), - // INVARIANT: The drm subsystem guarantees that the `struct drm_device` will live - // as long as the GEM object lives. - dev: dev.into(), }), GFP_KERNEL, )?; @@ -227,9 +222,13 @@ impl Object { /// Returns the `Device` that owns this GEM object. pub fn dev(&self) -> &drm::Device { - // SAFETY: The DRM subsystem guarantees that the `struct drm_device` will live as long as - // the GEM object lives, hence the pointer must be valid. - unsafe { self.dev.as_ref() } + // SAFETY: + // - `struct drm_gem_object.dev` is initialized and valid for as long as the GEM + // object lives. + // - The device we used for creating the gem object is passed as &drm::Device to + // Object::::new(), so we know that `T::Driver` is the right generic parameter to use + // here. + unsafe { drm::Device::from_raw((*self.as_raw()).dev) } } fn as_raw(&self) -> *mut bindings::drm_gem_object { -- cgit From e4ead68a390511384d6af7bc9d00835dd6185e3b Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Wed, 29 Oct 2025 00:07:36 +0900 Subject: rust: transmute: add `from_bytes_prefix` family of methods The `from_bytes*` family of functions expect a slice of the exact same size as the requested type. This can be sometimes cumbersome for callers that deal with dynamic stream of data that needs to be manually cut before each invocation of `from_bytes`. To simplify such callers, introduce a new `from_bytes*_prefix` family of methods, which split the input slice at the index required for the equivalent `from_bytes` method to succeed, and return its result alongside with the remainder of the slice. This design is inspired by zerocopy's `try_*_from_prefix` family of methods. Reviewed-by: Joel Fernandes Reviewed-by: Danilo Krummrich Reviewed-by: Alice Ryhl Acked-by: Danilo Krummrich Signed-off-by: Alexandre Courbot Message-ID: <20251029-nova-vbios-frombytes-v1-1-ac441ebc1de3@nvidia.com> Message-ID: <20251101-b4-frombytes-prefix-v1-1-0d9c1fd63b34@nvidia.com> --- rust/kernel/transmute.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'rust/kernel') diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs index cfc37d81adf2..be5dbf3829e2 100644 --- a/rust/kernel/transmute.rs +++ b/rust/kernel/transmute.rs @@ -58,6 +58,27 @@ pub unsafe trait FromBytes { } } + /// Converts the beginning of `bytes` to a reference to `Self`. + /// + /// This method is similar to [`Self::from_bytes`], with the difference that `bytes` does not + /// need to be the same size of `Self` - the appropriate portion is cut from the beginning of + /// `bytes`, and the remainder returned alongside `Self`. + fn from_bytes_prefix(bytes: &[u8]) -> Option<(&Self, &[u8])> + where + Self: Sized, + { + if bytes.len() < size_of::() { + None + } else { + // PANIC: We checked that `bytes.len() >= size_of::`, thus `split_at` cannot + // panic. + // TODO: replace with `split_at_checked` once the MSRV is >= 1.80. + let (prefix, remainder) = bytes.split_at(size_of::()); + + Self::from_bytes(prefix).map(|s| (s, remainder)) + } + } + /// Converts a mutable slice of bytes to a reference to `Self`. /// /// Succeeds if the reference is properly aligned, and the size of `bytes` is equal to that of @@ -80,6 +101,27 @@ pub unsafe trait FromBytes { } } + /// Converts the beginning of `bytes` to a mutable reference to `Self`. + /// + /// This method is similar to [`Self::from_bytes_mut`], with the difference that `bytes` does + /// not need to be the same size of `Self` - the appropriate portion is cut from the beginning + /// of `bytes`, and the remainder returned alongside `Self`. + fn from_bytes_mut_prefix(bytes: &mut [u8]) -> Option<(&mut Self, &mut [u8])> + where + Self: AsBytes + Sized, + { + if bytes.len() < size_of::() { + None + } else { + // PANIC: We checked that `bytes.len() >= size_of::`, thus `split_at_mut` cannot + // panic. + // TODO: replace with `split_at_mut_checked` once the MSRV is >= 1.80. + let (prefix, remainder) = bytes.split_at_mut(size_of::()); + + Self::from_bytes_mut(prefix).map(|s| (s, remainder)) + } + } + /// Creates an owned instance of `Self` by copying `bytes`. /// /// Unlike [`FromBytes::from_bytes`], which requires aligned input, this method can be used on @@ -97,6 +139,27 @@ pub unsafe trait FromBytes { None } } + + /// Creates an owned instance of `Self` from the beginning of `bytes`. + /// + /// This method is similar to [`Self::from_bytes_copy`], with the difference that `bytes` does + /// not need to be the same size of `Self` - the appropriate portion is cut from the beginning + /// of `bytes`, and the remainder returned alongside `Self`. + fn from_bytes_copy_prefix(bytes: &[u8]) -> Option<(Self, &[u8])> + where + Self: Sized, + { + if bytes.len() < size_of::() { + None + } else { + // PANIC: We checked that `bytes.len() >= size_of::`, thus `split_at` cannot + // panic. + // TODO: replace with `split_at_checked` once the MSRV is >= 1.80. + let (prefix, remainder) = bytes.split_at(size_of::()); + + Self::from_bytes_copy(prefix).map(|s| (s, remainder)) + } + } } macro_rules! impl_frombytes { -- cgit From e54ad0cd3673c93cdafda58505eaa81610fe3aef Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Fri, 7 Nov 2025 15:25:56 -0500 Subject: rust/drm/gem: Fix missing header in `Object` rustdoc Invariants should be prefixed with a # to turn it into a header. There are no functional changes in this patch. Cc: stable@vger.kernel.org Fixes: c284d3e42338 ("rust: drm: gem: Add GEM object abstraction") Signed-off-by: Lyude Paul Link: https://patch.msgid.link/20251107202603.465932-1-lyude@redhat.com Signed-off-by: Alice Ryhl --- rust/kernel/drm/gem/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'rust/kernel') diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs index eb5f3feac890..a7f682e95c01 100644 --- a/rust/kernel/drm/gem/mod.rs +++ b/rust/kernel/drm/gem/mod.rs @@ -164,7 +164,7 @@ impl BaseObject for T {} /// A base GEM object. /// -/// Invariants +/// # Invariants /// /// - `self.obj` is a valid instance of a `struct drm_gem_object`. #[repr(C)] -- cgit From 88622323dde3d9d6efd6f2efcfaa0bced5af94c3 Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Mon, 10 Nov 2025 22:34:16 +0900 Subject: rust: enable slice_flatten feature and provide it through an extension trait In Rust 1.80, the previously unstable `slice::flatten` family of methods have been stabilized and renamed to `slice::as_flattened`. This creates an issue as we want to use `as_flattened`, but need to support the MSRV (which at the moment is Rust 1.78) where it is named `flatten`. Solve this by enabling the `slice_flatten` feature, and providing an `as_flattened` implementation through an extension trait for compiler versions where it is not available. The trait is then exported from the prelude, making the `as_flattened` family of methods transparently available for all supported compiler versions. This extension trait can be removed once the MSRV passes 1.80. Suggested-by: Miguel Ojeda Link: https://lore.kernel.org/all/CANiq72kK4pG=O35NwxPNoTO17oRcg1yfGcvr3==Fi4edr+sfmw@mail.gmail.com/ Acked-by: Danilo Krummrich Acked-by: Miguel Ojeda Reviewed-by: Alice Ryhl Signed-off-by: Alexandre Courbot Message-ID: <20251110-gsp_boot-v9-8-8ae4058e3c0e@nvidia.com> Message-ID: <20251104-b4-as-flattened-v3-1-6cb9c26b45cd@nvidia.com> --- rust/kernel/lib.rs | 4 ++++ rust/kernel/prelude.rs | 3 +++ rust/kernel/slice.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 rust/kernel/slice.rs (limited to 'rust/kernel') diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 3dd7bebe7888..2581a356d114 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -21,6 +21,9 @@ #![feature(inline_const)] #![feature(pointer_is_aligned)] // +// Stable since Rust 1.80.0. +#![feature(slice_flatten)] +// // Stable since Rust 1.81.0. #![feature(lint_reasons)] // @@ -128,6 +131,7 @@ pub mod scatterlist; pub mod security; pub mod seq_file; pub mod sizes; +pub mod slice; mod static_assert; #[doc(hidden)] pub mod std_vendor; diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs index 198d09a31449..9ee8acc563de 100644 --- a/rust/kernel/prelude.rs +++ b/rust/kernel/prelude.rs @@ -51,3 +51,6 @@ pub use super::init::InPlaceInit; pub use super::current; pub use super::uaccess::UserPtr; + +#[cfg(not(CONFIG_RUSTC_HAS_SLICE_AS_FLATTENED))] +pub use super::slice::AsFlattened; diff --git a/rust/kernel/slice.rs b/rust/kernel/slice.rs new file mode 100644 index 000000000000..6ca91a4fd1f2 --- /dev/null +++ b/rust/kernel/slice.rs @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Additional (and temporary) slice helpers. + +/// Extension trait providing a portable version of [`as_flattened`] and +/// [`as_flattened_mut`]. +/// +/// In Rust 1.80, the previously unstable `slice::flatten` family of methods +/// have been stabilized and renamed from `flatten` to `as_flattened`. +/// +/// This creates an issue for as long as the MSRV is < 1.80, as the same functionality is provided +/// by different methods depending on the compiler version. +/// +/// This extension trait solves this by abstracting `as_flatten` and calling the correct method +/// depending on the Rust version. +/// +/// This trait can be removed once the MSRV passes 1.80. +/// +/// [`as_flattened`]: slice::as_flattened +/// [`as_flattened_mut`]: slice::as_flattened_mut +#[cfg(not(CONFIG_RUSTC_HAS_SLICE_AS_FLATTENED))] +pub trait AsFlattened { + /// Takes a `&[[T; N]]` and flattens it to a `&[T]`. + /// + /// This is an portable layer on top of [`as_flattened`]; see its documentation for details. + /// + /// [`as_flattened`]: slice::as_flattened + fn as_flattened(&self) -> &[T]; + + /// Takes a `&mut [[T; N]]` and flattens it to a `&mut [T]`. + /// + /// This is an portable layer on top of [`as_flattened_mut`]; see its documentation for details. + /// + /// [`as_flattened_mut`]: slice::as_flattened_mut + fn as_flattened_mut(&mut self) -> &mut [T]; +} + +#[cfg(not(CONFIG_RUSTC_HAS_SLICE_AS_FLATTENED))] +impl AsFlattened for [[T; N]] { + #[allow(clippy::incompatible_msrv)] + fn as_flattened(&self) -> &[T] { + self.flatten() + } + + #[allow(clippy::incompatible_msrv)] + fn as_flattened_mut(&mut self) -> &mut [T] { + self.flatten_mut() + } +} -- cgit From 57dc2ea0b7bdb828c5d966d9135c28fe854933a4 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Wed, 19 Nov 2025 19:51:25 +0100 Subject: rust: slice: fix broken intra-doc links In older versions of Rust, the compiler doesn't know about the newer `as_flattened*` methods, thus `rustdoc` complains about the intra-doc links, e.g. error: unresolved link to `slice::as_flattened` --> rust/kernel/slice.rs:19:23 | 19 | /// [`as_flattened`]: slice::as_flattened | ^^^^^^^^^^^^^^^^^^^ the primitive type `slice` has no associated item named `as_flattened` | = note: `-D rustdoc::broken-intra-doc-links` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(rustdoc::broken_intra_doc_links)]` Thus fix them by using an URL instead. Fixes: 88622323dde3 ("rust: enable slice_flatten feature and provide it through an extension trait") Signed-off-by: Miguel Ojeda Reviewed-by: Alexandre Courbot Reviewed-by: Alice Ryhl Link: https://patch.msgid.link/20251119185125.1411151-1-ojeda@kernel.org Signed-off-by: Alice Ryhl --- rust/kernel/slice.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'rust/kernel') diff --git a/rust/kernel/slice.rs b/rust/kernel/slice.rs index 6ca91a4fd1f2..ca2cde135061 100644 --- a/rust/kernel/slice.rs +++ b/rust/kernel/slice.rs @@ -16,22 +16,22 @@ /// /// This trait can be removed once the MSRV passes 1.80. /// -/// [`as_flattened`]: slice::as_flattened -/// [`as_flattened_mut`]: slice::as_flattened_mut +/// [`as_flattened`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_flattened +/// [`as_flattened_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_flattened_mut #[cfg(not(CONFIG_RUSTC_HAS_SLICE_AS_FLATTENED))] pub trait AsFlattened { /// Takes a `&[[T; N]]` and flattens it to a `&[T]`. /// /// This is an portable layer on top of [`as_flattened`]; see its documentation for details. /// - /// [`as_flattened`]: slice::as_flattened + /// [`as_flattened`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_flattened fn as_flattened(&self) -> &[T]; /// Takes a `&mut [[T; N]]` and flattens it to a `&mut [T]`. /// /// This is an portable layer on top of [`as_flattened_mut`]; see its documentation for details. /// - /// [`as_flattened_mut`]: slice::as_flattened_mut + /// [`as_flattened_mut`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_flattened_mut fn as_flattened_mut(&mut self) -> &mut [T]; } -- cgit