Re: [PATCH] rust/kernel: Add faux device bindings

Thomas Weißschuh
2025-02-06T21:44:42Z

On 2025-02-06 16:04:56-0500, Lyude Paul wrote:
> This introduces a crate for working with faux devices in rust, along with
> adding sample code to show how the API is used. Unlike other types of
> devices, we don't provide any hooks for device probe/removal - since these
> are optional for the faux API and are unnecessary in rust.
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Maíra Canal <mairacanal@riseup.net>
> ---
> rust/bindings/bindings_helper.h | 1 +
> rust/kernel/faux.rs | 60 ++++++++++++++++++++++++++++++++
> rust/kernel/lib.rs | 1 +
> samples/rust/Kconfig | 10 ++++++
> samples/rust/Makefile | 1 +
> samples/rust/rust_driver_faux.rs | 29 +++++++++++++++
> 6 files changed, 102 insertions(+)
> create mode 100644 rust/kernel/faux.rs
> create mode 100644 samples/rust/rust_driver_faux.rs

<snip>

> diff --git a/rust/kernel/faux.rs b/rust/kernel/faux.rs
> new file mode 100644
> index 0000000000000..5e58f397b747a
> --- /dev/null
> +++ b/rust/kernel/faux.rs
> @@ -0,0 +1,60 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +
> +//! Abstractions for the faux bus.
> +//!
> +//! This crate provides bindings for working with faux devices in kernel modules. It should be
> +//! preferred for creating virtual devices over the platform API.
> +//!
> +//! C header: [`include/linux/device/faux.h`]
> +use crate::{bindings, device, error::from_err_ptr, prelude::*};
> +use core::ptr::{addr_of_mut, null, NonNull};
> +
> +/// The faux device representation.
> +///
> +/// This type represents the registration of a [`struct faux_device`]. When an instance of this type
> +/// is dropped, its respective faux device will be unregistered from the system.
> +///
> +/// # Invariants
> +///
> +/// `self.0` always holds a valid pointer to an initialized and registered [`struct faux_device`].
> +///
> +/// [`struct faux_device`]: srctree/include/linux/device/faux.h
> +#[repr(transparent)]
> +pub struct Device(NonNull<bindings::faux_device>);
> +
> +impl Device {
> + /// Create and register a new faux device with the given name.
> + pub fn new(name: &CStr) -> Result<Self> {
> + // SAFETY:
> + // - `name` is copied by this function into its own storage
> + // - `faux_ops` is safe to leave NULL according to the C API
> + // - `faux_device_create` returns a valid non-null pointer to a `faux_device`, or error

In the v3 patch the C API returns NULL on error.

> + from_err_ptr(unsafe { bindings::faux_device_create(name.as_char_ptr(), null()) })
> + .map(|d| Self(unsafe { NonNull::new_unchecked(d) }))
> + }
> +
> + fn as_raw(&self) -> *mut bindings::faux_device {
> + self.0.as_ptr()
> + }
> +}
> +
> +impl AsRef<device::Device> for Device {
> + fn as_ref(&self) -> &device::Device {
> + // SAFETY: The underlying `device` in `faux_device` is guaranteed by the C API to be
> + // a valid initialized `device`.
> + unsafe { device::Device::as_ref(addr_of_mut!((*self.as_raw()).dev)) }
> + }
> +}
> +
> +impl Drop for Device {
> + fn drop(&mut self) {
> + // SAFETY: self.0 is a valid registered faux_device via our type invariants.
> + unsafe { bindings::faux_device_destroy(self.as_raw()) }
> + }
> +}
> +
> +// SAFETY: The faux device API is thread-safe
> +unsafe impl Send for Device {}
> +
> +// SAFETY: The faux device API is thread-safe
> +unsafe impl Sync for Device {}

<snip>