1 // SPDX-License-Identifier: GPL-2.0 OR MIT 2 3 //! DRM GEM API 4 //! 5 //! C header: [`include/linux/drm/drm_gem.h`](srctree/include/linux/drm/drm_gem.h) 6 7 use crate::{ 8 alloc::flags::*, 9 bindings, drm, 10 drm::driver::{AllocImpl, AllocOps}, 11 error::{to_result, Result}, 12 prelude::*, 13 types::{ARef, Opaque}, 14 }; 15 use core::{mem, ops::Deref, ptr, ptr::NonNull}; 16 17 /// GEM object functions, which must be implemented by drivers. 18 pub trait BaseDriverObject<T: BaseObject>: Sync + Send + Sized { 19 /// Create a new driver data object for a GEM object of a given size. 20 fn new(dev: &drm::Device<T::Driver>, size: usize) -> impl PinInit<Self, Error>; 21 22 /// Open a new handle to an existing object, associated with a File. 23 fn open( 24 _obj: &<<T as IntoGEMObject>::Driver as drm::Driver>::Object, 25 _file: &drm::File<<<T as IntoGEMObject>::Driver as drm::Driver>::File>, 26 ) -> Result { 27 Ok(()) 28 } 29 30 /// Close a handle to an existing object, associated with a File. 31 fn close( 32 _obj: &<<T as IntoGEMObject>::Driver as drm::Driver>::Object, 33 _file: &drm::File<<<T as IntoGEMObject>::Driver as drm::Driver>::File>, 34 ) { 35 } 36 } 37 38 /// Trait that represents a GEM object subtype 39 pub trait IntoGEMObject: Sized + super::private::Sealed { 40 /// Owning driver for this type 41 type Driver: drm::Driver; 42 43 /// Returns a reference to the raw `drm_gem_object` structure, which must be valid as long as 44 /// this owning object is valid. 45 #[allow(clippy::wrong_self_convention)] 46 fn into_gem_obj(&self) -> &Opaque<bindings::drm_gem_object>; 47 48 /// Converts a pointer to a `struct drm_gem_object` into a pointer to `Self`. 49 fn from_gem_obj(obj: *mut bindings::drm_gem_object) -> *mut Self; 50 } 51 52 /// Trait which must be implemented by drivers using base GEM objects. 53 pub trait DriverObject: BaseDriverObject<Object<Self>> { 54 /// Parent `Driver` for this object. 55 type Driver: drm::Driver; 56 } 57 58 extern "C" fn open_callback<T: BaseDriverObject<U>, U: BaseObject>( 59 raw_obj: *mut bindings::drm_gem_object, 60 raw_file: *mut bindings::drm_file, 61 ) -> core::ffi::c_int { 62 // SAFETY: `open_callback` is only ever called with a valid pointer to a `struct drm_file`. 63 let file = unsafe { 64 drm::File::<<<U as IntoGEMObject>::Driver as drm::Driver>::File>::as_ref(raw_file) 65 }; 66 let obj = 67 <<<U as IntoGEMObject>::Driver as drm::Driver>::Object as IntoGEMObject>::from_gem_obj( 68 raw_obj, 69 ); 70 71 // SAFETY: `from_gem_obj()` returns a valid pointer as long as the type is correct and the 72 // `raw_obj` we got is valid. 73 match T::open(unsafe { &*obj }, file) { 74 Err(e) => e.to_errno(), 75 Ok(()) => 0, 76 } 77 } 78 79 extern "C" fn close_callback<T: BaseDriverObject<U>, U: BaseObject>( 80 raw_obj: *mut bindings::drm_gem_object, 81 raw_file: *mut bindings::drm_file, 82 ) { 83 // SAFETY: `open_callback` is only ever called with a valid pointer to a `struct drm_file`. 84 let file = unsafe { 85 drm::File::<<<U as IntoGEMObject>::Driver as drm::Driver>::File>::as_ref(raw_file) 86 }; 87 let obj = 88 <<<U as IntoGEMObject>::Driver as drm::Driver>::Object as IntoGEMObject>::from_gem_obj( 89 raw_obj, 90 ); 91 92 // SAFETY: `from_gem_obj()` returns a valid pointer as long as the type is correct and the 93 // `raw_obj` we got is valid. 94 T::close(unsafe { &*obj }, file); 95 } 96 97 impl<T: DriverObject> IntoGEMObject for Object<T> { 98 type Driver = T::Driver; 99 100 fn into_gem_obj(&self) -> &Opaque<bindings::drm_gem_object> { 101 &self.obj 102 } 103 104 fn from_gem_obj(obj: *mut bindings::drm_gem_object) -> *mut Self { 105 // SAFETY: All of our objects are Object<T>. 106 unsafe { crate::container_of!(obj, Object<T>, obj).cast_mut() } 107 } 108 } 109 110 /// Base operations shared by all GEM object classes 111 pub trait BaseObject 112 where 113 Self: crate::types::AlwaysRefCounted + IntoGEMObject, 114 { 115 /// Returns the size of the object in bytes. 116 fn size(&self) -> usize { 117 // SAFETY: `self.into_gem_obj()` is guaranteed to be a pointer to a valid `struct 118 // drm_gem_object`. 119 unsafe { (*self.into_gem_obj().get()).size } 120 } 121 122 /// Creates a new handle for the object associated with a given `File` 123 /// (or returns an existing one). 124 fn create_handle( 125 &self, 126 file: &drm::File<<<Self as IntoGEMObject>::Driver as drm::Driver>::File>, 127 ) -> Result<u32> { 128 let mut handle: u32 = 0; 129 // SAFETY: The arguments are all valid per the type invariants. 130 to_result(unsafe { 131 bindings::drm_gem_handle_create( 132 file.as_raw().cast(), 133 self.into_gem_obj().get(), 134 &mut handle, 135 ) 136 })?; 137 Ok(handle) 138 } 139 140 /// Looks up an object by its handle for a given `File`. 141 fn lookup_handle( 142 file: &drm::File<<<Self as IntoGEMObject>::Driver as drm::Driver>::File>, 143 handle: u32, 144 ) -> Result<ARef<Self>> { 145 // SAFETY: The arguments are all valid per the type invariants. 146 let ptr = unsafe { bindings::drm_gem_object_lookup(file.as_raw().cast(), handle) }; 147 let ptr = <Self as IntoGEMObject>::from_gem_obj(ptr); 148 let ptr = NonNull::new(ptr).ok_or(ENOENT)?; 149 150 // SAFETY: We take ownership of the reference of `drm_gem_object_lookup()`. 151 Ok(unsafe { ARef::from_raw(ptr) }) 152 } 153 154 /// Creates an mmap offset to map the object from userspace. 155 fn create_mmap_offset(&self) -> Result<u64> { 156 // SAFETY: The arguments are valid per the type invariant. 157 to_result(unsafe { bindings::drm_gem_create_mmap_offset(self.into_gem_obj().get()) })?; 158 159 // SAFETY: The arguments are valid per the type invariant. 160 Ok(unsafe { 161 bindings::drm_vma_node_offset_addr(ptr::addr_of_mut!( 162 (*self.into_gem_obj().get()).vma_node 163 )) 164 }) 165 } 166 } 167 168 impl<T> BaseObject for T where Self: crate::types::AlwaysRefCounted + IntoGEMObject {} 169 170 /// A base GEM object. 171 /// 172 /// Invariants 173 /// 174 /// - `self.obj` is a valid instance of a `struct drm_gem_object`. 175 /// - `self.dev` is always a valid pointer to a `struct drm_device`. 176 #[repr(C)] 177 #[pin_data] 178 pub struct Object<T: DriverObject + Send + Sync> { 179 obj: Opaque<bindings::drm_gem_object>, 180 dev: *const drm::Device<T::Driver>, 181 #[pin] 182 data: T, 183 } 184 185 impl<T: DriverObject> Object<T> { 186 /// The size of this object's structure. 187 pub const SIZE: usize = mem::size_of::<Self>(); 188 189 const OBJECT_FUNCS: bindings::drm_gem_object_funcs = bindings::drm_gem_object_funcs { 190 free: Some(Self::free_callback), 191 open: Some(open_callback::<T, Object<T>>), 192 close: Some(close_callback::<T, Object<T>>), 193 print_info: None, 194 export: None, 195 pin: None, 196 unpin: None, 197 get_sg_table: None, 198 vmap: None, 199 vunmap: None, 200 mmap: None, 201 status: None, 202 vm_ops: core::ptr::null_mut(), 203 evict: None, 204 rss: None, 205 }; 206 207 /// Create a new GEM object. 208 pub fn new(dev: &drm::Device<T::Driver>, size: usize) -> Result<ARef<Self>> { 209 let obj: Pin<KBox<Self>> = KBox::pin_init( 210 try_pin_init!(Self { 211 obj: Opaque::new(bindings::drm_gem_object::default()), 212 data <- T::new(dev, size), 213 // INVARIANT: The drm subsystem guarantees that the `struct drm_device` will live 214 // as long as the GEM object lives. 215 dev, 216 }), 217 GFP_KERNEL, 218 )?; 219 220 // SAFETY: `obj.as_raw()` is guaranteed to be valid by the initialization above. 221 unsafe { (*obj.as_raw()).funcs = &Self::OBJECT_FUNCS }; 222 223 // SAFETY: The arguments are all valid per the type invariants. 224 to_result(unsafe { bindings::drm_gem_object_init(dev.as_raw(), obj.obj.get(), size) })?; 225 226 // SAFETY: We never move out of `Self`. 227 let ptr = KBox::into_raw(unsafe { Pin::into_inner_unchecked(obj) }); 228 229 // SAFETY: `ptr` comes from `KBox::into_raw` and hence can't be NULL. 230 let ptr = unsafe { NonNull::new_unchecked(ptr) }; 231 232 // SAFETY: We take over the initial reference count from `drm_gem_object_init()`. 233 Ok(unsafe { ARef::from_raw(ptr) }) 234 } 235 236 /// Returns the `Device` that owns this GEM object. 237 pub fn dev(&self) -> &drm::Device<T::Driver> { 238 // SAFETY: The DRM subsystem guarantees that the `struct drm_device` will live as long as 239 // the GEM object lives, hence the pointer must be valid. 240 unsafe { &*self.dev } 241 } 242 243 fn as_raw(&self) -> *mut bindings::drm_gem_object { 244 self.obj.get() 245 } 246 247 extern "C" fn free_callback(obj: *mut bindings::drm_gem_object) { 248 // SAFETY: All of our objects are of type `Object<T>`. 249 let this = unsafe { crate::container_of!(obj, Self, obj) }.cast_mut(); 250 251 // SAFETY: The C code only ever calls this callback with a valid pointer to a `struct 252 // drm_gem_object`. 253 unsafe { bindings::drm_gem_object_release(obj) }; 254 255 // SAFETY: All of our objects are allocated via `KBox`, and we're in the 256 // free callback which guarantees this object has zero remaining references, 257 // so we can drop it. 258 let _ = unsafe { KBox::from_raw(this) }; 259 } 260 } 261 262 // SAFETY: Instances of `Object<T>` are always reference-counted. 263 unsafe impl<T: DriverObject> crate::types::AlwaysRefCounted for Object<T> { 264 fn inc_ref(&self) { 265 // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. 266 unsafe { bindings::drm_gem_object_get(self.as_raw()) }; 267 } 268 269 unsafe fn dec_ref(obj: NonNull<Self>) { 270 // SAFETY: `obj` is a valid pointer to an `Object<T>`. 271 let obj = unsafe { obj.as_ref() }; 272 273 // SAFETY: The safety requirements guarantee that the refcount is non-zero. 274 unsafe { bindings::drm_gem_object_put(obj.as_raw()) } 275 } 276 } 277 278 impl<T: DriverObject> super::private::Sealed for Object<T> {} 279 280 impl<T: DriverObject> Deref for Object<T> { 281 type Target = T; 282 283 fn deref(&self) -> &Self::Target { 284 &self.data 285 } 286 } 287 288 impl<T: DriverObject> AllocImpl for Object<T> { 289 const ALLOC_OPS: AllocOps = AllocOps { 290 gem_create_object: None, 291 prime_handle_to_fd: None, 292 prime_fd_to_handle: None, 293 gem_prime_import: None, 294 gem_prime_import_sg_table: None, 295 dumb_create: None, 296 dumb_map_offset: None, 297 }; 298 } 299 300 pub(super) const fn create_fops() -> bindings::file_operations { 301 // SAFETY: As by the type invariant, it is safe to initialize `bindings::file_operations` 302 // zeroed. 303 let mut fops: bindings::file_operations = unsafe { core::mem::zeroed() }; 304 305 fops.owner = core::ptr::null_mut(); 306 fops.open = Some(bindings::drm_open); 307 fops.release = Some(bindings::drm_release); 308 fops.unlocked_ioctl = Some(bindings::drm_ioctl); 309 #[cfg(CONFIG_COMPAT)] 310 { 311 fops.compat_ioctl = Some(bindings::drm_compat_ioctl); 312 } 313 fops.poll = Some(bindings::drm_poll); 314 fops.read = Some(bindings::drm_read); 315 fops.llseek = Some(bindings::noop_llseek); 316 fops.mmap = Some(bindings::drm_gem_mmap); 317 fops.fop_flags = bindings::FOP_UNSIGNED_OFFSET; 318 319 fops 320 } 321