From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from sender4-pp-f112.zoho.com (sender4-pp-f112.zoho.com [136.143.188.112]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BB93823EA90; Fri, 23 Jan 2026 01:57:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=pass smtp.client-ip=136.143.188.112 ARC-Seal:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769133469; cv=pass; b=r7ot0aCFgcw3+DB4lsc3JpPoX3W6bsjpo0/7xzp480OAzYqgpBX5W2RZlDIeBfVj0c1y+ECHrcDPNTx8y8IqVQdc/43dijImCBQRok7TIgLH+3gyzRedu8Y0RkCoVPBrFWYAVkrcO86Bi0klLsx7k+gtfknKQWVphGbGEzHG4yw= ARC-Message-Signature:i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769133469; c=relaxed/simple; bh=jFTNf2kXI5PwADvXclB5lxp0dvxeoznEe0LoPso94S8=; h=Content-Type:Mime-Version:Subject:From:In-Reply-To:Date:Cc: Message-Id:References:To; b=SLlDe9FeR8HegEvGyIoKLmqu0XOw6d5+EMRUNqCwiCRCsblbRch+OTDmIbVZWNQZ/XnOsaBl3CkSin8JtpGTQZ3nPTcqT3SMR4WRts4cjT1bomD3dePkIApA2WGWmKdxlOylsabfGU1NBXDOz93dmOqfC/ZWXf45ZG6RBTkWHSs= ARC-Authentication-Results:i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com; spf=pass smtp.mailfrom=collabora.com; dkim=pass (1024-bit key) header.d=collabora.com header.i=daniel.almeida@collabora.com header.b=lSjyXU5T; arc=pass smtp.client-ip=136.143.188.112 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=collabora.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=collabora.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=collabora.com header.i=daniel.almeida@collabora.com header.b="lSjyXU5T" ARC-Seal: i=1; a=rsa-sha256; t=1769133437; cv=none; d=zohomail.com; s=zohoarc; b=UbeLMybWTx4401DF+sY8XSt5vBV8tOfzEJKBgf8hrZbU7COnBq07LvhWQaNrQe1E+dia4+0Kz9wI4lt8/oNlobnRSIO0BtNAnkWatGWJ0sLFdQ01aZUTmP3pREmCshsAF2nPJZlczrQeVNav2IBflIUbOs97XYYzXreM9Q5smKI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1769133437; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:Subject:To:To:Message-Id:Reply-To; bh=FXmR8QwFsxPz7f3VdjxeTlFtxTPHU0hhqHhOkBUPA5E=; b=CJBqBa+npFMoe1HRdNowIfs03cRsGdLbMHjDHZbe3n6zRl4P4R1Xg+kYu3iltKwqRfRk93SkYezixsId/Oc7hHZL2UhTg+rHFt/NpyVAPDSLzlphN+4HcmHeUCOWELuYDjknMuNIGomzMcbrGMfOvtshGUi3QRyNscgCdbMOXao= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=collabora.com; spf=pass smtp.mailfrom=daniel.almeida@collabora.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1769133437; s=zohomail; d=collabora.com; i=daniel.almeida@collabora.com; h=Content-Type:Mime-Version:Subject:Subject:From:From:In-Reply-To:Date:Date:Cc:Cc:Content-Transfer-Encoding:Message-Id:Message-Id:References:To:To:Reply-To; bh=FXmR8QwFsxPz7f3VdjxeTlFtxTPHU0hhqHhOkBUPA5E=; b=lSjyXU5TQ4Zqpmt0P/XBEkUA5urvcxVk5j5tfVo79ejdGIrZB8nfZdB51DPxjARP /F+zrCoITA208B+oV4StvplsjTOKQwgVT5Wi4sMr2gCr/Yp/qPOxVEWFPwWPVjYl6yj to4cbcFhBbgBK8uguYcTFaPLda0m646mTLP5UGdA= Received: by mx.zohomail.com with SMTPS id 1769133434217459.74454308212034; Thu, 22 Jan 2026 17:57:14 -0800 (PST) Content-Type: text/plain; charset=us-ascii Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.700.81\)) Subject: Re: [PATCH v3 3/3] rust/drm/gem: Use DeviceContext with GEM objects From: Daniel Almeida In-Reply-To: <20260122225057.3589500-4-lyude@redhat.com> Date: Thu, 22 Jan 2026 22:56:43 -0300 Cc: linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, rust-for-linux@vger.kernel.org, Danilo Krummrich , nouveau@lists.freedesktop.org, Miguel Ojeda , Simona Vetter , Alice Ryhl , Shankari Anand , David Airlie , Benno Lossin , Asahi Lina Content-Transfer-Encoding: quoted-printable Message-Id: References: <20260122225057.3589500-1-lyude@redhat.com> <20260122225057.3589500-4-lyude@redhat.com> To: Lyude Paul X-Mailer: Apple Mail (2.3826.700.81) X-ZohoMailClient: External Hi Lyude, > On 22 Jan 2026, at 19:46, Lyude Paul wrote: >=20 > Now that we have the ability to represent the context in which a DRM = device > is in at compile-time, we can start carrying around this context with = GEM > object types in order to allow a driver to safely create GEM objects = before > a DRM device has registered with userspace. >=20 > Signed-off-by: Lyude Paul > --- > drivers/gpu/drm/nova/driver.rs | 2 +- > drivers/gpu/drm/nova/gem.rs | 11 +++--- > drivers/gpu/drm/tyr/driver.rs | 2 +- > drivers/gpu/drm/tyr/gem.rs | 3 +- > rust/kernel/drm/device.rs | 14 ++++---- > rust/kernel/drm/driver.rs | 2 +- > rust/kernel/drm/gem/mod.rs | 64 +++++++++++++++++++++++----------- > 7 files changed, 63 insertions(+), 35 deletions(-) >=20 > diff --git a/drivers/gpu/drm/nova/driver.rs = b/drivers/gpu/drm/nova/driver.rs > index 8cea5f68c3b04..2c13261450406 100644 > --- a/drivers/gpu/drm/nova/driver.rs > +++ b/drivers/gpu/drm/nova/driver.rs > @@ -67,7 +67,7 @@ fn probe(adev: &auxiliary::Device, _info: = &Self::IdInfo) -> impl PinInit impl drm::Driver for NovaDriver { > type Data =3D NovaData; > type File =3D File; > - type Object =3D gem::Object; > + type Object =3D gem::Object; >=20 > const INFO: drm::DriverInfo =3D INFO; >=20 > diff --git a/drivers/gpu/drm/nova/gem.rs b/drivers/gpu/drm/nova/gem.rs > index 6ccfa5da57617..f6e98b9db58d8 100644 > --- a/drivers/gpu/drm/nova/gem.rs > +++ b/drivers/gpu/drm/nova/gem.rs > @@ -2,7 +2,7 @@ >=20 > use kernel::{ > drm, > - drm::{gem, gem::BaseObject}, > + drm::{gem, gem::BaseObject, DeviceContext}, > page, > prelude::*, > sync::aref::ARef, > @@ -20,20 +20,23 @@ pub(crate) struct NovaObject {} > impl gem::DriverObject for NovaObject { > type Driver =3D NovaDriver; >=20 > - fn new(_dev: &NovaDevice, _size: usize) -> impl PinInit { > + fn new(_dev: &NovaDevice, _size: usize) = -> impl PinInit { > try_pin_init!(NovaObject {}) > } > } >=20 > impl NovaObject { > /// Create a new DRM GEM object. > - pub(crate) fn new(dev: &NovaDevice, size: usize) -> = Result>> { > + pub(crate) fn new( > + dev: &NovaDevice, > + size: usize, > + ) -> Result>> { > if size =3D=3D 0 { > return Err(EINVAL); > } > let aligned_size =3D page::page_align(size).ok_or(EINVAL)?; >=20 > - gem::Object::new(dev, aligned_size) > + gem::Object::::new(dev, aligned_size) > } >=20 > /// Look up a GEM object handle for a `File` and return an = `ObjectRef` for it. > diff --git a/drivers/gpu/drm/tyr/driver.rs = b/drivers/gpu/drm/tyr/driver.rs > index e73c56659ea75..03e337d95521c 100644 > --- a/drivers/gpu/drm/tyr/driver.rs > +++ b/drivers/gpu/drm/tyr/driver.rs > @@ -177,7 +177,7 @@ fn drop(self: Pin<&mut Self>) { > impl drm::Driver for TyrDriver { > type Data =3D TyrData; > type File =3D File; > - type Object =3D drm::gem::Object; > + type Object =3D = drm::gem::Object; >=20 > const INFO: drm::DriverInfo =3D INFO; >=20 > diff --git a/drivers/gpu/drm/tyr/gem.rs b/drivers/gpu/drm/tyr/gem.rs > index 1273bf89dbd5d..00804f8c14bd4 100644 > --- a/drivers/gpu/drm/tyr/gem.rs > +++ b/drivers/gpu/drm/tyr/gem.rs > @@ -3,6 +3,7 @@ > use crate::driver::TyrDevice; > use crate::driver::TyrDriver; > use kernel::drm::gem; > +use kernel::drm::DeviceContext; > use kernel::prelude::*; >=20 > /// GEM Object inner driver data > @@ -12,7 +13,7 @@ pub(crate) struct TyrObject {} > impl gem::DriverObject for TyrObject { > type Driver =3D TyrDriver; >=20 > - fn new(_dev: &TyrDevice, _size: usize) -> impl PinInit { > + fn new(_dev: &TyrDevice, _size: usize) = -> impl PinInit { > try_pin_init!(TyrObject {}) > } > } > diff --git a/rust/kernel/drm/device.rs b/rust/kernel/drm/device.rs > index 0e81957cf8c28..4c03105e6a817 100644 > --- a/rust/kernel/drm/device.rs > +++ b/rust/kernel/drm/device.rs > @@ -163,13 +163,13 @@ impl UnregisteredDevice { > master_set: None, > master_drop: None, > debugfs_init: None, > - gem_create_object: T::Object::ALLOC_OPS.gem_create_object, > - prime_handle_to_fd: T::Object::ALLOC_OPS.prime_handle_to_fd, > - prime_fd_to_handle: T::Object::ALLOC_OPS.prime_fd_to_handle, > - gem_prime_import: T::Object::ALLOC_OPS.gem_prime_import, > - gem_prime_import_sg_table: = T::Object::ALLOC_OPS.gem_prime_import_sg_table, > - dumb_create: T::Object::ALLOC_OPS.dumb_create, > - dumb_map_offset: T::Object::ALLOC_OPS.dumb_map_offset, > + gem_create_object: = T::Object::::ALLOC_OPS.gem_create_object, > + prime_handle_to_fd: = T::Object::::ALLOC_OPS.prime_handle_to_fd, > + prime_fd_to_handle: = T::Object::::ALLOC_OPS.prime_fd_to_handle, > + gem_prime_import: = T::Object::::ALLOC_OPS.gem_prime_import, > + gem_prime_import_sg_table: = T::Object::::ALLOC_OPS.gem_prime_import_sg_table, > + dumb_create: T::Object::::ALLOC_OPS.dumb_create, > + dumb_map_offset: = T::Object::::ALLOC_OPS.dumb_map_offset, Why are we specifically going with Uninit here? > show_fdinfo: None, > fbdev_probe: None, >=20 > diff --git a/rust/kernel/drm/driver.rs b/rust/kernel/drm/driver.rs > index a16605b407159..94ebaf19ac069 100644 > --- a/rust/kernel/drm/driver.rs > +++ b/rust/kernel/drm/driver.rs > @@ -110,7 +110,7 @@ pub trait Driver { > type Data: Sync + Send; >=20 > /// The type used to manage memory for this driver. > - type Object: AllocImpl; > + type Object: AllocImpl; >=20 > /// The type used to represent a DRM File (client) > type File: drm::file::DriverFile; > diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs > index b4199945db378..3af9f52f8eda4 100644 > --- a/rust/kernel/drm/gem/mod.rs > +++ b/rust/kernel/drm/gem/mod.rs > @@ -8,6 +8,10 @@ > bindings, > drm::{ > self, > + device::{ > + DeviceContext, > + Registered, // > + }, > driver::{ > AllocImpl, > AllocOps, // > @@ -22,6 +26,7 @@ > types::Opaque, > }; > use core::{ > + marker::PhantomData, > ops::Deref, > ptr::NonNull, // > }; > @@ -33,21 +38,30 @@ > /// [`DriverFile`]: drm::file::DriverFile > pub type DriverFile =3D drm::File<<::Driver as = drm::Driver>::File>; >=20 > +/// A type alias for retrieving the current [`AllocImpl`] for a given = [`DriverObject`]. > +/// > +/// [`Driver`]: drm::Driver > +pub type DriverAllocImpl =3D > + <::Driver as drm::Driver>::Object; Should this be a follow up patch instead? > + > /// GEM object functions, which must be implemented by drivers. > pub trait DriverObject: Sync + Send + Sized { > /// Parent `Driver` for this object. > type Driver: drm::Driver; >=20 > /// Create a new driver data object for a GEM object of a given = size. > - fn new(dev: &drm::Device, size: usize) -> impl = PinInit; > + fn new( > + dev: &drm::Device, > + size: usize, > + ) -> impl PinInit; >=20 > /// Open a new handle to an existing object, associated with a = File. > - fn open(_obj: &::Object, _file: = &DriverFile) -> Result { > + fn open(_obj: &DriverAllocImpl, _file: &DriverFile) = -> Result { > Ok(()) > } >=20 > /// Close a handle to an existing object, associated with a File. > - fn close(_obj: &::Object, _file: = &DriverFile) {} > + fn close(_obj: &DriverAllocImpl, _file: &DriverFile) = {} > } >=20 > /// Trait that represents a GEM object subtype > @@ -73,9 +87,12 @@ extern "C" fn open_callback( > // SAFETY: `open_callback` is only ever called with a valid = pointer to a `struct drm_file`. > let file =3D unsafe { DriverFile::::from_raw(raw_file) }; >=20 > - // SAFETY: `open_callback` is specified in the AllocOps structure = for `DriverObject`, > - // ensuring that `raw_obj` is contained within a = `DriverObject` > - let obj =3D unsafe { <::Object as = IntoGEMObject>::from_raw(raw_obj) }; > + // SAFETY: > + // * `open_callback` is specified in the AllocOps structure for = `DriverObject`, ensuring that > + // `raw_obj` is contained within a `DriverAllocImpl` > + // * It is only possible for `open_callback` to be called after = device registration, ensuring > + // that the object's device is in the `Registered` state. > + let obj: &DriverAllocImpl =3D unsafe { = IntoGEMObject::from_raw(raw_obj) }; >=20 > match T::open(obj, file) { > Err(e) =3D> e.to_errno(), > @@ -92,12 +109,12 @@ extern "C" fn close_callback( >=20 > // SAFETY: `close_callback` is specified in the AllocOps structure = for `Object`, ensuring > // that `raw_obj` is indeed contained within a `Object`. > - let obj =3D unsafe { <::Object as = IntoGEMObject>::from_raw(raw_obj) }; > + let obj: &DriverAllocImpl =3D unsafe { = IntoGEMObject::from_raw(raw_obj) }; >=20 > T::close(obj, file); > } >=20 > -impl IntoGEMObject for Object { > +impl IntoGEMObject for Object { > fn as_raw(&self) -> *mut bindings::drm_gem_object { > self.obj.get() > } > @@ -105,7 +122,7 @@ fn as_raw(&self) -> *mut bindings::drm_gem_object = { > unsafe fn from_raw<'a>(self_ptr: *mut bindings::drm_gem_object) -> = &'a Self { > // SAFETY: `obj` is guaranteed to be in an `Object` via the = safety contract of this > // function > - unsafe { &*crate::container_of!(Opaque::cast_from(self_ptr), = Object, obj) } > + unsafe { &*crate::container_of!(Opaque::cast_from(self_ptr), = Object, obj) } > } > } >=20 > @@ -122,7 +139,7 @@ fn size(&self) -> usize { > fn create_handle(&self, file: &drm::File) -> Result > where > Self: AllocImpl, > - D: drm::Driver, > + D: drm::Driver =3D Self, File =3D F>, > F: drm::file::DriverFile, > { > let mut handle: u32 =3D 0; > @@ -137,7 +154,7 @@ fn create_handle(&self, file: &drm::File) = -> Result > fn lookup_handle(file: &drm::File, handle: u32) -> = Result> > where > Self: AllocImpl, > - D: drm::Driver, > + D: drm::Driver =3D Self, File =3D F>, > F: drm::file::DriverFile, > { > // SAFETY: The arguments are all valid per the type = invariants. > @@ -177,16 +194,18 @@ impl BaseObject for T {} > /// > /// # Invariants > /// > -/// - `self.obj` is a valid instance of a `struct drm_gem_object`. > +/// * `self.obj` is a valid instance of a `struct drm_gem_object`. > +/// * Any type invariants of `Ctx` apply to the parent DRM device for = this GEM object. > #[repr(C)] > #[pin_data] > -pub struct Object { > +pub struct Object { > obj: Opaque, > #[pin] > data: T, > + _ctx: PhantomData, > } >=20 > -impl Object { > +impl Object { > const OBJECT_FUNCS: bindings::drm_gem_object_funcs =3D = bindings::drm_gem_object_funcs { > free: Some(Self::free_callback), > open: Some(open_callback::), > @@ -206,11 +225,12 @@ impl Object { > }; >=20 > /// Create a new GEM object. > - pub fn new(dev: &drm::Device, size: usize) -> = Result> { > + pub fn new(dev: &drm::Device, size: usize) -> = Result> { > let obj: Pin> =3D KBox::pin_init( > try_pin_init!(Self { > obj: Opaque::new(bindings::drm_gem_object::default()), > data <- T::new(dev, size), > + _ctx: PhantomData, > }), > GFP_KERNEL, > )?; > @@ -219,6 +239,8 @@ pub fn new(dev: &drm::Device, size: = usize) -> Result> { > unsafe { (*obj.as_raw()).funcs =3D &Self::OBJECT_FUNCS }; >=20 > // SAFETY: The arguments are all valid per the type = invariants. > + // INVARIANT: We use `dev` for creating the GEM object, which = is known to be in state `Ctx` - > + // ensuring that the GEM object's pointer to the DRM device = is always in the same state. > to_result(unsafe { bindings::drm_gem_object_init(dev.as_raw(), = obj.obj.get(), size) })?; >=20 > // SAFETY: We will never move out of `Self` as `ARef` is = always treated as pinned. > @@ -232,13 +254,15 @@ pub fn new(dev: &drm::Device, size: = usize) -> Result> { > } >=20 > /// Returns the `Device` that owns this GEM object. > - pub fn dev(&self) -> &drm::Device { > + pub fn dev(&self) -> &drm::Device { > // 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. > + // - Any type invariants of `Ctx` are upheld by using the = same `Ctx` for the `Device` we > + // return. > unsafe { drm::Device::from_raw((*self.as_raw()).dev) } > } >=20 > @@ -264,7 +288,7 @@ extern "C" fn free_callback(obj: *mut = bindings::drm_gem_object) { > } >=20 > // SAFETY: Instances of `Object` are always reference-counted. > -unsafe impl crate::sync::aref::AlwaysRefCounted for = Object { > +unsafe impl 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()) }; > @@ -279,9 +303,9 @@ unsafe fn dec_ref(obj: NonNull) { > } > } >=20 > -impl super::private::Sealed for Object {} > +impl super::private::Sealed for = Object {} >=20 > -impl Deref for Object { > +impl Deref for Object { > type Target =3D T; >=20 > fn deref(&self) -> &Self::Target { > @@ -289,7 +313,7 @@ fn deref(&self) -> &Self::Target { > } > } >=20 > -impl AllocImpl for Object { > +impl AllocImpl for Object { > type Driver =3D T::Driver; >=20 > const ALLOC_OPS: AllocOps =3D AllocOps { > --=20 > 2.52.0 >=20 >=20