Alloc and drm::Device fixes
Subsystems (4)
Danilo Krummrich
maintainercover 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
Danilo Krummrich
maintainerPATCH 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.
--- rust/kernel/alloc/allocator.rs | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-)
rust/kernel/alloc/allocator.rs +18 -12
@@ -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
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 supportkmalloc()only, but is now used inReallocFunc::call()and hence for all allocators.However, the additional padding applied by
aligned_size()is only required by thekmalloc()allocator backend.Hence, replace
aligned_size()withKmalloc::aligned_layout()and use it for the affected allocators, i.e.kmalloc()andkvmalloc(), only.
Quoted 6 lines
While at it, make
Kmalloc::aligned_layout()public, such that Rust abstractions, which have to call subsystem specifickmalloc()based allocation primitives directly, can make use of it.Fixes 8a799831fc63 ("rust: alloc: implement `ReallocFunc`")Signed-off-by Danilo Krummrich <[email protected]>
I guess vmalloc handles alignment in a different way ... ok makes sense to me.
Re: [PATCH 1/4] rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()
In reply to Danilo KrummrichQuoted 10 lines · Danilo Krummrich
aligned_size()dates back to when Rust did supportkmalloc()only, but is now used inReallocFunc::call()and hence for all allocators.However, the additional padding applied by
aligned_size()is only required by thekmalloc()allocator backend.Hence, replace
aligned_size()withKmalloc::aligned_layout()and use it for the affected allocators, i.e.kmalloc()andkvmalloc(), only.
Quoted 6 lines
While at it, make
Kmalloc::aligned_layout()public, such that Rust abstractions, which have to call subsystem specifickmalloc()based allocation primitives directly, can make use of it.Fixes 8a799831fc63 ("rust: alloc: implement `ReallocFunc`")Signed-off-by Danilo Krummrich <[email protected]>
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
Danilo Krummrich
maintainerRe: [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
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_SIZEaligned and the size always a multiple ofPAGE_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
Danilo Krummrich
maintainerRe: [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_SIZEaligned and the size always a multiple ofPAGE_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.
Re: [PATCH 1/4] rust: alloc: replace aligned_size() with Kmalloc::aligned_layout()
In reply to Danilo KrummrichReview
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 enableSince 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
@@ -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
Danilo Krummrich
maintainerRe: [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 fnhere was removed when applying to make it work with older compilers, right?
Yes, that's correct.
Quoted 5 lines
I was fixing another
rusttestthing 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 thatconst fnagain.
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.
Danilo Krummrich
maintainerPATCH 2/4 rust: drm: ensure kmalloc() compatible Layout
In reply to Danilo Krummrichdrm::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.
--- rust/kernel/drm/device.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
rust/kernel/drm/device.rs +7 -2
@@ -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
Alice Ryhl
maintainerRe: [PATCH 2/4] rust: drm: ensure kmalloc() compatible Layout
Quoted 10 lines · Danilo Krummrich
drm::Deviceis allocated through__drm_dev_alloc()(which useskmalloc()) and the driver private data, <T as drm::Driver>::Data, is initialized in-place.Due to the order of fields in
drm::Devicepub 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::Datait 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")Signed-off-by Danilo Krummrich <[email protected]>--- rust/kernel/drm/device.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)rust/kernel/drm/device.rs +7
-2@@ -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
Danilo Krummrich
maintainerRe: [PATCH 2/4] rust: drm: ensure kmalloc() compatible Layout
Quoted 12 lines · Alice Ryhl
Quoted 10 lines · Danilo Krummrich
drm::Deviceis allocated through__drm_dev_alloc()(which useskmalloc()) and the driver private data, <T as drm::Driver>::Data, is initialized in-place.Due to the order of fields in
drm::Devicepub 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::Datahas size and alignment both equal to 16, and lets say thatdrm_devicehas 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::Datait 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")Signed-off-by Danilo Krummrich <[email protected]>--- rust/kernel/drm/device.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)rust/kernel/drm/device.rs +7
-2@@ -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
Alice Ryhl
maintainerRe: [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::Deviceis allocated through__drm_dev_alloc()(which useskmalloc()) and the driver private data, <T as drm::Driver>::Data, is initialized in-place.Due to the order of fields in
drm::Devicepub 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::Datahas size and alignment both equal to 16, and lets say thatdrm_devicehas 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
Re: [PATCH 2/4] rust: drm: ensure kmalloc() compatible Layout
In reply to Danilo KrummrichQuoted 12 lines · Danilo Krummrich
drm::Deviceis allocated through__drm_dev_alloc()(which useskmalloc()) and the driver private data, <T as drm::Driver>::Data, is initialized in-place.Due to the order of fields in
drm::Devicepub 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::Datait 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")Signed-off-by Danilo Krummrich <[email protected]>
Danilo Krummrich
maintainerPATCH 3/4 rust: drm: remove pin annotations from drm::Device
In reply to Danilo KrummrichThe #[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().
--- rust/kernel/drm/device.rs | 2 -- 1 file changed, 2 deletions(-)
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 , }
Signature · 1 line
2.50.0
Benno Lossin
reviewerRe: [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 ofdrm::Device::new().
But you're still pinning Device, right?
Quoted 11 lines
Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")Signed-off-by Danilo Krummrich <[email protected]>--- rust/kernel/drm/device.rs | 2 -- 1 file changed, 2 deletions(-)rust/kernel/drm/device.rs +0
-0
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}
Danilo Krummrich
maintainerRe: [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 ofdrm::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")Signed-off-by Danilo Krummrich <[email protected]>--- rust/kernel/drm/device.rs | 2 -- 1 file changed, 2 deletions(-)rust/kernel/drm/device.rs +0
-1@@ -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
-1pub 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>implementedUnpinifT::Datadid which is most likely wrong (or isdrm_devicenot 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,
BennoQuoted 2 lines
rust/kernel/drm/device.rs +0
-0}
Benno Lossin
reviewerRe: [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>implementedUnpinifT::Datadid which is most likely wrong (or isdrm_devicenot address sensitive?).It is, but as mentioned above a
drm::Deviceonly 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
Re: [PATCH 3/4] rust: drm: remove pin annotations from drm::Device
In reply to Danilo KrummrichQuoted 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 ofdrm::Device::new().Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")Signed-off-by Danilo Krummrich <[email protected]>
---
Cheers,
Benno
Quoted 3 lines
--- rust/kernel/drm/device.rs | 2 -- 1 file changed, 2 deletions(-)
Danilo Krummrich
maintainerPATCH 4/4 rust: drm: don't pass the address of drm::Device to drm_dev_put()
In reply to Danilo KrummrichIn 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.
--- rust/kernel/drm/device.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
rust/kernel/drm/device.rs +18 -3
@@ -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
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 inAlwaysRefCounted::dec_ref()we rely on structdrm_deviceto be the first field indrm::Device, whereas everywhere else we correctly obtain the address of the actual structdrm_device.Analogous to the
from_drm_device()helper, provide theinto_drm_device()helper in order to address this.Fixes 1e4b8896c0f3 ("rust: drm: add device abstraction")Signed-off-by Danilo Krummrich <[email protected]>
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
Quoted 6 lines · Danilo Krummrich
This patch series replaces
aligned_size()withKmalloc::aligned_layout(), which is subsequently used to obtain akmalloc()compatible Layout for__drm_dev_alloc()indrm::Device::new().It also contains two additional
drm::Devicefixes; the commits are based on next-20250731.
Applied to drm-misc-fixes, thanks!