[PATCH v4 00/16] rust: drm: Higher-Ranked Lifetime private data

From: Danilo Krummrich

Date: Sat Jun 20 2026 - 14:49:54 EST


DRM ioctls run in process context without any guarantee that the parent
bus device is still bound. This series solves the problem by introducing
RegistrationGuard -- a guard representing a drm_dev_enter/exit SRCU
critical section that proves the parent bus device is bound for the
lifetime of the guard.

As initial plumbing for this, the DRM DeviceContext typestates are
reworked: Uninit is renamed to Normal, defaults are adjusted,
AlwaysRefCounted is restricted to Normal, and a Deref chain from
Device<T, Registered> to Device<T, Normal> is established. This gives
Device<T, Registered> the semantic that the device is currently
registered and the parent bus device is bound, which makes the
RegistrationGuard and ioctl dispatch much cleaner. An Ioctl context
restricts registration_guard() to ioctl dispatch, where the DRM core
guarantees prior registration.

On top of that, add RegistrationData as a ForLt associated type on
drm::Driver, allowing drivers to store data whose lifetime is tied to
the parent bus device binding scope. The data is allocated in
Registration::new(), lifetime-erased to 'static for storage, and made
accessible through Device<T, Registered>::registration_data_with(). The
closure's HRTB ties the lifetime to the closure scope; internally the
'static pointer is cast back to the closure-scoped lifetime. The
reference is valid for the duration of the drm_dev_enter/exit critical
section held by RegistrationGuard.

Also update the ioctl dispatch macro to wrap every handler in a
RegistrationGuard, returning ENODEV if the device has been unplugged,
and pass the registration data to handlers.

This series is based on [1]; a branch with all patches can be found
in [2].

[1] https://lore.kernel.org/driver-core/20260618230834.812007-1-dakr@xxxxxxxxxx/
[2] https://git.kernel.org/pub/scm/linux/kernel/git/dakr/linux.git/log/?h=drm-lifetime

Changes in v4:
- Fix pre-existing unbounded lifetimes in ioctl handler arguments.
- Fix registration_guard() being callable on unregistered devices by
introducing an Ioctl device context typestate; registration_guard() is
now only available on Device<T, Ioctl>, which is exclusively
constructed in ioctl dispatch context where the DRM core guarantees
prior registration.
- Fix type inference allowing handlers to obtain Device<Registered>
before RegistrationGuard is acquired.
- Make RegistrationGuard !Send via NotThreadSafe to prevent potential
lockdep splats from cross-thread SRCU unlock.
- Store &Device<T, Registered> directly in RegistrationGuard instead of
calling assume_ctx() in Deref.

Changes in v3:
- Rename UnbindGuard to RegistrationGuard
- RegistrationGuard no longer dereferences to &Device<Bound>; it
dereferences to &drm::Device<T, Registered> instead
- Drop Registration::new() and rename Registration::new_with_lt() to
Registration::new()
- Rework DeviceContext typestates: rename Uninit to Normal, restrict
AlwaysRefCounted to Normal, establish Deref chain from Registered
to Normal
- Add AsRef<ParentDevice<Bound>> on Device<T, Registered> for parent
device access
- Move registration_data_with() from RegistrationGuard to
drm::Device<T, Registered>
- Ioctl handlers no longer receive &Device<Bound>, only registration
data and drm::Device<T, Registered>
- Use Device<Registered>::as_ref() to access parent device in nova-drm

Changes in v2:
- Replace unsafe direct registration data access in ioctl dispatch with
safe UnbindGuard::registration_data_with() closure
- Eliminate unbind_guard() free function; use type-inference anchor to
enable direct dev.unbind_guard() method call in the ioctl macro
- UnbindGuard::registration_data_with() provides both parent device and
registration data to the closure
- Add nova-drm conversion patch demonstrating lifetime-aware registration
data with &'bound auxiliary::Device<Bound>
- Various safety comment and documentation improvements

Danilo Krummrich (16):
rust: drm: ioctl: fix unbounded lifetimes in ioctl handler arguments
rust: drm: rename Uninit DeviceContext to Normal
rust: drm: Add Driver::ParentDevice associated type
rust: drm: change default DeviceContext to Normal
rust: drm: restrict AlwaysRefCounted to Normal Device context
rust: drm: restrict AlwaysRefCounted to Normal GEM Object context
rust: drm: split Deref for Device context typestates
rust: drm: pin ioctl Device reference to Normal context
rust: drm: add Ioctl device context typestate
rust: drm: Add RegistrationGuard for drm_dev_enter/exit critical
sections
rust: drm: Wrap ioctl dispatch in RegistrationGuard
rust: drm: return ParentDevice from Device AsRef
rust: drm: add AsRef<ParentDevice<Bound>> for Device<Registered>
rust: drm: Add RegistrationData to drm::Driver
rust: drm: Pass registration data to ioctl handlers
drm: nova: Use drm::Device<Registered> to access the parent bus device

drivers/gpu/drm/nova/driver.rs | 41 +++--
drivers/gpu/drm/nova/file.rs | 22 ++-
drivers/gpu/drm/nova/gem.rs | 18 +-
drivers/gpu/drm/tyr/driver.rs | 28 ++--
drivers/gpu/drm/tyr/file.rs | 8 +-
drivers/gpu/drm/tyr/gem.rs | 11 +-
rust/kernel/drm/device.rs | 293 ++++++++++++++++++++++++---------
rust/kernel/drm/driver.rs | 123 +++++++++-----
rust/kernel/drm/gem/mod.rs | 98 ++++++-----
rust/kernel/drm/gem/shmem.rs | 79 ++++-----
rust/kernel/drm/ioctl.rs | 108 ++++++++++--
rust/kernel/drm/mod.rs | 4 +-
12 files changed, 550 insertions(+), 283 deletions(-)


base-commit: 9ece8b7075e983bc01223a4aa1eb1c99285f83ad
--
2.54.0