From nobody Sun Feb 8 09:33:07 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 357591DE891 for ; Thu, 6 Feb 2025 21:06:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738875998; cv=none; b=T4nVQdjJ1aPdr2fydjqYhby5TGCh+PNCPgkJrRHO/8tpRNGwguUGfm2o1eYcJAVD6BB2NHjSfoVYP8HOBhR9U3tVfeeSdXTn8EfR/pWEveUwSckSdyW9TEFHT/gw9LY+WMRbs+HVdxZ1eThhTgBrlK45zw35XCvkV7S/zHrq5qY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738875998; c=relaxed/simple; bh=kOOEPl/veYhynAhhL0jpvHiTjC+U6g7X09NmSzkbB80=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=OTRgxYNJysVpn52jq6A9arlj9PKw384ZpM/Kg8DrMB3O8aq8KFBxrubu/RQFFnvHXN+7tvPN3sX2BJcvYTw0+SmVqhbDZfmPmuRK9dO/vkoviLojpVfJ0354MEI2njDROaagZYn3zOGMLYWCjkk7HVu6dwCZbTh3UaFFM0vXL/M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=BT0JkoBg; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="BT0JkoBg" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1738875995; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=GihRnkuZEyKR3tOEQSNi7Ep19r88LL1Tvr+PPotI6bE=; b=BT0JkoBgqJr/5+y4gzkUEdQEhtjO43jIX+qNnu6A4HAZhZP4CvhtvU2DKhDrv6am06Ws+R YrM6+k28LidoVnJd66Y7pm8dmKOJkfwvRGER4YzRHbEOv/bUUxc3H80PVUH4t53jp/ZRCY DnSy6sjrhhG6TgKAheeST5xF7EfI5Sw= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-632-1CgXrbzLOb677x8OZ5Bheg-1; Thu, 06 Feb 2025 16:06:32 -0500 X-MC-Unique: 1CgXrbzLOb677x8OZ5Bheg-1 X-Mimecast-MFC-AGG-ID: 1CgXrbzLOb677x8OZ5Bheg Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 798731800877; Thu, 6 Feb 2025 21:06:29 +0000 (UTC) Received: from chopper.redhat.com (unknown [10.22.66.91]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C75D71955BCB; Thu, 6 Feb 2025 21:06:25 +0000 (UTC) From: Lyude Paul To: rust-for-linux@vger.kernel.org, Greg Kroah-Hartman , =?UTF-8?q?Ma=C3=ADra=20Canal?= Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Wedson Almeida Filho , Mika Westerberg , Xiangfei Ding , linux-kernel@vger.kernel.org (open list) Subject: [PATCH] rust/kernel: Add faux device bindings Date: Thu, 6 Feb 2025 16:04:56 -0500 Message-ID: <20250206210503.102061-2-lyude@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 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 Cc: Greg Kroah-Hartman Cc: Ma=C3=ADra Canal --- 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 diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 55354e4dec14e..f46cf3bb70695 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include 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 m= odules. 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`]. Whe= n an instance of this type +/// is dropped, its respective faux device will be unregistered from the s= ystem. +/// +/// # 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); + +impl Device { + /// Create and register a new faux device with the given name. + pub fn new(name: &CStr) -> Result { + // 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 `f= aux_device`, or error + from_err_ptr(unsafe { bindings::faux_device_create(name.as_char_pt= r(), null()) }) + .map(|d| Self(unsafe { NonNull::new_unchecked(d) })) + } + + fn as_raw(&self) -> *mut bindings::faux_device { + self.0.as_ptr() + } +} + +impl AsRef 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 i= nvariants. + 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 {} diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 496ed32b0911a..398242f92a961 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -46,6 +46,7 @@ pub mod devres; pub mod driver; pub mod error; +pub mod faux; #[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)] pub mod firmware; pub mod fs; diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index 918dbead2c0b4..3b6eae84b2977 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -61,6 +61,16 @@ config SAMPLE_RUST_DRIVER_PLATFORM =20 If unsure, say N. =20 +config SAMPLE_RUST_DRIVER_FAUX + tristate "Faux Driver" + help + This option builds the Rust Faux driver sample. + + To compile this as a module, choose M here: + the module will be called rust_driver_faux. + + If unsure, say N. + config SAMPLE_RUST_HOSTPROGS bool "Host programs" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 5a8ab0df0567c..0dbc6d90f1ef9 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_SAMPLE_RUST_MISC_DEVICE) +=3D rust_misc_devic= e.o obj-$(CONFIG_SAMPLE_RUST_PRINT) +=3D rust_print.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) +=3D rust_driver_pci.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) +=3D rust_driver_platform.o +obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) +=3D rust_driver_faux.o =20 rust_print-y :=3D rust_print_main.o rust_print_events.o =20 diff --git a/samples/rust/rust_driver_faux.rs b/samples/rust/rust_driver_fa= ux.rs new file mode 100644 index 0000000000000..fb0d8527bdcb2 --- /dev/null +++ b/samples/rust/rust_driver_faux.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Rust faux device sample. + +use kernel::{c_str, faux::*, prelude::*, Module}; + +module! { + type: SampleModule, + name: "rust_faux_driver", + author: "Lyude Paul", + description: "Rust faux device sample", + license: "GPL", +} + +struct SampleModule { + _dev: Device, +} + +impl Module for SampleModule { + fn init(_module: &'static ThisModule) -> Result { + pr_info!("Initialising Rust Faux Device Sample\n"); + + let dev =3D Device::new(c_str!("rust-faux-sample-device"))?; + + dev_info!(dev.as_ref(), "Hello from faux device!"); + + Ok(Self { _dev: dev }) + } +} base-commit: 808eb958781e4ebb6e9c0962af2e856767e20f45 prerequisite-patch-id: f05ff916822e21eec452f9e5b8d11339c409265a --=20 2.48.1