Skip to contentSkip to conversation

Alloc and drm::Device fixes

PATCH Applied Danilo Krummrich 4 participants 22 messages Jul 31, 2025 – Aug 16, 2025

Subsystems (4)
lore
Share & tools
lore

Danilo Krummrich

author maintainer
#0 lore raw

cover Alloc and drm::Device fixes

This patch series replaces aligned_size() with Kmalloc::aligned_layout(), which is subsequently used to obtain a kmalloc() compatible Layout for __drm_dev_alloc() in drm::Device::new().

It also contains two additional drm::Device fixes; the commits are based on next-20250731.

Danilo Krummrich (4):
rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()
rust: drm: ensure kmalloc() compatible Layout
rust: drm: remove pin annotations from drm::Device
rust: drm: don't pass the address of drm::Device to drm_dev_put()

 rust/kernel/alloc/allocator.rs | 30 ++++++++++++++++++------------
 rust/kernel/drm/device.rs      | 32 +++++++++++++++++++++++++-------
 2 files changed, 43 insertions(+), 19 deletions(-)

base-commit: 84b92a499e7eca54ba1df6f6c6e01766025943f1

Signature · 1 line
2.50.0
author maintainer
#1 lore raw

PATCH 1/4 rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()

aligned_size() dates back to when Rust did support kmalloc() only, but is now used in ReallocFunc::call() and hence for all allocators.

However, the additional padding applied by aligned_size() is only required by the kmalloc() allocator backend.

Hence, replace aligned_size() with Kmalloc::aligned_layout() and use it for the affected allocators, i.e. kmalloc() and kvmalloc(), only.

While at it, make Kmalloc::aligned_layout() public, such that Rust abstractions, which have to call subsystem specific kmalloc() based allocation primitives directly, can make use of it.

Fixes 8a799831fc63 ("rust: alloc: implement `ReallocFunc`")
---
 rust/kernel/alloc/allocator.rs | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)
rust/kernel/alloc/allocator.rs +18 -12
index aa2dfa9dca4c..3331ef338f3b 100644
@@ -43,17 +43,6 @@
 /// For more details see [self].
 pub struct KVmalloc;
 
-/// Returns a proper size to alloc a new object aligned to `new_layout`'s alignment.
-fn aligned_size(new_layout: Layout) -> usize {
-    // Customized layouts from `Layout::from_size_align()` can have size < align, so pad first.
-    let layout = new_layout.pad_to_align();
-
-    // Note that `layout.size()` (after padding) is guaranteed to be a multiple of `layout.align()`
-    // which together with the slab guarantees means the `krealloc` will return a properly aligned
-    // object (see comments in `kmalloc()` for more information).
-    layout.size()
-}
-
 /// # Invariants
 ///
 /// One of the following: `krealloc`, `vrealloc`, `kvrealloc`.
@@ -88,7 +77,7 @@ unsafe fn call(
         old_layout: Layout,
         flags: Flags,
     ) -> Result<NonNull<[u8]>, AllocError> {
-        let size = aligned_size(layout);
+        let size = layout.size();
         let ptr = match ptr {
             Some(ptr) => {
                 if old_layout.size() == 0 {
@@ -123,6 +112,17 @@ unsafe fn call(
     }
 }
 
+impl Kmalloc {
+    /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of
+    /// `layout`.
+    pub const fn aligned_layout(layout: Layout) -> Layout {
+        // Note that `layout.size()` (after padding) is guaranteed to be a multiple of
+        // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return
+        // a properly aligned object (see comments in `kmalloc()` for more information).
+        layout.pad_to_align()
+    }
+}
+
 // SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees that
 // - memory remains valid until it is explicitly freed,
 // - passing a pointer to a valid memory allocation is OK,
@@ -135,6 +135,8 @@ unsafe fn realloc(
         old_layout: Layout,
         flags: Flags,
     ) -> Result<NonNull<[u8]>, AllocError> {
+        let layout = Kmalloc::aligned_layout(layout);
+
         // SAFETY: `ReallocFunc::call` has the same safety requirements as `Allocator::realloc`.
         unsafe { ReallocFunc::KREALLOC.call(ptr, layout, old_layout, flags) }
     }
@@ -176,6 +178,10 @@ unsafe fn realloc(
         old_layout: Layout,
         flags: Flags,
     ) -> Result<NonNull<[u8]>, AllocError> {
+        // `KVmalloc` may use the `Kmalloc` backend, hence we have to enforce a `Kmalloc`
+        // compatible layout.
+        let layout = Kmalloc::aligned_layout(layout);
+
         // TODO: Support alignments larger than PAGE_SIZE.
         if layout.align() > bindings::PAGE_SIZE {
             pr_warn!("KVmalloc does not support alignments larger than PAGE_SIZE yet.\n");
Signature · 1 line
2.50.0
maintainer Reviewed-by on v1 1/4
#2 lore raw

Re: [PATCH 1/4] rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()

Quoted 9 lines · Danilo Krummrich

aligned_size() dates back to when Rust did support kmalloc() only, but is now used in ReallocFunc::call() and hence for all allocators.

However, the additional padding applied by aligned_size() is only required by the kmalloc() allocator backend.

Hence, replace aligned_size() with Kmalloc::aligned_layout() and use it for the affected allocators, i.e. kmalloc() and kvmalloc(), only.

Quoted 6 lines

While at it, make Kmalloc::aligned_layout() public, such that Rust abstractions, which have to call subsystem specific kmalloc() based allocation primitives directly, can make use of it.

Fixes 8a799831fc63 ("rust: alloc: implement `ReallocFunc`")

I guess vmalloc handles alignment in a different way ... ok makes sense to me.

#3 lore raw

Re: [PATCH 1/4] rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()

In reply to Danilo Krummrich
Quoted 10 lines · Danilo Krummrich

aligned_size() dates back to when Rust did support kmalloc() only, but is now used in ReallocFunc::call() and hence for all allocators.

However, the additional padding applied by aligned_size() is only required by the kmalloc() allocator backend.

Hence, replace aligned_size() with Kmalloc::aligned_layout() and use it for the affected allocators, i.e. kmalloc() and kvmalloc(), only.

Quoted 6 lines

While at it, make Kmalloc::aligned_layout() public, such that Rust abstractions, which have to call subsystem specific kmalloc() based allocation primitives directly, can make use of it.

Fixes 8a799831fc63 ("rust: alloc: implement `ReallocFunc`")

Did this need Cc: stable or was it skipped since it is just extra padding?

(i.e. not sure what you usually do for DRM, but I was looking at this since it is alloc since I would normally pick it.)

Thanks!

Cheers,
Miguel

author maintainer
#4 lore raw

Re: [PATCH 1/4] rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()

Quoted 1 line · Miguel Ojeda

Did this need Cc: stable or was it skipped since it is just extra padding?

I don't think so, it just lead to pad to the alignment for Vmalloc too.

Technically, this makes no difference, since Vmalloc is always PAGE_SIZE aligned and the size always a multiple of PAGE_SIZE.

However, the patch is a prerequisite for the DRM device fix in patch 2.

- Danilo

#5 lore raw

Re: [PATCH 1/4] rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()

Quoted 5 lines · Danilo Krummrich

I don't think so, it just lead to pad to the alignment for Vmalloc too.

Technically, this makes no difference, since Vmalloc is always PAGE_SIZE aligned and the size always a multiple of PAGE_SIZE.

Got it, thanks for the quick reply! Then I guess we could have skipped the Fixes in this one, but it is not a big deal and as usual it depends on how one defines "fix".

Cheers,
Miguel

author maintainer
#6 lore raw

Re: [PATCH 1/4] rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()

Quoted 10 lines · Miguel Ojeda
Quoted 5 lines · Danilo Krummrich

I don't think so, it just lead to pad to the alignment for Vmalloc too.

Technically, this makes no difference, since Vmalloc is always PAGE_SIZE aligned and the size always a multiple of PAGE_SIZE.

Got it, thanks for the quick reply! Then I guess we could have skipped the Fixes in this one, but it is not a big deal and as usual it depends on how one defines "fix".

Yeah, in the past I was more on the "'Fixes:' for actual bugs only" side of things, but I changed my mind a bit; I find it useful to have this as a reference even for minor issues that might not be actual bugs, such as this one.

#7 lore raw

Re: [PATCH 1/4] rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()

In reply to Danilo Krummrich

Review

Quoted 5 lines · Danilo Krummrich
(quoted diff) +4 -0
+impl Kmalloc {
+    /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of
+    /// `layout`.
+    pub const fn aligned_layout(layout: Layout) -> Layout {

I think this const fn here was removed when applying to make it work with older compilers, right?

I was fixing another rusttest thing and noticed while applying these. I had a patch to fix it, since we can actually just use the feature, and then I noticed it wasn't in the tree. Since I have it, I am attaching it for reference in case the now-stable feature is needed, e.g. if you want to make that const fn again.

Cheers,
Miguel

From 3cf24f05614e33493ba086bab1f02f701c894807 Mon Sep 17 00:00:00 2001
From: Miguel Ojeda <[email protected]>
Date: Sat, 16 Aug 2025 22:20:29 +0200
Subject: [NOT PATCH] rust: kernel: use const_alloc_layout feature to fix Rust
< 1.85 builds

Before Rust 1.85.0 (released 2025-02-20), pad_to_align was not available in const contexts:

    error: `core::alloc::Layout::pad_to_align` is not yet stable as a const fn
       --> rust/kernel/alloc/allocator.rs:122:9
        |
    122 |         layout.pad_to_align()
        |         ^^^^^^^^^^^^^^^^^^^^^
        |
        = help: add `#![feature(const_alloc_layout)]` to the crate attributes to enable

Since the const_alloc_layout feature [1] is already stable [2] and is available in our minimum Rust version too, simply add it to the list of the ones we use.

Not-Fixes (patch was changed on apply): fde578c86281 ("rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()")

---
 rust/kernel/lib.rs | 3 +++
 1 file changed, 3 insertions(+)
rust/kernel/lib.rs +3 -0
index ed53169e795c..94d174ed7b8b 100644
@@ -31,6 +31,9 @@
 #![feature(const_ptr_write)]
 #![feature(const_refs_to_cell)]
 //
+// Stable since Rust 1.85.0.
+#![feature(const_alloc_layout)]
+//
 // Expected to become stable.
 #![feature(arbitrary_self_types)]
 //

--
2.50.1

author maintainer
#8 lore raw

Re: [PATCH 1/4] rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()

Quoted 9 lines · Miguel Ojeda

Review

Quoted 5 lines · Danilo Krummrich
(quoted diff) +4 -0
+impl Kmalloc {
+    /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of
+    /// `layout`.
+    pub const fn aligned_layout(layout: Layout) -> Layout {

I think this const fn here was removed when applying to make it work with older compilers, right?

Yes, that's correct.

Quoted 5 lines

I was fixing another rusttest thing and noticed while applying these. I had a patch to fix it, since we can actually just use the feature, and then I noticed it wasn't in the tree. Since I have it, I am attaching it for reference in case the now-stable feature is needed, e.g. if you want to make that const fn again.

I think it doesn't add much value for this to be a const function anyways, but maybe it is more useful elsewhere? In that case, I think it also doesn't hurt to Kmalloc::aligned_layout() const again.

author maintainer
#9 lore raw

PATCH 2/4 rust: drm: ensure kmalloc() compatible Layout

In reply to Danilo Krummrich

drm::Device is allocated through __drm_dev_alloc() (which uses kmalloc()) and the driver private data, <T as drm::Driver>::Data, is initialized in-place.

Due to the order of fields in drm::Device

  pub struct Device<T: drm::Driver> {
     dev: Opaque<bindings::drm_device>,
     data: T::Data,
  }

even with an arbitrary large alignment requirement of T::Data it can't happen that the size of Device is smaller than its alignment requirement.

However, let's not rely on this subtle circumstance and create a proper kmalloc() compatible Layout.

Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")
---
 rust/kernel/drm/device.rs | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
rust/kernel/drm/device.rs +7 -2
index 3bb7c83966cf..d19410deaf6c 100644
@@ -5,6 +5,7 @@
 //! C header: [`include/linux/drm/drm_device.h`](srctree/include/linux/drm/drm_device.h)
 
 use crate::{
+    alloc::allocator::Kmalloc,
     bindings, device, drm,
     drm::driver::AllocImpl,
     error::from_err_ptr,
@@ -12,7 +13,7 @@
     prelude::*,
     types::{ARef, AlwaysRefCounted, Opaque},
 };
-use core::{mem, ops::Deref, ptr, ptr::NonNull};
+use core::{alloc::Layout, mem, ops::Deref, ptr, ptr::NonNull};
 
 #[cfg(CONFIG_DRM_LEGACY)]
 macro_rules! drm_legacy_fields {
@@ -96,6 +97,10 @@ impl<T: drm::Driver> Device<T> {
 
     /// Create a new `drm::Device` for a `drm::Driver`.
     pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<ARef<Self>> {
+        // `__drm_dev_alloc` uses `kmalloc()` to allocate memory, hence ensure a `kmalloc()`
+        // compatible `Layout`.
+        let layout = Kmalloc::aligned_layout(Layout::new::<Self>());
+
         // SAFETY:
         // - `VTABLE`, as a `const` is pinned to the read-only section of the compilation,
         // - `dev` is valid by its type invarants,
@@ -103,7 +108,7 @@ pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<A
             bindings::__drm_dev_alloc(
                 dev.as_raw(),
                 &Self::VTABLE,
-                mem::size_of::<Self>(),
+                layout.size(),
                 mem::offset_of!(Self, dev),
             )
         }
Signature · 1 line
2.50.0
maintainer
#10 lore raw

Re: [PATCH 2/4] rust: drm: ensure kmalloc() compatible Layout

Quoted 10 lines · Danilo Krummrich

drm::Device is allocated through __drm_dev_alloc() (which uses kmalloc()) and the driver private data, <T as drm::Driver>::Data, is initialized in-place.

Due to the order of fields in drm::Device

  pub struct Device<T: drm::Driver> {
     dev: Opaque<bindings::drm_device>,
     data: T::Data,
  }

I'm not convinced this patch is right.

Imagine this scenario: T::Data has size and alignment both equal to 16, and lets say that drm_device has a size that is a multiple of 8 but not 16 such as 72. In that case, you will allocate 72+16=88 bytes for Device, but actually the size of Device is 96 because there is 8 bytes of padding between dev and data.

Alice

Quoted 56 lines

even with an arbitrary large alignment requirement of T::Data it can't happen that the size of Device is smaller than its alignment requirement.

However, let's not rely on this subtle circumstance and create a proper kmalloc() compatible Layout.

Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")
---
 rust/kernel/drm/device.rs | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
rust/kernel/drm/device.rs +7 -2
index 3bb7c83966cf..d19410deaf6c 100644
@@ -5,6 +5,7 @@
 //! C header: [`include/linux/drm/drm_device.h`](srctree/include/linux/drm/drm_device.h)
 
 use crate::{
+    alloc::allocator::Kmalloc,
     bindings, device, drm,
     drm::driver::AllocImpl,
     error::from_err_ptr,
@@ -12,7 +13,7 @@
     prelude::*,
     types::{ARef, AlwaysRefCounted, Opaque},
 };
-use core::{mem, ops::Deref, ptr, ptr::NonNull};
+use core::{alloc::Layout, mem, ops::Deref, ptr, ptr::NonNull};
 
 #[cfg(CONFIG_DRM_LEGACY)]
 macro_rules! drm_legacy_fields {
@@ -96,6 +97,10 @@ impl<T: drm::Driver> Device<T> {
 
     /// Create a new `drm::Device` for a `drm::Driver`.
     pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<ARef<Self>> {
+        // `__drm_dev_alloc` uses `kmalloc()` to allocate memory, hence ensure a `kmalloc()`
+        // compatible `Layout`.
+        let layout = Kmalloc::aligned_layout(Layout::new::<Self>());
+
         // SAFETY:
         // - `VTABLE`, as a `const` is pinned to the read-only section of the compilation,
         // - `dev` is valid by its type invarants,
@@ -103,7 +108,7 @@ pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<A
             bindings::__drm_dev_alloc(
                 dev.as_raw(),
                 &Self::VTABLE,
-                mem::size_of::<Self>(),
+                layout.size(),
                 mem::offset_of!(Self, dev),
             )
         }
Signature · 1 line
2.50.0
author maintainer
#11 lore raw

Re: [PATCH 2/4] rust: drm: ensure kmalloc() compatible Layout

Quoted 12 lines · Alice Ryhl
Quoted 10 lines · Danilo Krummrich

drm::Device is allocated through __drm_dev_alloc() (which uses kmalloc()) and the driver private data, <T as drm::Driver>::Data, is initialized in-place.

Due to the order of fields in drm::Device

  pub struct Device<T: drm::Driver> {
     dev: Opaque<bindings::drm_device>,
     data: T::Data,
  }
Quoted 7 lines

I'm not convinced this patch is right.

Imagine this scenario: T::Data has size and alignment both equal to 16, and lets say that drm_device has a size that is a multiple of 8 but not 16 such as 72. In that case, you will allocate 72+16=88 bytes for Device, but actually the size of Device is 96 because there is 8 bytes of padding between dev and data.

Are you saying that there is an issue with

(1) the existing implementation with uses mem::size_of::<Self>() or

(2) the proper one that uses Kmalloc::aligned_layout(Layout::new::<Self>())?

I think neither has, because we're not allocating size_of::<Opaque<bindings::drm_device>>() + size_of::<T::Data>() as you seem to assume above, but size_of::<Device<T>>().

Quoted 56 lines
Quoted 56 lines

even with an arbitrary large alignment requirement of T::Data it can't happen that the size of Device is smaller than its alignment requirement.

However, let's not rely on this subtle circumstance and create a proper kmalloc() compatible Layout.

Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")
---
 rust/kernel/drm/device.rs | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
rust/kernel/drm/device.rs +7 -2
index 3bb7c83966cf..d19410deaf6c 100644
@@ -5,6 +5,7 @@
 //! C header: [`include/linux/drm/drm_device.h`](srctree/include/linux/drm/drm_device.h)
 
 use crate::{
+    alloc::allocator::Kmalloc,
     bindings, device, drm,
     drm::driver::AllocImpl,
     error::from_err_ptr,
@@ -12,7 +13,7 @@
     prelude::*,
     types::{ARef, AlwaysRefCounted, Opaque},
 };
-use core::{mem, ops::Deref, ptr, ptr::NonNull};
+use core::{alloc::Layout, mem, ops::Deref, ptr, ptr::NonNull};
 
 #[cfg(CONFIG_DRM_LEGACY)]
 macro_rules! drm_legacy_fields {
@@ -96,6 +97,10 @@ impl<T: drm::Driver> Device<T> {
 
     /// Create a new `drm::Device` for a `drm::Driver`.
     pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<ARef<Self>> {
+        // `__drm_dev_alloc` uses `kmalloc()` to allocate memory, hence ensure a `kmalloc()`
+        // compatible `Layout`.
+        let layout = Kmalloc::aligned_layout(Layout::new::<Self>());
+
         // SAFETY:
         // - `VTABLE`, as a `const` is pinned to the read-only section of the compilation,
         // - `dev` is valid by its type invarants,
@@ -103,7 +108,7 @@ pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<A
             bindings::__drm_dev_alloc(
                 dev.as_raw(),
                 &Self::VTABLE,
-                mem::size_of::<Self>(),
+                layout.size(),
                 mem::offset_of!(Self, dev),
             )
         }
Signature · 1 line
2.50.0
maintainer
#12 lore raw

Re: [PATCH 2/4] rust: drm: ensure kmalloc() compatible Layout

Quoted 24 lines · Danilo Krummrich
Quoted 12 lines · Alice Ryhl
Quoted 10 lines · Danilo Krummrich

drm::Device is allocated through __drm_dev_alloc() (which uses kmalloc()) and the driver private data, <T as drm::Driver>::Data, is initialized in-place.

Due to the order of fields in drm::Device

  pub struct Device<T: drm::Driver> {
     dev: Opaque<bindings::drm_device>,
     data: T::Data,
  }
Quoted 7 lines

I'm not convinced this patch is right.

Imagine this scenario: T::Data has size and alignment both equal to 16, and lets say that drm_device has a size that is a multiple of 8 but not 16 such as 72. In that case, you will allocate 72+16=88 bytes for Device, but actually the size of Device is 96 because there is 8 bytes of padding between dev and data.

Are you saying that there is an issue with

Quoted 7 lines

(1) the existing implementation with uses mem::size_of::<Self>() or

(2) the proper one that uses Kmalloc::aligned_layout(Layout::new::<Self>())?

I think neither has, because we're not allocating size_of::<Opaque<bindings::drm_device>>() + size_of::<T::Data>() as you seem to assume above, but size_of::<Device<T>>().

Yes, you're right. I misunderstood how __drm_dev_alloc works.

Alice

maintainer Reviewed-by on v1 2/4
#13 lore raw

Re: [PATCH 2/4] rust: drm: ensure kmalloc() compatible Layout

In reply to Danilo Krummrich
Quoted 12 lines · Danilo Krummrich

drm::Device is allocated through __drm_dev_alloc() (which uses kmalloc()) and the driver private data, <T as drm::Driver>::Data, is initialized in-place.

Due to the order of fields in drm::Device

  pub struct Device<T: drm::Driver> {
     dev: Opaque<bindings::drm_device>,
     data: T::Data,
  }
Quoted 8 lines

even with an arbitrary large alignment requirement of T::Data it can't happen that the size of Device is smaller than its alignment requirement.

However, let's not rely on this subtle circumstance and create a proper kmalloc() compatible Layout.

Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")
author maintainer
#14 lore raw

PATCH 3/4 rust: drm: remove pin annotations from drm::Device

In reply to Danilo Krummrich

The #[pin_data] and #[pin] annotations are not necessary for drm::Device, since we don't use any pin-init macros, but only __pinned_init() on the impl PinInit<T::Data, Error> argument of drm::Device::new().

Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")
---
 rust/kernel/drm/device.rs | 2 --
 1 file changed, 2 deletions(-)
rust/kernel/drm/device.rs +0 -2
index d19410deaf6c..d0a9528121f1 100644
@@ -54,10 +54,8 @@ macro_rules! drm_legacy_fields {
 ///
 /// `self.dev` is a valid instance of a `struct device`.
 #[repr(C)]
-#[pin_data]
 pub struct Device<T: drm::Driver> {
     dev: Opaque<bindings::drm_device>,
-    #[pin]
     data: T::Data,
 }
 
Signature · 1 line
2.50.0
reviewer
#15 lore raw

Re: [PATCH 3/4] rust: drm: remove pin annotations from drm::Device

Quoted 4 lines · Danilo Krummrich

The #[pin_data] and #[pin] annotations are not necessary for drm::Device, since we don't use any pin-init macros, but only __pinned_init() on the impl PinInit<T::Data, Error> argument of drm::Device::new().

But you're still pinning Device, right?

Quoted 11 lines
Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")
---
 rust/kernel/drm/device.rs | 2 --
 1 file changed, 2 deletions(-)
rust/kernel/drm/device.rs +0 -0
index d19410deaf6c..d0a9528121f1 100644

rust/kernel/drm/device.rs macro_rules! drm_legacy_fields { · line 59

Quoted 8 lines
rust/kernel/drm/device.rs +0 -2
@@ -54,10 +54,8 @@ macro_rules! drm_legacy_fields {
 ///
 /// `self.dev` is a valid instance of a `struct device`.
 #[repr(C)]
-#[pin_data]
 pub struct Device<T: drm::Driver> {
     dev: Opaque<bindings::drm_device>,
-    #[pin]
     data: T::Data,

Looking at this code again, I also noticed that it was wrong before this
patch: Device<T> implemented Unpin if T::Data did which is most likely wrong (or is drm_device not address sensitive?).

So good to see that fixed, thanks!

---
Cheers,
Benno

Quoted 2 lines
rust/kernel/drm/device.rs +0 -0
 }
 
author maintainer
#16 lore raw

Re: [PATCH 3/4] rust: drm: remove pin annotations from drm::Device

Quoted 7 lines · Benno Lossin
Quoted 4 lines · Danilo Krummrich

The #[pin_data] and #[pin] annotations are not necessary for drm::Device, since we don't use any pin-init macros, but only __pinned_init() on the impl PinInit<T::Data, Error> argument of drm::Device::new().

But you're still pinning Device, right?

A drm::Device instance never exists other than as ARef<drm::Device>.

Quoted 15 lines
Quoted 15 lines
Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")
---
 rust/kernel/drm/device.rs | 2 --
 1 file changed, 2 deletions(-)
rust/kernel/drm/device.rs +0 -1
index d19410deaf6c..d0a9528121f1 100644
@@ -54,10 +54,8 @@ macro_rules! drm_legacy_fields {
 ///
 /// `self.dev` is a valid instance of a `struct device`.
 #[repr(C)]
-#[pin_data]
Quoted 8 lines

rust/kernel/drm/device.rs macro_rules! drm_legacy_fields { · line 59

Quoted 4 lines
rust/kernel/drm/device.rs +0 -1
 pub struct Device<T: drm::Driver> {
     dev: Opaque<bindings::drm_device>,
-    #[pin]
     data: T::Data,

Looking at this code again, I also noticed that it was wrong before this
patch: Device<T> implemented Unpin if T::Data did which is most likely wrong (or is drm_device not address sensitive?).

It is, but as mentioned above a drm::Device only ever exists as ARef<drm::Device>.

So, in drm::Device::new() we allocate the drm::Device with __drm_dev_alloc(), initialize data in-place within this allocated memory and create an ARef<drm::Device> directly from the raw pointer returned by __drm_dev_alloc().

Quoted 8 lines

So good to see that fixed, thanks!

---
Cheers,
Benno

Quoted 2 lines
rust/kernel/drm/device.rs +0 -0
 }
 
reviewer
#17 lore raw

Re: [PATCH 3/4] rust: drm: remove pin annotations from drm::Device

Quoted 9 lines · Danilo Krummrich
Quoted 8 lines · Benno Lossin
Quoted 6 lines · Danilo Krummrich

#[repr(C)]

rust/kernel/drm/device.rs +0 -2
-#[pin_data]
 pub struct Device<T: drm::Driver> {
     dev: Opaque<bindings::drm_device>,
-    #[pin]
     data: T::Data,
Quoted 6 lines
Quoted 3 lines

Looking at this code again, I also noticed that it was wrong before this
patch: Device<T> implemented Unpin if T::Data did which is most likely wrong (or is drm_device not address sensitive?).

It is, but as mentioned above a drm::Device only ever exists as ARef<drm::Device>.

Yeah the Unpin thing isn't a problem for ARef, but we are theoretically allowed to implement moving out of an ARef (given that it is unique) when the type is Unpin.

Thanks for confirming.

---
Cheers,
Benno

reviewer Reviewed-by on v1 3/4
#18 lore raw

Re: [PATCH 3/4] rust: drm: remove pin annotations from drm::Device

In reply to Danilo Krummrich
Quoted 7 lines · Danilo Krummrich

The #[pin_data] and #[pin] annotations are not necessary for drm::Device, since we don't use any pin-init macros, but only __pinned_init() on the impl PinInit<T::Data, Error> argument of drm::Device::new().

Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")

---
Cheers,
Benno

Quoted 3 lines
---
 rust/kernel/drm/device.rs | 2 --
 1 file changed, 2 deletions(-)
author maintainer
#19 lore raw

PATCH 4/4 rust: drm: don't pass the address of drm::Device to drm_dev_put()

In reply to Danilo Krummrich

In drm_dev_put() call in AlwaysRefCounted::dec_ref() we rely on struct drm_device to be the first field in drm::Device, whereas everywhere else we correctly obtain the address of the actual struct drm_device.

Analogous to the from_drm_device() helper, provide the into_drm_device() helper in order to address this.

Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")
---
 rust/kernel/drm/device.rs | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)
rust/kernel/drm/device.rs +18 -3
index d0a9528121f1..d29c477e89a8 100644
@@ -120,9 +120,13 @@ pub fn new(dev: &device::Device, data: impl PinInit<T::Data, Error>) -> Result<A
         // - `raw_data` is a valid pointer to uninitialized memory.
         // - `raw_data` will not move until it is dropped.
         unsafe { data.__pinned_init(raw_data) }.inspect_err(|_| {
-            // SAFETY: `__drm_dev_alloc()` was successful, hence `raw_drm` must be valid and the
+            // SAFETY: `raw_drm` is a valid pointer to `Self`, given that `__drm_dev_alloc` was
+            // successful.
+            let drm_dev = unsafe { Self::into_drm_device(raw_drm) };
+
+            // SAFETY: `__drm_dev_alloc()` was successful, hence `drm_dev` must be valid and the
             // refcount must be non-zero.
-            unsafe { bindings::drm_dev_put(ptr::addr_of_mut!((*raw_drm.as_ptr()).dev).cast()) };
+            unsafe { bindings::drm_dev_put(drm_dev) };
         })?;
 
         // SAFETY: The reference count is one, and now we take ownership of that reference as a
@@ -143,6 +147,14 @@ unsafe fn from_drm_device(ptr: *const bindings::drm_device) -> *mut Self {
         unsafe { crate::container_of!(Opaque::cast_from(ptr), Self, dev) }.cast_mut()
     }
 
+    /// # Safety
+    ///
+    /// `ptr` must be a valid pointer to `Self`.
+    unsafe fn into_drm_device(ptr: NonNull<Self>) -> *mut bindings::drm_device {
+        // SAFETY: By the safety requirements of this function, `ptr` is a valid pointer to `Self`.
+        unsafe { &raw mut (*ptr.as_ptr()).dev }.cast()
+    }
+
     /// Not intended to be called externally, except via declare_drm_ioctls!()
     ///
     /// # Safety
@@ -192,8 +204,11 @@ fn inc_ref(&self) {
     }
 
     unsafe fn dec_ref(obj: NonNull<Self>) {
+        // SAFETY: `obj` is a valid pointer to `Self`.
+        let drm_dev = unsafe { Self::into_drm_device(obj) };
+
         // SAFETY: The safety requirements guarantee that the refcount is non-zero.
-        unsafe { bindings::drm_dev_put(obj.cast().as_ptr()) };
+        unsafe { bindings::drm_dev_put(drm_dev) };
     }
 }
 
Signature · 1 line
2.50.0
maintainer Reviewed-by on v1 4/4
#20 lore raw

Re: [PATCH 4/4] rust: drm: don't pass the address of drm::Device to drm_dev_put()

Quoted 9 lines · Danilo Krummrich

In drm_dev_put() call in AlwaysRefCounted::dec_ref() we rely on struct drm_device to be the first field in drm::Device, whereas everywhere else we correctly obtain the address of the actual struct drm_device.

Analogous to the from_drm_device() helper, provide the into_drm_device() helper in order to address this.

Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")

rust/kernel/drm/device.rs unsafe fn from_drm_device(ptr: *const bindings::drm_device) -> *mut Self { · line 156

Quoted 7 lines
rust/kernel/drm/device.rs +7 -0
+    /// # Safety
+    ///
+    /// `ptr` must be a valid pointer to `Self`.
+    unsafe fn into_drm_device(ptr: NonNull<Self>) -> *mut bindings::drm_device {
+        // SAFETY: By the safety requirements of this function, `ptr` is a valid pointer to `Self`.
+        unsafe { &raw mut (*ptr.as_ptr()).dev }.cast()
+    }

I think it would somewhat more consistent to use the naming raw_get() or cast_into(), but I am ok with this naming too.

Alice

author maintainer Applied
#21 lore raw
In reply to Danilo Krummrich
Quoted 6 lines · Danilo Krummrich

This patch series replaces aligned_size() with Kmalloc::aligned_layout(), which is subsequently used to obtain a kmalloc() compatible Layout for __drm_dev_alloc() in drm::Device::new().

It also contains two additional drm::Device fixes; the commits are based on next-20250731.

Applied to drm-misc-fixes, thanks!