Skip to content

Commit 2cd17f6

Browse files
hoshinolinamarcan
authored andcommitted
rust: drm: gem: Allow pinning GEM object driver data
This requires type_alias_impl_trait. Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent e7a26cb commit 2cd17f6

1 file changed

Lines changed: 31 additions & 11 deletions

File tree

rust/kernel/drm/gem/mod.rs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ use crate::{
1212
error::{to_result, Result},
1313
prelude::*,
1414
};
15-
use core::{mem, ops::Deref, ops::DerefMut};
15+
use core::{marker::PhantomPinned, mem, ops::Deref, ops::DerefMut};
1616

1717
/// GEM object functions, which must be implemented by drivers.
1818
pub trait BaseDriverObject<T: BaseObject>: Sync + Send + Sized {
19+
/// The return type of the new() function. Should be `impl PinInit<Self, Error>`.
20+
/// TODO: Remove this when return_position_impl_trait_in_trait is stable.
21+
type Initializer: PinInit<Self, Error>;
22+
1923
/// Create a new driver data object for a GEM object of a given size.
20-
fn new(dev: &device::Device<T::Driver>, size: usize) -> Result<Self>;
24+
fn new(dev: &device::Device<T::Driver>, size: usize) -> Self::Initializer;
2125

2226
/// Open a new handle to an existing object, associated with a File.
2327
fn open(
@@ -188,14 +192,21 @@ impl<T: IntoGEMObject> BaseObject for T {}
188192

189193
/// A base GEM object.
190194
#[repr(C)]
195+
#[pin_data]
191196
pub struct Object<T: DriverObject> {
192197
obj: bindings::drm_gem_object,
193198
// The DRM core ensures the Device exists as long as its objects exist, so we don't need to
194199
// manage the reference count here.
195200
dev: *const bindings::drm_device,
201+
#[pin]
196202
inner: T,
203+
#[pin]
204+
_p: PhantomPinned,
197205
}
198206

207+
// SAFETY: This struct is safe to zero-initialize
208+
unsafe impl init::Zeroable for bindings::drm_gem_object {}
209+
199210
impl<T: DriverObject> Object<T> {
200211
/// The size of this object's structure.
201212
pub const SIZE: usize = mem::size_of::<Self>();
@@ -217,23 +228,31 @@ impl<T: DriverObject> Object<T> {
217228
};
218229

219230
/// Create a new GEM object.
220-
pub fn new(dev: &device::Device<T::Driver>, size: usize) -> Result<UniqueObjectRef<Self>> {
221-
let mut obj: Box<Self> = Box::try_new(Self {
231+
pub fn new(dev: &device::Device<T::Driver>, size: usize) -> Result<Pin<UniqueObjectRef<Self>>> {
232+
let obj: Pin<Box<Self>> = Box::pin_init(try_pin_init!(Self {
222233
// SAFETY: This struct is expected to be zero-initialized
223-
obj: unsafe { mem::zeroed() },
234+
obj: bindings::drm_gem_object {
235+
funcs: &Self::OBJECT_FUNCS,
236+
..Default::default()
237+
},
238+
inner <- T::new(dev, size),
224239
// SAFETY: The drm subsystem guarantees that the drm_device will live as long as
225240
// the GEM object lives, so we can conjure a reference out of thin air.
226241
dev: dev.drm.get(),
227-
inner: T::new(dev, size)?,
228-
})?;
242+
_p: PhantomPinned
243+
}))?;
229244

230-
obj.obj.funcs = &Self::OBJECT_FUNCS;
231245
to_result(unsafe {
232-
bindings::drm_gem_object_init(dev.raw() as *mut _, &mut obj.obj, size)
246+
bindings::drm_gem_object_init(dev.raw() as *mut _, &obj.obj as *const _ as *mut _, size)
233247
})?;
234248

235-
let obj_ref = UniqueObjectRef {
236-
ptr: Box::leak(obj),
249+
// SAFETY: We never move out of self
250+
let obj_ref = unsafe {
251+
Pin::new_unchecked(UniqueObjectRef {
252+
// SAFETY: We never move out of the Box
253+
ptr: Box::leak(Pin::into_inner_unchecked(obj)),
254+
_p: PhantomPinned,
255+
})
237256
};
238257

239258
Ok(obj_ref)
@@ -316,6 +335,7 @@ pub struct UniqueObjectRef<T: IntoGEMObject> {
316335
// Invariant: the pointer is valid and initialized, and this ObjectRef owns the only reference
317336
// to it.
318337
ptr: *mut T,
338+
_p: PhantomPinned,
319339
}
320340

321341
impl<T: IntoGEMObject> UniqueObjectRef<T> {

0 commit comments

Comments
 (0)