[PATCH v2 00/25] rust: device: Higher-Ranked Lifetime Types for device drivers

Danilo Krummrich posted 25 patches 1 month, 1 week ago
There is a newer version of this series
drivers/base/dd.c                        |   2 +-
drivers/cpufreq/rcpufreq_dt.rs           |  10 +-
drivers/gpu/drm/nova/driver.rs           |   9 +-
drivers/gpu/drm/tyr/driver.rs            |  24 ++-
drivers/gpu/drm/tyr/gpu.rs               |  62 +++---
drivers/gpu/drm/tyr/regs.rs              |  21 +-
drivers/gpu/nova-core/driver.rs          |  48 ++---
drivers/gpu/nova-core/fb.rs              |  31 ++-
drivers/gpu/nova-core/firmware/gsp.rs    |   8 +-
drivers/gpu/nova-core/gpu.rs             |  38 ++--
drivers/gpu/nova-core/gsp/commands.rs    |  10 +-
drivers/gpu/nova-core/gsp/fw/commands.rs |   4 +-
drivers/gpu/nova-core/nova_core.rs       |   4 +-
drivers/pwm/pwm_th1520.rs                |  14 +-
include/linux/device/driver.h            |   4 +-
rust/Makefile                            |   1 +
rust/kernel/auxiliary.rs                 | 132 +++++++++----
rust/kernel/cpufreq.rs                   |   8 +-
rust/kernel/device.rs                    |  79 +++++---
rust/kernel/devres.rs                    |  16 +-
rust/kernel/driver.rs                    |  44 +++--
rust/kernel/i2c.rs                       | 130 +++++++-----
rust/kernel/io/mem.rs                    | 131 ++++++------
rust/kernel/pci.rs                       |  89 ++++++---
rust/kernel/pci/io.rs                    |  68 ++++---
rust/kernel/pci/irq.rs                   |  38 ++--
rust/kernel/platform.rs                  | 120 +++++++----
rust/kernel/types.rs                     |   4 +
rust/kernel/types/for_lt.rs              | 117 +++++++++++
rust/kernel/usb.rs                       |  94 +++++----
rust/macros/for_lt.rs                    | 242 +++++++++++++++++++++++
rust/macros/lib.rs                       |  12 ++
samples/rust/rust_debugfs.rs             |  10 +-
samples/rust/rust_dma.rs                 |   9 +-
samples/rust/rust_driver_auxiliary.rs    |  53 +++--
samples/rust/rust_driver_i2c.rs          |  18 +-
samples/rust/rust_driver_pci.rs          |  93 ++++-----
samples/rust/rust_driver_platform.rs     |  12 +-
samples/rust/rust_driver_usb.rs          |  14 +-
samples/rust/rust_i2c_client.rs          |  12 +-
samples/rust/rust_soc.rs                 |  12 +-
41 files changed, 1220 insertions(+), 627 deletions(-)
create mode 100644 rust/kernel/types/for_lt.rs
create mode 100644 rust/macros/for_lt.rs
[PATCH v2 00/25] rust: device: Higher-Ranked Lifetime Types for device drivers
Posted by Danilo Krummrich 1 month, 1 week ago
Currently, Rust device drivers access device resources such as PCI BAR mappings
and I/O memory regions through Devres<T>.

Devres::access() provides zero-overhead access by taking a &Device<Bound>
reference as proof that the device is still bound. Since a &Device<Bound> is
available in almost all contexts by design, Devres is mostly a type-system level
proof that the resource is valid, but it can also be used from scopes without
this guarantee through its try_access() accessor.

This works well in general, but has a few limitations:

  - Every access to a device resource goes through Devres::access(), which
    despite zero cost, adds boilerplate to every access site.

  - Destructors do not receive a &Device<Bound>, so they must use try_access(),
    which can fail. In practice the access succeeds if teardown ordering is
    correct, but the type system can't express this, forcing drivers to handle a
    failure path that should never be taken.

  - Sharing a resource across components (e.g. passing a BAR to a sub-component)
    requires Arc<Devres<T>>.

  - Device references must be stored as ARef<Device> rather than plain &Device
    borrows.

These limitations stem from the driver's bus device private data being 'static
-- the driver struct cannot borrow from the device reference it receives in
probe(), even though it structurally cannot outlive the device binding.

This series introduces Higher-Ranked Lifetime Types (HRT) for Rust device
drivers. An HRT is a type that is generic over a lifetime -- it does not have a
fixed lifetime, but can be instantiated with any lifetime chosen by the caller.

Rust does not directly support types that are generic over a lifetime as type
parameters; the ForLt trait (contributed by Gary Guo) encodes this internally.

The module_*_driver! macros handle the wrapping, so driver authors just write
struct MyDriver<'a> and impl Driver<'a>.

With HRT, driver structs carry a lifetime parameter tied to the device binding
scope -- the interval of a bus device being bound to a driver. Device resources
like pci::Bar<'a> and IoMem<'a> are handed out with this lifetime, so the
compiler enforces at build time that they do not escape the binding scope.

Before:

	struct MyDriver {
	    pdev: ARef<pci::Device>,
	    bar: Devres<pci::Bar<BAR_SIZE>>,
	}

	let io = self.bar.access(dev)?;
	io.read32(OFFSET);

After:

	struct MyDriver<'a> {
	    pdev: &'a pci::Device,
	    bar: pci::Bar<'a, BAR_SIZE>,
	}

	self.bar.read32(OFFSET);

Lifetime-parameterized device resources can be put into a Devres at any point
via Bar::into_devres() / IoMem::into_devres(), providing the exact same
semantics as before. This is useful for resources shared across subsystem
boundaries where revocation is needed.

This also synergizes with the upcoming self-referential initialization support
in pin-init, which allows one field of the driver struct to borrow another
during initialization without unsafe code.

The same pattern is applied to auxiliary device registration data as a first
example beyond bus device private data. Registration<F: ForLt> can hold
lifetime-parameterized data tied to the parent driver's binding scope. Since the
auxiliary bus guarantees that the parent remains bound while the auxiliary
device is registered, the registration data can safely borrow the parent's
device resources.

More generally, binding resource lifetimes to a registration scope applies to
every registration that is scoped to a driver binding -- auxiliary devices,
class devices, IRQ handlers, workqueues.

A follow-up series extends this to class device registrations, starting with
DRM, so that class device callbacks (IOCTLs, etc.) can safely access device
resources through the separate registration data bound to the registration's
lifetime without Devres indirection.

The series contains a few driver patches for reference, indicated by the REF
suffix.

Thanks to Gary for coming up with the ForLt implementation; thanks to Alice for
the early discussions around lifetime-parameterized private data that helped
shape the direction of this work.

This series depends on [1].

[1] https://lore.kernel.org/driver-core/20260505152400.3905096-1-dakr@kernel.org/

Changes in v2:
  - Add 'a bound to ForLt::Of<'a> and WithLt::Of, making the lifetime bound
    inherent to the trait; remove all F::Of<'static>: 'static where clauses
  - Drop "rust: devres: add ForLt support to Devres"; Devres itself stays
    unchanged -- ForLt-aware access is introduced later through DevresLt in a
    separate series
  - Use 'bound instead of 'a; add patches to consistently use 'bound for
    pre-existing 'a

Danilo Krummrich (24):
  rust: driver core: drop drvdata before devres release
  rust: device: generalize drvdata methods over ForLt
  rust: driver: make Adapter trait lifetime-parameterized
  rust: pci: implement Sync for Device<Bound>
  rust: platform: implement Sync for Device<Bound>
  rust: auxiliary: implement Sync for Device<Bound>
  rust: usb: implement Sync for Device<Bound>
  rust: device: implement Sync for Device<Bound>
  rust: pci: make Driver trait lifetime-parameterized
  rust: platform: make Driver trait lifetime-parameterized
  rust: auxiliary: make Driver trait lifetime-parameterized
  rust: auxiliary: generalize Registration over ForLt
  samples: rust: rust_driver_auxiliary: showcase lifetime-bound
    registration data
  rust: usb: make Driver trait lifetime-parameterized
  rust: i2c: make Driver trait lifetime-parameterized
  rust: pci: make Bar lifetime-parameterized
  rust: io: make IoMem and ExclusiveIoMem lifetime-parameterized
  samples: rust: rust_driver_pci: use HRT lifetime for Bar
  rust: driver-core: rename 'a lifetime to 'bound
  gpu: nova-core: rename 'a lifetime to 'bound
  gpu: nova-core: use HRT lifetime for Bar
  gpu: nova-core: unregister sysmem flush page from Drop
  gpu: nova-core: replace ARef<Device> with &'bound Device in
    SysmemFlush
  gpu: drm: tyr: use HRT lifetime for IoMem

Gary Guo (1):
  rust: types: add `ForLt` trait for higher-ranked lifetime support

 drivers/base/dd.c                        |   2 +-
 drivers/cpufreq/rcpufreq_dt.rs           |  10 +-
 drivers/gpu/drm/nova/driver.rs           |   9 +-
 drivers/gpu/drm/tyr/driver.rs            |  24 ++-
 drivers/gpu/drm/tyr/gpu.rs               |  62 +++---
 drivers/gpu/drm/tyr/regs.rs              |  21 +-
 drivers/gpu/nova-core/driver.rs          |  48 ++---
 drivers/gpu/nova-core/fb.rs              |  31 ++-
 drivers/gpu/nova-core/firmware/gsp.rs    |   8 +-
 drivers/gpu/nova-core/gpu.rs             |  38 ++--
 drivers/gpu/nova-core/gsp/commands.rs    |  10 +-
 drivers/gpu/nova-core/gsp/fw/commands.rs |   4 +-
 drivers/gpu/nova-core/nova_core.rs       |   4 +-
 drivers/pwm/pwm_th1520.rs                |  14 +-
 include/linux/device/driver.h            |   4 +-
 rust/Makefile                            |   1 +
 rust/kernel/auxiliary.rs                 | 132 +++++++++----
 rust/kernel/cpufreq.rs                   |   8 +-
 rust/kernel/device.rs                    |  79 +++++---
 rust/kernel/devres.rs                    |  16 +-
 rust/kernel/driver.rs                    |  44 +++--
 rust/kernel/i2c.rs                       | 130 +++++++-----
 rust/kernel/io/mem.rs                    | 131 ++++++------
 rust/kernel/pci.rs                       |  89 ++++++---
 rust/kernel/pci/io.rs                    |  68 ++++---
 rust/kernel/pci/irq.rs                   |  38 ++--
 rust/kernel/platform.rs                  | 120 +++++++----
 rust/kernel/types.rs                     |   4 +
 rust/kernel/types/for_lt.rs              | 117 +++++++++++
 rust/kernel/usb.rs                       |  94 +++++----
 rust/macros/for_lt.rs                    | 242 +++++++++++++++++++++++
 rust/macros/lib.rs                       |  12 ++
 samples/rust/rust_debugfs.rs             |  10 +-
 samples/rust/rust_dma.rs                 |   9 +-
 samples/rust/rust_driver_auxiliary.rs    |  53 +++--
 samples/rust/rust_driver_i2c.rs          |  18 +-
 samples/rust/rust_driver_pci.rs          |  93 ++++-----
 samples/rust/rust_driver_platform.rs     |  12 +-
 samples/rust/rust_driver_usb.rs          |  14 +-
 samples/rust/rust_i2c_client.rs          |  12 +-
 samples/rust/rust_soc.rs                 |  12 +-
 41 files changed, 1220 insertions(+), 627 deletions(-)
 create mode 100644 rust/kernel/types/for_lt.rs
 create mode 100644 rust/macros/for_lt.rs

-- 
2.54.0
Re: [PATCH v2 00/25] rust: device: Higher-Ranked Lifetime Types for device drivers
Posted by Dirk Behme 1 month, 1 week ago
On 06.05.2026 23:50, Danilo Krummrich wrote:
> Currently, Rust device drivers access device resources such as PCI BAR mappings
> and I/O memory regions through Devres<T>.
> 
> Devres::access() provides zero-overhead access by taking a &Device<Bound>
> reference as proof that the device is still bound. Since a &Device<Bound> is
> available in almost all contexts by design, Devres is mostly a type-system level
> proof that the resource is valid, but it can also be used from scopes without
> this guarantee through its try_access() accessor.
> 
> This works well in general, but has a few limitations:
> 
>    - Every access to a device resource goes through Devres::access(), which
>      despite zero cost, adds boilerplate to every access site.
> 
>    - Destructors do not receive a &Device<Bound>, so they must use try_access(),
>      which can fail. In practice the access succeeds if teardown ordering is
>      correct, but the type system can't express this, forcing drivers to handle a
>      failure path that should never be taken.
> 
>    - Sharing a resource across components (e.g. passing a BAR to a sub-component)
>      requires Arc<Devres<T>>.
> 
>    - Device references must be stored as ARef<Device> rather than plain &Device
>      borrows.
> 
> These limitations stem from the driver's bus device private data being 'static
> -- the driver struct cannot borrow from the device reference it receives in
> probe(), even though it structurally cannot outlive the device binding.
> 
> This series introduces Higher-Ranked Lifetime Types (HRT) for Rust device
> drivers. An HRT is a type that is generic over a lifetime -- it does not have a
> fixed lifetime, but can be instantiated with any lifetime chosen by the caller.
> 
> Rust does not directly support types that are generic over a lifetime as type
> parameters; the ForLt trait (contributed by Gary Guo) encodes this internally.
> 
> The module_*_driver! macros handle the wrapping, so driver authors just write
> struct MyDriver<'a> and impl Driver<'a>.
> 
> With HRT, driver structs carry a lifetime parameter tied to the device binding
> scope -- the interval of a bus device being bound to a driver. Device resources
> like pci::Bar<'a> and IoMem<'a> are handed out with this lifetime, so the
> compiler enforces at build time that they do not escape the binding scope.
> 
> Before:
> 
> 	struct MyDriver {
> 	    pdev: ARef<pci::Device>,
> 	    bar: Devres<pci::Bar<BAR_SIZE>>,
> 	}
> 
> 	let io = self.bar.access(dev)?;
> 	io.read32(OFFSET);
> 
> After:
> 
> 	struct MyDriver<'a> {
> 	    pdev: &'a pci::Device,
> 	    bar: pci::Bar<'a, BAR_SIZE>,
> 	}
> 
> 	self.bar.read32(OFFSET);
> 
> Lifetime-parameterized device resources can be put into a Devres at any point
> via Bar::into_devres() / IoMem::into_devres(), providing the exact same
> semantics as before. This is useful for resources shared across subsystem
> boundaries where revocation is needed.
> 
> This also synergizes with the upcoming self-referential initialization support
> in pin-init, which allows one field of the driver struct to borrow another
> during initialization without unsafe code.
> 
> The same pattern is applied to auxiliary device registration data as a first
> example beyond bus device private data. Registration<F: ForLt> can hold
> lifetime-parameterized data tied to the parent driver's binding scope. Since the
> auxiliary bus guarantees that the parent remains bound while the auxiliary
> device is registered, the registration data can safely borrow the parent's
> device resources.
> 
> More generally, binding resource lifetimes to a registration scope applies to
> every registration that is scoped to a driver binding -- auxiliary devices,
> class devices, IRQ handlers, workqueues.
> 
> A follow-up series extends this to class device registrations, starting with
> DRM, so that class device callbacks (IOCTLs, etc.) can safely access device
> resources through the separate registration data bound to the registration's
> lifetime without Devres indirection.
> 
> The series contains a few driver patches for reference, indicated by the REF
> suffix.
> 
> Thanks to Gary for coming up with the ForLt implementation; thanks to Alice for
> the early discussions around lifetime-parameterized private data that helped
> shape the direction of this work.
> 
> This series depends on [1].
> 
> [1] https://lore.kernel.org/driver-core/20260505152400.3905096-1-dakr@kernel.org/


I have applied this series together with [1] on top of 7.1.0-rc1. I made 
some adaptions to local changes (e.g. my ARM64 TMU interrupt test) and 
boot tested it. Several parts this patch series touches (e.g. PCI, 
auxiliary, gpu) I might not use or even don't have it enabled. So I 
don't know if this is worth mentioning

Tested-by: Dirk Behme <dirk.behme@de.bosch.com>

Please feel free to ignore this, then.

Thanks

Dirk


> Changes in v2:
>    - Add 'a bound to ForLt::Of<'a> and WithLt::Of, making the lifetime bound
>      inherent to the trait; remove all F::Of<'static>: 'static where clauses
>    - Drop "rust: devres: add ForLt support to Devres"; Devres itself stays
>      unchanged -- ForLt-aware access is introduced later through DevresLt in a
>      separate series
>    - Use 'bound instead of 'a; add patches to consistently use 'bound for
>      pre-existing 'a
> 
> Danilo Krummrich (24):
>    rust: driver core: drop drvdata before devres release
>    rust: device: generalize drvdata methods over ForLt
>    rust: driver: make Adapter trait lifetime-parameterized
>    rust: pci: implement Sync for Device<Bound>
>    rust: platform: implement Sync for Device<Bound>
>    rust: auxiliary: implement Sync for Device<Bound>
>    rust: usb: implement Sync for Device<Bound>
>    rust: device: implement Sync for Device<Bound>
>    rust: pci: make Driver trait lifetime-parameterized
>    rust: platform: make Driver trait lifetime-parameterized
>    rust: auxiliary: make Driver trait lifetime-parameterized
>    rust: auxiliary: generalize Registration over ForLt
>    samples: rust: rust_driver_auxiliary: showcase lifetime-bound
>      registration data
>    rust: usb: make Driver trait lifetime-parameterized
>    rust: i2c: make Driver trait lifetime-parameterized
>    rust: pci: make Bar lifetime-parameterized
>    rust: io: make IoMem and ExclusiveIoMem lifetime-parameterized
>    samples: rust: rust_driver_pci: use HRT lifetime for Bar
>    rust: driver-core: rename 'a lifetime to 'bound
>    gpu: nova-core: rename 'a lifetime to 'bound
>    gpu: nova-core: use HRT lifetime for Bar
>    gpu: nova-core: unregister sysmem flush page from Drop
>    gpu: nova-core: replace ARef<Device> with &'bound Device in
>      SysmemFlush
>    gpu: drm: tyr: use HRT lifetime for IoMem
> 
> Gary Guo (1):
>    rust: types: add `ForLt` trait for higher-ranked lifetime support
> 
>   drivers/base/dd.c                        |   2 +-
>   drivers/cpufreq/rcpufreq_dt.rs           |  10 +-
>   drivers/gpu/drm/nova/driver.rs           |   9 +-
>   drivers/gpu/drm/tyr/driver.rs            |  24 ++-
>   drivers/gpu/drm/tyr/gpu.rs               |  62 +++---
>   drivers/gpu/drm/tyr/regs.rs              |  21 +-
>   drivers/gpu/nova-core/driver.rs          |  48 ++---
>   drivers/gpu/nova-core/fb.rs              |  31 ++-
>   drivers/gpu/nova-core/firmware/gsp.rs    |   8 +-
>   drivers/gpu/nova-core/gpu.rs             |  38 ++--
>   drivers/gpu/nova-core/gsp/commands.rs    |  10 +-
>   drivers/gpu/nova-core/gsp/fw/commands.rs |   4 +-
>   drivers/gpu/nova-core/nova_core.rs       |   4 +-
>   drivers/pwm/pwm_th1520.rs                |  14 +-
>   include/linux/device/driver.h            |   4 +-
>   rust/Makefile                            |   1 +
>   rust/kernel/auxiliary.rs                 | 132 +++++++++----
>   rust/kernel/cpufreq.rs                   |   8 +-
>   rust/kernel/device.rs                    |  79 +++++---
>   rust/kernel/devres.rs                    |  16 +-
>   rust/kernel/driver.rs                    |  44 +++--
>   rust/kernel/i2c.rs                       | 130 +++++++-----
>   rust/kernel/io/mem.rs                    | 131 ++++++------
>   rust/kernel/pci.rs                       |  89 ++++++---
>   rust/kernel/pci/io.rs                    |  68 ++++---
>   rust/kernel/pci/irq.rs                   |  38 ++--
>   rust/kernel/platform.rs                  | 120 +++++++----
>   rust/kernel/types.rs                     |   4 +
>   rust/kernel/types/for_lt.rs              | 117 +++++++++++
>   rust/kernel/usb.rs                       |  94 +++++----
>   rust/macros/for_lt.rs                    | 242 +++++++++++++++++++++++
>   rust/macros/lib.rs                       |  12 ++
>   samples/rust/rust_debugfs.rs             |  10 +-
>   samples/rust/rust_dma.rs                 |   9 +-
>   samples/rust/rust_driver_auxiliary.rs    |  53 +++--
>   samples/rust/rust_driver_i2c.rs          |  18 +-
>   samples/rust/rust_driver_pci.rs          |  93 ++++-----
>   samples/rust/rust_driver_platform.rs     |  12 +-
>   samples/rust/rust_driver_usb.rs          |  14 +-
>   samples/rust/rust_i2c_client.rs          |  12 +-
>   samples/rust/rust_soc.rs                 |  12 +-
>   41 files changed, 1220 insertions(+), 627 deletions(-)
>   create mode 100644 rust/kernel/types/for_lt.rs
>   create mode 100644 rust/macros/for_lt.rs
>
Re: [PATCH v2 00/25] rust: device: Higher-Ranked Lifetime Types for device drivers
Posted by Danilo Krummrich 1 month ago
On Thu May 7, 2026 at 2:14 PM CEST, Dirk Behme wrote:
> I have applied this series together with [1] on top of 7.1.0-rc1. I made 
> some adaptions to local changes (e.g. my ARM64 TMU interrupt test) and 
> boot tested it. Several parts this patch series touches (e.g. PCI, 
> auxiliary, gpu) I might not use or even don't have it enabled. So I 
> don't know if this is worth mentioning
>
> Tested-by: Dirk Behme <dirk.behme@de.bosch.com>
>
> Please feel free to ignore this, then.

Thanks Dirk! Any test coverage is valuable and much appreciated.