rust/kernel/drm/gpuvm/vm_bo.rs

Source file repositories/reference/linux-study-clean/rust/kernel/drm/gpuvm/vm_bo.rs

File Facts

System
Linux kernel
Corpus path
rust/kernel/drm/gpuvm/vm_bo.rs
Extension
.rs
Size
9715 bytes
Lines
250
Domain
Rust Kernel Layer
Bucket
Rust API Membrane
Inferred role
Rust Kernel Layer: implementation source
Status
source implementation candidate

Why This File Exists

Rust-side wrappers and abstractions around kernel C APIs, ownership contracts, allocation, synchronization, and module integration.

Dependency Surface

Detected Declarations

Annotated Snippet

fn inc_ref(&self) {
        // SAFETY: By type invariants, the allocation is managed by the refcount in `self.inner`.
        unsafe { bindings::drm_gpuvm_bo_get(self.inner.get()) };
    }

    unsafe fn dec_ref(obj: NonNull<Self>) {
        // CAST: `drm_gpuvm_bo` is first field of repr(C) struct.
        // SAFETY: By type invariants, the allocation is managed by the refcount in `self.inner`.
        // This GPUVM instance uses immediate mode, so we may put the refcount using the deferred
        // mechanism.
        unsafe { bindings::drm_gpuvm_bo_put_deferred(obj.as_ptr().cast()) };
    }
}

impl<T: DriverGpuVm> PartialEq for GpuVmBo<T> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        core::ptr::eq(self.as_raw(), other.as_raw())
    }
}
impl<T: DriverGpuVm> Eq for GpuVmBo<T> {}

impl<T: DriverGpuVm> GpuVmBo<T> {
    /// The function pointer for allocating a GpuVmBo stored in the gpuvm vtable.
    ///
    /// Allocation is always implemented according to [`Self::vm_bo_alloc`], but it is set to
    /// `None` if the default gpuvm behavior is the same as `vm_bo_alloc`.
    ///
    /// This may be `Some` even if `FREE_FN` is `None`, or vice-versa.
    pub(super) const ALLOC_FN: Option<unsafe extern "C" fn() -> *mut bindings::drm_gpuvm_bo> = {
        use core::alloc::Layout;
        let base = Layout::new::<bindings::drm_gpuvm_bo>();
        let rust = Layout::new::<Self>();
        assert!(base.size() <= rust.size());
        if base.size() != rust.size() || base.align() != rust.align() {
            Some(Self::vm_bo_alloc)
        } else {
            // This causes GPUVM to allocate a `GpuVmBo<T>` with `kzalloc(sizeof(drm_gpuvm_bo))`.
            None
        }
    };

    /// The function pointer for freeing a GpuVmBo stored in the gpuvm vtable.
    ///
    /// Freeing is always implemented according to [`Self::vm_bo_free`], but it is set to `None` if
    /// the default gpuvm behavior is the same as `vm_bo_free`.
    ///
    /// This may be `Some` even if `ALLOC_FN` is `None`, or vice-versa.
    pub(super) const FREE_FN: Option<unsafe extern "C" fn(*mut bindings::drm_gpuvm_bo)> = {
        if core::mem::needs_drop::<Self>() {
            Some(Self::vm_bo_free)
        } else {
            // This causes GPUVM to free a `GpuVmBo<T>` with `kfree`.
            None
        }
    };

    /// Custom function for allocating a `drm_gpuvm_bo`.
    ///
    /// # Safety
    ///
    /// Always safe to call.
    unsafe extern "C" fn vm_bo_alloc() -> *mut bindings::drm_gpuvm_bo {
        let raw_ptr = KBox::<Self>::new_uninit(GFP_KERNEL | __GFP_ZERO)
            .map(KBox::into_raw)
            .unwrap_or(ptr::null_mut());

        // CAST: `drm_gpuvm_bo` is first field of `Self`.
        raw_ptr.cast()
    }

    /// Custom function for freeing a `drm_gpuvm_bo`.
    ///
    /// # Safety
    ///
    /// The pointer must have been allocated with [`GpuVmBo::ALLOC_FN`], and must not be used after
    /// this call.
    unsafe extern "C" fn vm_bo_free(ptr: *mut bindings::drm_gpuvm_bo) {
        // CAST: `drm_gpuvm_bo` is first field of `Self`.
        // SAFETY:
        // * The ptr was allocated from kmalloc with the layout of `GpuVmBo<T>`.
        // * `ptr->inner` has no destructor.
        // * `ptr->data` contains a valid `T::VmBoData` that we can drop.
        drop(unsafe { KBox::<Self>::from_raw(ptr.cast()) });
    }

    /// Access this [`GpuVmBo`] from a raw pointer.
    ///
    /// # Safety
    ///

Annotation

Implementation Notes