diff options
Diffstat (limited to 'rust/kernel/miscdevice.rs')
| -rw-r--r-- | rust/kernel/miscdevice.rs | 45 | 
1 files changed, 45 insertions, 0 deletions
| diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs index fa9ecc42602a..9d9771247c38 100644 --- a/rust/kernel/miscdevice.rs +++ b/rust/kernel/miscdevice.rs @@ -14,6 +14,7 @@ use crate::{      error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR},      ffi::{c_int, c_long, c_uint, c_ulong},      fs::File, +    mm::virt::VmaNew,      prelude::*,      seq_file::SeqFile,      str::CStr, @@ -119,6 +120,22 @@ pub trait MiscDevice: Sized {          drop(device);      } +    /// Handle for mmap. +    /// +    /// This function is invoked when a user space process invokes the `mmap` system call on +    /// `file`. The function is a callback that is part of the VMA initializer. The kernel will do +    /// initial setup of the VMA before calling this function. The function can then interact with +    /// the VMA initialization by calling methods of `vma`. If the function does not return an +    /// error, the kernel will complete initialization of the VMA according to the properties of +    /// `vma`. +    fn mmap( +        _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>, +        _file: &File, +        _vma: &VmaNew, +    ) -> Result { +        build_error!(VTABLE_DEFAULT_ERROR) +    } +      /// Handler for ioctls.      ///      /// The `cmd` argument is usually manipulated using the utilties in [`kernel::ioctl`]. @@ -226,6 +243,33 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {      /// # Safety      ///      /// `file` must be a valid file that is associated with a `MiscDeviceRegistration<T>`. +    /// `vma` must be a vma that is currently being mmap'ed with this file. +    unsafe extern "C" fn mmap( +        file: *mut bindings::file, +        vma: *mut bindings::vm_area_struct, +    ) -> c_int { +        // SAFETY: The mmap call of a file can access the private data. +        let private = unsafe { (*file).private_data }; +        // SAFETY: This is a Rust Miscdevice, so we call `into_foreign` in `open` and +        // `from_foreign` in `release`, and `fops_mmap` is guaranteed to be called between those +        // two operations. +        let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) }; +        // SAFETY: The caller provides a vma that is undergoing initial VMA setup. +        let area = unsafe { VmaNew::from_raw(vma) }; +        // SAFETY: +        // * The file is valid for the duration of this call. +        // * There is no active fdget_pos region on the file on this thread. +        let file = unsafe { File::from_raw_file(file) }; + +        match T::mmap(device, file, area) { +            Ok(()) => 0, +            Err(err) => err.to_errno(), +        } +    } + +    /// # Safety +    /// +    /// `file` must be a valid file that is associated with a `MiscDeviceRegistration<T>`.      unsafe extern "C" fn ioctl(file: *mut bindings::file, cmd: c_uint, arg: c_ulong) -> c_long {          // SAFETY: The ioctl call of a file can access the private data.          let private = unsafe { (*file).private_data }; @@ -291,6 +335,7 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {      const VTABLE: bindings::file_operations = bindings::file_operations {          open: Some(Self::open),          release: Some(Self::release), +        mmap: if T::HAS_MMAP { Some(Self::mmap) } else { None },          unlocked_ioctl: if T::HAS_IOCTL {              Some(Self::ioctl)          } else { | 
