Re: [PATCH v7 5/7] drm/tyr: add a kernel buffer object
Daniel Almeida <[email protected]>
| Newsgroups | org.kernel.vger.rust-for-linux,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
> On 14 Jul 2026, at 00:18, Deborah Brouwer <[email protected]> wrote: > > Introduce a buffer object type (KernelBo) for internal driver allocations > that are managed by the kernel rather than userspace. > > KernelBo wraps a GEM shmem object and automatically handles GPU virtual > address space mapping during creation and unmapping on drop. This provides > a safe and convenient way for the driver to both allocate and clean up > internal buffers for kernel-managed resources. > > Co-developed-by: Boris Brezillon <[email protected]> > Signed-off-by: Boris Brezillon <[email protected]> > Signed-off-by: Deborah Brouwer <[email protected]> > --- > drivers/gpu/drm/tyr/gem.rs | 101 +++++++++++++++++++++++++++++++++++++++++++-- > 1 file changed, 97 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/tyr/gem.rs b/drivers/gpu/drm/tyr/gem.rs > index c28be61a01bb..47a05a33388e 100644 > --- a/drivers/gpu/drm/tyr/gem.rs > +++ b/drivers/gpu/drm/tyr/gem.rs > @@ -4,18 +4,29 @@ > //! This module provides buffer object (BO) management functionality using > //! DRM's GEM subsystem with shmem backing. > > +use core::ops::Range; > + > use kernel::{ > drm::gem::{ > self, > shmem, // > }, > prelude::*, > - sync::aref::ARef, // > + sync::{ > + aref::ARef, > + Arc, // > + }, // > }; > > -use crate::driver::{ > - TyrDrmDevice, > - TyrDrmDriver, // > +use crate::{ > + driver::{ > + TyrDrmDevice, > + TyrDrmDriver, // > + }, > + vm::{ > + Vm, > + VmMapFlags, // > + }, > }; > > /// Tyr's DriverObject type for GEM objects. > @@ -56,3 +67,85 @@ pub(crate) fn new_dummy_object(ddev: &TyrDrmDevice) -> Result<ARef<Bo>> { > > Ok(bo) > } > + > +/// Specifies how to choose a GPU virtual address for a [`KernelBo`]. > +/// An automatic VA allocation strategy will be added in the future. > +pub(crate) enum KernelBoVaAlloc { > + /// Explicit VA address specified by the caller. > + #[expect(dead_code)] > + Explicit(u64), > +} > + > +/// A kernel-owned buffer object with automatic GPU virtual address mapping. > +/// > +/// This structure represents a buffer object that is created and managed entirely > +/// by the kernel driver, as opposed to userspace-created GEM objects. It combines > +/// a GEM object with automatic GPU virtual address (VA) space mapping and cleanup. > +/// > +/// When dropped, the buffer is automatically unmapped from the GPU VA space. > +pub(crate) struct KernelBo<'bound> { > + /// The underlying GEM buffer object. > + #[expect(dead_code)] > + pub(crate) bo: ARef<Bo>, Can we make this private? > + /// The GPU VM this buffer is mapped into. > + vm: Arc<Vm<'bound>>, > + /// The GPU VA range occupied by this buffer. > + va_range: Range<u64>, > +} > + > +impl<'bound> KernelBo<'bound> { > + /// Creates a new kernel-owned buffer object and maps it into GPU VA space. > + /// > + /// This function allocates a new shmem-backed GEM object and immediately maps > + /// it into the specified GPU virtual memory space. The mapping is automatically > + /// cleaned up when the [`KernelBo`] is dropped. > + #[expect(dead_code)] > + pub(crate) fn new( > + ddev: &TyrDrmDevice, > + vm: Arc<Vm<'bound>>, > + size: u64, > + va_alloc: KernelBoVaAlloc, > + flags: VmMapFlags, > + ) -> Result<Self> { > + if size == 0 { > + pr_err!("Cannot create KernelBo with size 0\n"); > + return Err(EINVAL); > + } > + > + let KernelBoVaAlloc::Explicit(va) = va_alloc; > + > + let bo = Bo::new( > + ddev, > + size as usize, As a general rule, let’s try our best to reduce the number of `as` casts. Let’s go with usize::try_from > + shmem::ObjectConfig { > + map_wc: true, > + parent_resv_obj: None, > + }, > + BoCreateArgs { flags: 0 }, > + )?; > + > + vm.map_bo_range(&bo, 0, size, va, flags)?; > + > + Ok(KernelBo { > + bo, > + vm, > + va_range: va..(va + size), > + }) > + } > +} > + > +impl Drop for KernelBo<'_> { > + fn drop(&mut self) { > + let va = self.va_range.start; > + let size = self.va_range.end - self.va_range.start; > + > + if let Err(e) = self.vm.unmap_range(va, size) { > + pr_err!( > + "Failed to unmap KernelBo range {:#x}..{:#x}: {:?}\n", > + self.va_range.start, > + self.va_range.end, > + e > + ); > + } > + } > +} > > -- > 2.54.0 >