Skip to content

Commit 78418f3

Browse files
Lyudegregkh
authored andcommitted
rust/kernel: Add faux device bindings
This introduces a module 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 <[email protected]> Cc: Maíra Canal <[email protected]> Cc: Danilo Krummrich <[email protected]> Cc: Miguel Ojeda <[email protected]> Acked-by: Danilo Krummrich <[email protected]> Link: https://lore.kernel.org/r/2025021026-exert-accent-b4c6@gregkh Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 35fa2d8 commit 78418f3

File tree

7 files changed

+111
-0
lines changed

7 files changed

+111
-0
lines changed

MAINTAINERS

+2
Original file line numberDiff line numberDiff line change
@@ -7116,8 +7116,10 @@ F: rust/kernel/device.rs
71167116
F: rust/kernel/device_id.rs
71177117
F: rust/kernel/devres.rs
71187118
F: rust/kernel/driver.rs
7119+
F: rust/kernel/faux.rs
71197120
F: rust/kernel/platform.rs
71207121
F: samples/rust/rust_driver_platform.rs
7122+
F: samples/rust/rust_driver_faux.rs
71217123

71227124
DRIVERS FOR OMAP ADAPTIVE VOLTAGE SCALING (AVS)
71237125
M: Nishanth Menon <[email protected]>

rust/bindings/bindings_helper.h

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/blk_types.h>
1212
#include <linux/blkdev.h>
1313
#include <linux/cred.h>
14+
#include <linux/device/faux.h>
1415
#include <linux/errname.h>
1516
#include <linux/ethtool.h>
1617
#include <linux/file.h>

rust/kernel/faux.rs

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
3+
//! Abstractions for the faux bus.
4+
//!
5+
//! This module provides bindings for working with faux devices in kernel modules.
6+
//!
7+
//! C header: [`include/linux/device/faux.h`]
8+
9+
use crate::{bindings, device, error::code::*, prelude::*};
10+
use core::ptr::{addr_of_mut, null, null_mut, NonNull};
11+
12+
/// The registration of a faux device.
13+
///
14+
/// This type represents the registration of a [`struct faux_device`]. When an instance of this type
15+
/// is dropped, its respective faux device will be unregistered from the system.
16+
///
17+
/// # Invariants
18+
///
19+
/// `self.0` always holds a valid pointer to an initialized and registered [`struct faux_device`].
20+
///
21+
/// [`struct faux_device`]: srctree/include/linux/device/faux.h
22+
#[repr(transparent)]
23+
pub struct Registration(NonNull<bindings::faux_device>);
24+
25+
impl Registration {
26+
/// Create and register a new faux device with the given name.
27+
pub fn new(name: &CStr) -> Result<Self> {
28+
// SAFETY:
29+
// - `name` is copied by this function into its own storage
30+
// - `faux_ops` is safe to leave NULL according to the C API
31+
let dev = unsafe { bindings::faux_device_create(name.as_char_ptr(), null_mut(), null()) };
32+
33+
// The above function will return either a valid device, or NULL on failure
34+
// INVARIANT: The device will remain registered until faux_device_destroy() is called, which
35+
// happens in our Drop implementation.
36+
Ok(Self(NonNull::new(dev).ok_or(ENODEV)?))
37+
}
38+
39+
fn as_raw(&self) -> *mut bindings::faux_device {
40+
self.0.as_ptr()
41+
}
42+
}
43+
44+
impl AsRef<device::Device> for Registration {
45+
fn as_ref(&self) -> &device::Device {
46+
// SAFETY: The underlying `device` in `faux_device` is guaranteed by the C API to be
47+
// a valid initialized `device`.
48+
unsafe { device::Device::as_ref(addr_of_mut!((*self.as_raw()).dev)) }
49+
}
50+
}
51+
52+
impl Drop for Registration {
53+
fn drop(&mut self) {
54+
// SAFETY: `self.0` is a valid registered faux_device via our type invariants.
55+
unsafe { bindings::faux_device_destroy(self.as_raw()) }
56+
}
57+
}
58+
59+
// SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as
60+
// faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not
61+
// having Copy/Clone.
62+
unsafe impl Send for Registration {}
63+
64+
// SAFETY: The faux device API is thread-safe as guaranteed by the device core, as long as
65+
// faux_device_destroy() is guaranteed to only be called once - which is guaranteed by our type not
66+
// having Copy/Clone.
67+
unsafe impl Sync for Registration {}

rust/kernel/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ pub mod device_id;
4646
pub mod devres;
4747
pub mod driver;
4848
pub mod error;
49+
pub mod faux;
4950
#[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
5051
pub mod firmware;
5152
pub mod fs;

samples/rust/Kconfig

+10
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ config SAMPLE_RUST_DRIVER_PLATFORM
6161

6262
If unsure, say N.
6363

64+
config SAMPLE_RUST_DRIVER_FAUX
65+
tristate "Faux Driver"
66+
help
67+
This option builds the Rust Faux driver sample.
68+
69+
To compile this as a module, choose M here:
70+
the module will be called rust_driver_faux.
71+
72+
If unsure, say N.
73+
6474
config SAMPLE_RUST_HOSTPROGS
6575
bool "Host programs"
6676
help

samples/rust/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ obj-$(CONFIG_SAMPLE_RUST_MISC_DEVICE) += rust_misc_device.o
66
obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o
77
obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o
88
obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o
9+
obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o
910

1011
rust_print-y := rust_print_main.o rust_print_events.o
1112

samples/rust/rust_driver_faux.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
3+
//! Rust faux device sample.
4+
5+
use kernel::{c_str, faux, prelude::*, Module};
6+
7+
module! {
8+
type: SampleModule,
9+
name: "rust_faux_driver",
10+
author: "Lyude Paul",
11+
description: "Rust faux device sample",
12+
license: "GPL",
13+
}
14+
15+
struct SampleModule {
16+
_reg: faux::Registration,
17+
}
18+
19+
impl Module for SampleModule {
20+
fn init(_module: &'static ThisModule) -> Result<Self> {
21+
pr_info!("Initialising Rust Faux Device Sample\n");
22+
23+
let reg = faux::Registration::new(c_str!("rust-faux-sample-device"))?;
24+
25+
dev_info!(reg.as_ref(), "Hello from faux device!\n");
26+
27+
Ok(Self { _reg: reg })
28+
}
29+
}

0 commit comments

Comments
 (0)