2021-07-03 16:56:17 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
|
|
|
|
|
|
//! Crate for all kernel procedural macros.
|
|
|
|
|
|
2024-09-02 18:55:31 +02:00
|
|
|
// When fixdep scans this, it will find this string `CONFIG_RUSTC_VERSION_TEXT`
|
|
|
|
|
// and thus add a dependency on `include/config/RUSTC_VERSION_TEXT`, which is
|
|
|
|
|
// touched by Kconfig when the version string from the compiler changes.
|
|
|
|
|
|
2026-04-06 01:52:51 +02:00
|
|
|
// Stable since Rust 1.87.0.
|
|
|
|
|
#![feature(extract_if)]
|
|
|
|
|
//
|
rust: kunit: support KUnit-mapped `assert!` macros in `#[test]`s
The KUnit `#[test]` support that landed recently is very basic and does
not map the `assert*!` macros into KUnit like the doctests do, so they
panic at the moment.
Thus implement the custom mapping in a similar way to doctests, reusing
the infrastructure there.
In Rust 1.88.0, the `file()` method in `Span` may be stable [1]. However,
it was changed recently (from `SourceFile`), so we need to do something
different in previous versions. Thus create a helper for it and use it
to get the path.
With this, a failing test suite like:
#[kunit_tests(my_test_suite)]
mod tests {
use super::*;
#[test]
fn my_first_test() {
assert_eq!(42, 43);
}
#[test]
fn my_second_test() {
assert!(42 >= 43);
}
}
will properly map back to KUnit, printing something like:
[ 1.924325] KTAP version 1
[ 1.924421] # Subtest: my_test_suite
[ 1.924506] # speed: normal
[ 1.924525] 1..2
[ 1.926385] # my_first_test: ASSERTION FAILED at rust/kernel/lib.rs:251
[ 1.926385] Expected 42 == 43 to be true, but is false
[ 1.928026] # my_first_test.speed: normal
[ 1.928075] not ok 1 my_first_test
[ 1.928723] # my_second_test: ASSERTION FAILED at rust/kernel/lib.rs:256
[ 1.928723] Expected 42 >= 43 to be true, but is false
[ 1.929834] # my_second_test.speed: normal
[ 1.929868] not ok 2 my_second_test
[ 1.930032] # my_test_suite: pass:0 fail:2 skip:0 total:2
[ 1.930153] # Totals: pass:0 fail:2 skip:0 total
Link: https://github.com/rust-lang/rust/pull/140514 [1]
Reviewed-by: David Gow <davidgow@google.com>
Acked-by: Danilo Krummrich <dakr@kernel.org>
Link: https://lore.kernel.org/r/20250502215133.1923676-2-ojeda@kernel.org
[ Required `KUNIT=y` like for doctests. Used the `cfg_attr` from the
TODO comment and clarified its comment now that the stabilization is
in beta and thus quite likely stable in Rust 1.88.0. Simplified the
`new_body` code by introducing a new variable. Added
`#[allow(clippy::incompatible_msrv)]`. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2025-05-02 23:51:26 +02:00
|
|
|
// Stable since Rust 1.88.0 under a different name, `proc_macro_span_file`,
|
|
|
|
|
// which was added in Rust 1.88.0. This is why `cfg_attr` is used here, i.e.
|
|
|
|
|
// to avoid depending on the full `proc_macro_span` on Rust >= 1.88.0.
|
|
|
|
|
#![cfg_attr(not(CONFIG_RUSTC_HAS_SPAN_FILE), feature(proc_macro_span))]
|
|
|
|
|
|
2022-11-10 17:41:17 +01:00
|
|
|
mod concat_idents;
|
rust: add #[export] macro
Rust has two different tools for generating function declarations to
call across the FFI boundary:
* bindgen. Generates Rust declarations from a C header.
* cbindgen. Generates C headers from Rust declarations.
However, we only use bindgen in the kernel. This means that when C code
calls a Rust function by name, its signature must be duplicated in both
Rust code and a C header, and the signature needs to be kept in sync
manually.
Introducing cbindgen as a mandatory dependency to build the kernel would
be a rather complex and large change, so we do not consider that at this
time. Instead, to eliminate this manual checking, introduce a new macro
that verifies at compile time that the two function declarations use the
same signature. The idea is to run the C declaration through bindgen,
and then have rustc verify that the function pointers have the same
type.
The signature must still be written twice, but at least you can no
longer get it wrong. If the signatures don't match, you will get errors
that look like this:
error[E0308]: `if` and `else` have incompatible types
--> <linux>/rust/kernel/print.rs:22:22
|
21 | #[export]
| --------- expected because of this
22 | unsafe extern "C" fn rust_fmt_argument(
| ^^^^^^^^^^^^^^^^^ expected `u8`, found `i8`
|
= note: expected fn item `unsafe extern "C" fn(*mut u8, *mut u8, *mut c_void) -> *mut u8 {bindings::rust_fmt_argument}`
found fn item `unsafe extern "C" fn(*mut i8, *mut i8, *const c_void) -> *mut i8 {print::rust_fmt_argument}`
It is unfortunate that the error message starts out by saying "`if` and
`else` have incompatible types", but I believe the rest of the error
message is reasonably clear and not too confusing.
Reviewed-by: Tamir Duberstein <tamird@gmail.com>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20250303-export-macro-v3-3-41fbad85a27f@google.com
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2025-03-03 08:45:14 +00:00
|
|
|
mod export;
|
2025-10-18 15:16:36 -04:00
|
|
|
mod fmt;
|
2021-07-03 16:56:17 +02:00
|
|
|
mod helpers;
|
2025-03-07 17:00:57 +08:00
|
|
|
mod kunit;
|
2021-07-03 16:56:17 +02:00
|
|
|
mod module;
|
2023-06-28 18:11:01 +01:00
|
|
|
mod paste;
|
2022-11-10 17:41:18 +01:00
|
|
|
mod vtable;
|
2021-07-03 16:56:17 +02:00
|
|
|
|
|
|
|
|
use proc_macro::TokenStream;
|
|
|
|
|
|
2026-01-12 17:07:14 +00:00
|
|
|
use syn::parse_macro_input;
|
|
|
|
|
|
2021-07-03 16:56:17 +02:00
|
|
|
/// Declares a kernel module.
|
|
|
|
|
///
|
|
|
|
|
/// The `type` argument should be a type which implements the [`Module`]
|
|
|
|
|
/// trait. Also accepts various forms of kernel metadata.
|
|
|
|
|
///
|
2025-09-24 14:39:28 +02:00
|
|
|
/// The `params` field describe module parameters. Each entry has the form
|
|
|
|
|
///
|
|
|
|
|
/// ```ignore
|
|
|
|
|
/// parameter_name: type {
|
|
|
|
|
/// default: default_value,
|
|
|
|
|
/// description: "Description",
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// `type` may be one of
|
|
|
|
|
///
|
|
|
|
|
/// - [`i8`]
|
|
|
|
|
/// - [`u8`]
|
|
|
|
|
/// - [`i8`]
|
|
|
|
|
/// - [`u8`]
|
|
|
|
|
/// - [`i16`]
|
|
|
|
|
/// - [`u16`]
|
|
|
|
|
/// - [`i32`]
|
|
|
|
|
/// - [`u32`]
|
|
|
|
|
/// - [`i64`]
|
|
|
|
|
/// - [`u64`]
|
|
|
|
|
/// - [`isize`]
|
|
|
|
|
/// - [`usize`]
|
|
|
|
|
///
|
2023-12-16 00:54:28 +01:00
|
|
|
/// C header: [`include/linux/moduleparam.h`](srctree/include/linux/moduleparam.h)
|
2021-07-03 16:56:17 +02:00
|
|
|
///
|
|
|
|
|
/// [`Module`]: ../kernel/trait.Module.html
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
2026-01-14 18:16:38 +00:00
|
|
|
/// ```ignore
|
2021-07-03 16:56:17 +02:00
|
|
|
/// use kernel::prelude::*;
|
|
|
|
|
///
|
|
|
|
|
/// module!{
|
|
|
|
|
/// type: MyModule,
|
2022-11-10 17:41:19 +01:00
|
|
|
/// name: "my_kernel_module",
|
2025-03-09 14:57:11 -03:00
|
|
|
/// authors: ["Rust for Linux Contributors"],
|
2022-11-10 17:41:19 +01:00
|
|
|
/// description: "My very own kernel module!",
|
|
|
|
|
/// license: "GPL",
|
2024-05-12 11:23:20 +00:00
|
|
|
/// alias: ["alternate_module_name"],
|
2025-09-24 14:39:28 +02:00
|
|
|
/// params: {
|
|
|
|
|
/// my_parameter: i64 {
|
|
|
|
|
/// default: 1,
|
|
|
|
|
/// description: "This parameter has a default of 1",
|
|
|
|
|
/// },
|
|
|
|
|
/// },
|
2021-07-03 16:56:17 +02:00
|
|
|
/// }
|
|
|
|
|
///
|
2024-07-04 09:55:43 -05:00
|
|
|
/// struct MyModule(i32);
|
2021-07-03 16:56:17 +02:00
|
|
|
///
|
|
|
|
|
/// impl kernel::Module for MyModule {
|
2024-07-04 09:55:43 -05:00
|
|
|
/// fn init(_module: &'static ThisModule) -> Result<Self> {
|
|
|
|
|
/// let foo: i32 = 42;
|
|
|
|
|
/// pr_info!("I contain: {}\n", foo);
|
2025-09-24 14:39:28 +02:00
|
|
|
/// pr_info!("i32 param is: {}\n", module_parameters::my_parameter.read());
|
2024-07-04 09:55:43 -05:00
|
|
|
/// Ok(Self(foo))
|
2021-07-03 16:56:17 +02:00
|
|
|
/// }
|
|
|
|
|
/// }
|
2024-07-04 09:55:43 -05:00
|
|
|
/// # fn main() {}
|
2021-07-03 16:56:17 +02:00
|
|
|
/// ```
|
|
|
|
|
///
|
2024-05-01 21:35:48 +09:00
|
|
|
/// ## Firmware
|
|
|
|
|
///
|
|
|
|
|
/// The following example shows how to declare a kernel module that needs
|
|
|
|
|
/// to load binary firmware files. You need to specify the file names of
|
|
|
|
|
/// the firmware in the `firmware` field. The information is embedded
|
|
|
|
|
/// in the `modinfo` section of the kernel module. For example, a tool to
|
|
|
|
|
/// build an initramfs uses this information to put the firmware files into
|
|
|
|
|
/// the initramfs image.
|
|
|
|
|
///
|
2024-07-04 09:55:43 -05:00
|
|
|
/// ```
|
2024-05-01 21:35:48 +09:00
|
|
|
/// use kernel::prelude::*;
|
|
|
|
|
///
|
|
|
|
|
/// module!{
|
|
|
|
|
/// type: MyDeviceDriverModule,
|
|
|
|
|
/// name: "my_device_driver_module",
|
2025-03-09 14:57:11 -03:00
|
|
|
/// authors: ["Rust for Linux Contributors"],
|
2024-05-01 21:35:48 +09:00
|
|
|
/// description: "My device driver requires firmware",
|
|
|
|
|
/// license: "GPL",
|
|
|
|
|
/// firmware: ["my_device_firmware1.bin", "my_device_firmware2.bin"],
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// struct MyDeviceDriverModule;
|
|
|
|
|
///
|
|
|
|
|
/// impl kernel::Module for MyDeviceDriverModule {
|
2024-07-04 09:55:43 -05:00
|
|
|
/// fn init(_module: &'static ThisModule) -> Result<Self> {
|
2024-05-01 21:35:48 +09:00
|
|
|
/// Ok(Self)
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
2024-07-04 09:55:43 -05:00
|
|
|
/// # fn main() {}
|
2024-05-01 21:35:48 +09:00
|
|
|
/// ```
|
|
|
|
|
///
|
2021-07-03 16:56:17 +02:00
|
|
|
/// # Supported argument types
|
|
|
|
|
/// - `type`: type which implements the [`Module`] trait (required).
|
2024-05-12 11:23:21 +00:00
|
|
|
/// - `name`: ASCII string literal of the name of the kernel module (required).
|
2025-03-09 14:57:11 -03:00
|
|
|
/// - `authors`: array of ASCII string literals of the authors of the kernel module.
|
2024-05-12 11:23:21 +00:00
|
|
|
/// - `description`: string literal of the description of the kernel module.
|
|
|
|
|
/// - `license`: ASCII string literal of the license of the kernel module (required).
|
|
|
|
|
/// - `alias`: array of ASCII string literals of the alias names of the kernel module.
|
2024-05-01 21:35:48 +09:00
|
|
|
/// - `firmware`: array of ASCII string literals of the firmware files of
|
2024-07-25 20:46:44 +02:00
|
|
|
/// the kernel module.
|
2021-07-03 16:56:17 +02:00
|
|
|
#[proc_macro]
|
rust: macros: use `syn` to parse `module!` macro
With `syn` being available in the kernel, use it to parse the complex
custom `module!` macro to replace existing helpers. Only parsing is
changed in this commit, the code generation is untouched.
This has the benefit of better error message when the macro is used
incorrectly, as it can point to a concrete span on what's going wrong.
For example, if a field is specified twice, previously it reads:
error: proc macro panicked
--> samples/rust/rust_minimal.rs:7:1
|
7 | / module! {
8 | | type: RustMinimal,
9 | | name: "rust_minimal",
10 | | author: "Rust for Linux Contributors",
11 | | description: "Rust minimal sample",
12 | | license: "GPL",
13 | | license: "GPL",
14 | | }
| |_^
|
= help: message: Duplicated key "license". Keys can only be specified once.
now it reads:
error: duplicated key "license". Keys can only be specified once.
--> samples/rust/rust_minimal.rs:13:5
|
13 | license: "GPL",
| ^^^^^^^
Reviewed-by: Tamir Duberstein <tamird@gmail.com>
Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Benno Lossin <lossin@kernel.org>
Link: https://patch.msgid.link/20260112170919.1888584-5-gary@kernel.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2026-01-12 17:07:15 +00:00
|
|
|
pub fn module(input: TokenStream) -> TokenStream {
|
|
|
|
|
module::module(parse_macro_input!(input))
|
|
|
|
|
.unwrap_or_else(|e| e.into_compile_error())
|
|
|
|
|
.into()
|
2021-07-03 16:56:17 +02:00
|
|
|
}
|
2022-11-10 17:41:17 +01:00
|
|
|
|
2022-11-10 17:41:18 +01:00
|
|
|
/// Declares or implements a vtable trait.
|
|
|
|
|
///
|
|
|
|
|
/// Linux's use of pure vtables is very close to Rust traits, but they differ
|
|
|
|
|
/// in how unimplemented functions are represented. In Rust, traits can provide
|
|
|
|
|
/// default implementation for all non-required methods (and the default
|
|
|
|
|
/// implementation could just return `Error::EINVAL`); Linux typically use C
|
|
|
|
|
/// `NULL` pointers to represent these functions.
|
|
|
|
|
///
|
2023-10-26 20:19:33 +00:00
|
|
|
/// This attribute closes that gap. A trait can be annotated with the
|
|
|
|
|
/// `#[vtable]` attribute. Implementers of the trait will then also have to
|
|
|
|
|
/// annotate the trait with `#[vtable]`. This attribute generates a `HAS_*`
|
|
|
|
|
/// associated constant bool for each method in the trait that is set to true if
|
|
|
|
|
/// the implementer has overridden the associated method.
|
2022-11-10 17:41:18 +01:00
|
|
|
///
|
2023-10-26 20:19:33 +00:00
|
|
|
/// For a trait method to be optional, it must have a default implementation.
|
|
|
|
|
/// This is also the case for traits annotated with `#[vtable]`, but in this
|
|
|
|
|
/// case the default implementation will never be executed. The reason for this
|
|
|
|
|
/// is that the functions will be called through function pointers installed in
|
|
|
|
|
/// C side vtables. When an optional method is not implemented on a `#[vtable]`
|
2025-11-30 22:12:33 +01:00
|
|
|
/// trait, a `NULL` entry is installed in the vtable. Thus the default
|
2023-10-26 20:19:33 +00:00
|
|
|
/// implementation is never called. Since these traits are not designed to be
|
|
|
|
|
/// used on the Rust side, it should not be possible to call the default
|
|
|
|
|
/// implementation. This is done to ensure that we call the vtable methods
|
|
|
|
|
/// through the C vtable, and not through the Rust vtable. Therefore, the
|
2024-11-23 23:28:49 +01:00
|
|
|
/// default implementation should call `build_error!`, which prevents
|
2023-10-26 20:19:33 +00:00
|
|
|
/// calls to this function at compile time:
|
|
|
|
|
///
|
|
|
|
|
/// ```compile_fail
|
2024-07-04 09:55:42 -05:00
|
|
|
/// # // Intentionally missing `use`s to simplify `rusttest`.
|
2024-11-23 23:28:49 +01:00
|
|
|
/// build_error!(VTABLE_DEFAULT_ERROR)
|
2023-10-26 20:19:33 +00:00
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// Note that you might need to import [`kernel::error::VTABLE_DEFAULT_ERROR`].
|
|
|
|
|
///
|
|
|
|
|
/// This macro should not be used when all functions are required.
|
2022-11-10 17:41:18 +01:00
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
2024-07-04 09:55:45 -05:00
|
|
|
/// ```
|
2023-10-26 20:19:33 +00:00
|
|
|
/// use kernel::error::VTABLE_DEFAULT_ERROR;
|
2022-11-10 17:41:18 +01:00
|
|
|
/// use kernel::prelude::*;
|
|
|
|
|
///
|
|
|
|
|
/// // Declares a `#[vtable]` trait
|
|
|
|
|
/// #[vtable]
|
|
|
|
|
/// pub trait Operations: Send + Sync + Sized {
|
|
|
|
|
/// fn foo(&self) -> Result<()> {
|
2024-11-23 23:28:49 +01:00
|
|
|
/// build_error!(VTABLE_DEFAULT_ERROR)
|
2022-11-10 17:41:18 +01:00
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// fn bar(&self) -> Result<()> {
|
2024-11-23 23:28:49 +01:00
|
|
|
/// build_error!(VTABLE_DEFAULT_ERROR)
|
2022-11-10 17:41:18 +01:00
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// struct Foo;
|
|
|
|
|
///
|
|
|
|
|
/// // Implements the `#[vtable]` trait
|
|
|
|
|
/// #[vtable]
|
|
|
|
|
/// impl Operations for Foo {
|
|
|
|
|
/// fn foo(&self) -> Result<()> {
|
|
|
|
|
/// # Err(EINVAL)
|
|
|
|
|
/// // ...
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(<Foo as Operations>::HAS_FOO, true);
|
|
|
|
|
/// assert_eq!(<Foo as Operations>::HAS_BAR, false);
|
|
|
|
|
/// ```
|
2023-10-26 20:19:33 +00:00
|
|
|
///
|
|
|
|
|
/// [`kernel::error::VTABLE_DEFAULT_ERROR`]: ../kernel/error/constant.VTABLE_DEFAULT_ERROR.html
|
2022-11-10 17:41:18 +01:00
|
|
|
#[proc_macro_attribute]
|
2026-01-12 17:07:14 +00:00
|
|
|
pub fn vtable(attr: TokenStream, input: TokenStream) -> TokenStream {
|
|
|
|
|
parse_macro_input!(attr as syn::parse::Nothing);
|
|
|
|
|
vtable::vtable(parse_macro_input!(input))
|
|
|
|
|
.unwrap_or_else(|e| e.into_compile_error())
|
|
|
|
|
.into()
|
2022-11-10 17:41:18 +01:00
|
|
|
}
|
|
|
|
|
|
rust: add #[export] macro
Rust has two different tools for generating function declarations to
call across the FFI boundary:
* bindgen. Generates Rust declarations from a C header.
* cbindgen. Generates C headers from Rust declarations.
However, we only use bindgen in the kernel. This means that when C code
calls a Rust function by name, its signature must be duplicated in both
Rust code and a C header, and the signature needs to be kept in sync
manually.
Introducing cbindgen as a mandatory dependency to build the kernel would
be a rather complex and large change, so we do not consider that at this
time. Instead, to eliminate this manual checking, introduce a new macro
that verifies at compile time that the two function declarations use the
same signature. The idea is to run the C declaration through bindgen,
and then have rustc verify that the function pointers have the same
type.
The signature must still be written twice, but at least you can no
longer get it wrong. If the signatures don't match, you will get errors
that look like this:
error[E0308]: `if` and `else` have incompatible types
--> <linux>/rust/kernel/print.rs:22:22
|
21 | #[export]
| --------- expected because of this
22 | unsafe extern "C" fn rust_fmt_argument(
| ^^^^^^^^^^^^^^^^^ expected `u8`, found `i8`
|
= note: expected fn item `unsafe extern "C" fn(*mut u8, *mut u8, *mut c_void) -> *mut u8 {bindings::rust_fmt_argument}`
found fn item `unsafe extern "C" fn(*mut i8, *mut i8, *const c_void) -> *mut i8 {print::rust_fmt_argument}`
It is unfortunate that the error message starts out by saying "`if` and
`else` have incompatible types", but I believe the rest of the error
message is reasonably clear and not too confusing.
Reviewed-by: Tamir Duberstein <tamird@gmail.com>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20250303-export-macro-v3-3-41fbad85a27f@google.com
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2025-03-03 08:45:14 +00:00
|
|
|
/// Export a function so that C code can call it via a header file.
|
|
|
|
|
///
|
|
|
|
|
/// Functions exported using this macro can be called from C code using the declaration in the
|
|
|
|
|
/// appropriate header file. It should only be used in cases where C calls the function through a
|
|
|
|
|
/// header file; cases where C calls into Rust via a function pointer in a vtable (such as
|
|
|
|
|
/// `file_operations`) should not use this macro.
|
|
|
|
|
///
|
|
|
|
|
/// This macro has the following effect:
|
|
|
|
|
///
|
|
|
|
|
/// * Disables name mangling for this function.
|
|
|
|
|
/// * Verifies at compile-time that the function signature matches the declaration in the header
|
|
|
|
|
/// file.
|
|
|
|
|
///
|
|
|
|
|
/// You must declare the signature of the Rust function in a header file that is included by
|
|
|
|
|
/// `rust/bindings/bindings_helper.h`.
|
|
|
|
|
///
|
|
|
|
|
/// This macro is *not* the same as the C macros `EXPORT_SYMBOL_*`. All Rust symbols are currently
|
|
|
|
|
/// automatically exported with `EXPORT_SYMBOL_GPL`.
|
|
|
|
|
#[proc_macro_attribute]
|
2026-01-12 17:07:17 +00:00
|
|
|
pub fn export(attr: TokenStream, input: TokenStream) -> TokenStream {
|
|
|
|
|
parse_macro_input!(attr as syn::parse::Nothing);
|
|
|
|
|
export::export(parse_macro_input!(input)).into()
|
rust: add #[export] macro
Rust has two different tools for generating function declarations to
call across the FFI boundary:
* bindgen. Generates Rust declarations from a C header.
* cbindgen. Generates C headers from Rust declarations.
However, we only use bindgen in the kernel. This means that when C code
calls a Rust function by name, its signature must be duplicated in both
Rust code and a C header, and the signature needs to be kept in sync
manually.
Introducing cbindgen as a mandatory dependency to build the kernel would
be a rather complex and large change, so we do not consider that at this
time. Instead, to eliminate this manual checking, introduce a new macro
that verifies at compile time that the two function declarations use the
same signature. The idea is to run the C declaration through bindgen,
and then have rustc verify that the function pointers have the same
type.
The signature must still be written twice, but at least you can no
longer get it wrong. If the signatures don't match, you will get errors
that look like this:
error[E0308]: `if` and `else` have incompatible types
--> <linux>/rust/kernel/print.rs:22:22
|
21 | #[export]
| --------- expected because of this
22 | unsafe extern "C" fn rust_fmt_argument(
| ^^^^^^^^^^^^^^^^^ expected `u8`, found `i8`
|
= note: expected fn item `unsafe extern "C" fn(*mut u8, *mut u8, *mut c_void) -> *mut u8 {bindings::rust_fmt_argument}`
found fn item `unsafe extern "C" fn(*mut i8, *mut i8, *const c_void) -> *mut i8 {print::rust_fmt_argument}`
It is unfortunate that the error message starts out by saying "`if` and
`else` have incompatible types", but I believe the rest of the error
message is reasonably clear and not too confusing.
Reviewed-by: Tamir Duberstein <tamird@gmail.com>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20250303-export-macro-v3-3-41fbad85a27f@google.com
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2025-03-03 08:45:14 +00:00
|
|
|
}
|
|
|
|
|
|
2025-10-18 15:16:36 -04:00
|
|
|
/// Like [`core::format_args!`], but automatically wraps arguments in [`kernel::fmt::Adapter`].
|
|
|
|
|
///
|
|
|
|
|
/// This macro allows generating `fmt::Arguments` while ensuring that each argument is wrapped with
|
|
|
|
|
/// `::kernel::fmt::Adapter`, which customizes formatting behavior for kernel logging.
|
|
|
|
|
///
|
|
|
|
|
/// Named arguments used in the format string (e.g. `{foo}`) are detected and resolved from local
|
|
|
|
|
/// bindings. All positional and named arguments are automatically wrapped.
|
|
|
|
|
///
|
|
|
|
|
/// This macro is an implementation detail of other kernel logging macros like [`pr_info!`] and
|
|
|
|
|
/// should not typically be used directly.
|
|
|
|
|
///
|
|
|
|
|
/// [`kernel::fmt::Adapter`]: ../kernel/fmt/struct.Adapter.html
|
|
|
|
|
/// [`pr_info!`]: ../kernel/macro.pr_info.html
|
|
|
|
|
#[proc_macro]
|
|
|
|
|
pub fn fmt(input: TokenStream) -> TokenStream {
|
2026-01-12 17:07:13 +00:00
|
|
|
fmt::fmt(input.into()).into()
|
2025-10-18 15:16:36 -04:00
|
|
|
}
|
|
|
|
|
|
2022-11-10 17:41:17 +01:00
|
|
|
/// Concatenate two identifiers.
|
|
|
|
|
///
|
|
|
|
|
/// This is useful in macros that need to declare or reference items with names
|
|
|
|
|
/// starting with a fixed prefix and ending in a user specified name. The resulting
|
|
|
|
|
/// identifier has the span of the second argument.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
2024-07-04 09:55:45 -05:00
|
|
|
/// ```
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_OK: u32 = 0;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_ERROR: u32 = 1;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_TRANSACTION: u32 = 2;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_REPLY: u32 = 3;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_DEAD_REPLY: u32 = 4;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_TRANSACTION_COMPLETE: u32 = 5;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_INCREFS: u32 = 6;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_ACQUIRE: u32 = 7;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_RELEASE: u32 = 8;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_DECREFS: u32 = 9;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_NOOP: u32 = 10;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_SPAWN_LOOPER: u32 = 11;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_DEAD_BINDER: u32 = 12;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = 13;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_FAILED_REPLY: u32 = 14;
|
|
|
|
|
/// use kernel::macros::concat_idents;
|
2022-11-10 17:41:17 +01:00
|
|
|
///
|
|
|
|
|
/// macro_rules! pub_no_prefix {
|
|
|
|
|
/// ($prefix:ident, $($newname:ident),+) => {
|
2024-07-04 09:55:45 -05:00
|
|
|
/// $(pub(crate) const $newname: u32 = concat_idents!($prefix, $newname);)+
|
2022-11-10 17:41:17 +01:00
|
|
|
/// };
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// pub_no_prefix!(
|
|
|
|
|
/// binder_driver_return_protocol_,
|
|
|
|
|
/// BR_OK,
|
|
|
|
|
/// BR_ERROR,
|
|
|
|
|
/// BR_TRANSACTION,
|
|
|
|
|
/// BR_REPLY,
|
|
|
|
|
/// BR_DEAD_REPLY,
|
|
|
|
|
/// BR_TRANSACTION_COMPLETE,
|
|
|
|
|
/// BR_INCREFS,
|
|
|
|
|
/// BR_ACQUIRE,
|
|
|
|
|
/// BR_RELEASE,
|
|
|
|
|
/// BR_DECREFS,
|
|
|
|
|
/// BR_NOOP,
|
|
|
|
|
/// BR_SPAWN_LOOPER,
|
|
|
|
|
/// BR_DEAD_BINDER,
|
|
|
|
|
/// BR_CLEAR_DEATH_NOTIFICATION_DONE,
|
|
|
|
|
/// BR_FAILED_REPLY
|
|
|
|
|
/// );
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK);
|
|
|
|
|
/// ```
|
|
|
|
|
#[proc_macro]
|
2026-01-12 17:07:18 +00:00
|
|
|
pub fn concat_idents(input: TokenStream) -> TokenStream {
|
|
|
|
|
concat_idents::concat_idents(parse_macro_input!(input)).into()
|
2022-11-10 17:41:17 +01:00
|
|
|
}
|
2023-04-08 12:25:51 +00:00
|
|
|
|
2023-06-28 18:11:01 +01:00
|
|
|
/// Paste identifiers together.
|
|
|
|
|
///
|
|
|
|
|
/// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
|
|
|
|
|
/// single identifier.
|
|
|
|
|
///
|
2023-11-17 20:39:59 -05:00
|
|
|
/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers and
|
|
|
|
|
/// literals (lifetimes and documentation strings are not supported). There is a difference in
|
2023-06-28 18:11:01 +01:00
|
|
|
/// supported modifiers as well.
|
|
|
|
|
///
|
2024-10-02 02:28:48 +00:00
|
|
|
/// # Examples
|
2023-06-28 18:11:01 +01:00
|
|
|
///
|
2024-07-04 09:55:44 -05:00
|
|
|
/// ```
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_OK: u32 = 0;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_ERROR: u32 = 1;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_TRANSACTION: u32 = 2;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_REPLY: u32 = 3;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_DEAD_REPLY: u32 = 4;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_TRANSACTION_COMPLETE: u32 = 5;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_INCREFS: u32 = 6;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_ACQUIRE: u32 = 7;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_RELEASE: u32 = 8;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_DECREFS: u32 = 9;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_NOOP: u32 = 10;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_SPAWN_LOOPER: u32 = 11;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_DEAD_BINDER: u32 = 12;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = 13;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_FAILED_REPLY: u32 = 14;
|
2023-06-28 18:11:01 +01:00
|
|
|
/// macro_rules! pub_no_prefix {
|
|
|
|
|
/// ($prefix:ident, $($newname:ident),+) => {
|
2025-05-19 17:45:53 +01:00
|
|
|
/// ::kernel::macros::paste! {
|
2023-06-28 18:11:01 +01:00
|
|
|
/// $(pub(crate) const $newname: u32 = [<$prefix $newname>];)+
|
|
|
|
|
/// }
|
|
|
|
|
/// };
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// pub_no_prefix!(
|
|
|
|
|
/// binder_driver_return_protocol_,
|
|
|
|
|
/// BR_OK,
|
|
|
|
|
/// BR_ERROR,
|
|
|
|
|
/// BR_TRANSACTION,
|
|
|
|
|
/// BR_REPLY,
|
|
|
|
|
/// BR_DEAD_REPLY,
|
|
|
|
|
/// BR_TRANSACTION_COMPLETE,
|
|
|
|
|
/// BR_INCREFS,
|
|
|
|
|
/// BR_ACQUIRE,
|
|
|
|
|
/// BR_RELEASE,
|
|
|
|
|
/// BR_DECREFS,
|
|
|
|
|
/// BR_NOOP,
|
|
|
|
|
/// BR_SPAWN_LOOPER,
|
|
|
|
|
/// BR_DEAD_BINDER,
|
|
|
|
|
/// BR_CLEAR_DEATH_NOTIFICATION_DONE,
|
|
|
|
|
/// BR_FAILED_REPLY
|
|
|
|
|
/// );
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK);
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// # Modifiers
|
|
|
|
|
///
|
|
|
|
|
/// For each identifier, it is possible to attach one or multiple modifiers to
|
|
|
|
|
/// it.
|
|
|
|
|
///
|
|
|
|
|
/// Currently supported modifiers are:
|
|
|
|
|
/// * `span`: change the span of concatenated identifier to the span of the specified token. By
|
2024-07-09 18:05:56 +02:00
|
|
|
/// default the span of the `[< >]` group is used.
|
2023-06-28 18:11:01 +01:00
|
|
|
/// * `lower`: change the identifier to lower case.
|
|
|
|
|
/// * `upper`: change the identifier to upper case.
|
|
|
|
|
///
|
2024-07-04 09:55:44 -05:00
|
|
|
/// ```
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_OK: u32 = 0;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_ERROR: u32 = 1;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_TRANSACTION: u32 = 2;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_REPLY: u32 = 3;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_DEAD_REPLY: u32 = 4;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_TRANSACTION_COMPLETE: u32 = 5;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_INCREFS: u32 = 6;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_ACQUIRE: u32 = 7;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_RELEASE: u32 = 8;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_DECREFS: u32 = 9;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_NOOP: u32 = 10;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_SPAWN_LOOPER: u32 = 11;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_DEAD_BINDER: u32 = 12;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_CLEAR_DEATH_NOTIFICATION_DONE: u32 = 13;
|
|
|
|
|
/// # const binder_driver_return_protocol_BR_FAILED_REPLY: u32 = 14;
|
2023-06-28 18:11:01 +01:00
|
|
|
/// macro_rules! pub_no_prefix {
|
|
|
|
|
/// ($prefix:ident, $($newname:ident),+) => {
|
2025-05-19 17:45:53 +01:00
|
|
|
/// ::kernel::macros::paste! {
|
2024-10-19 09:22:08 +02:00
|
|
|
/// $(pub(crate) const fn [<$newname:lower:span>]() -> u32 { [<$prefix $newname:span>] })+
|
2023-06-28 18:11:01 +01:00
|
|
|
/// }
|
|
|
|
|
/// };
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// pub_no_prefix!(
|
|
|
|
|
/// binder_driver_return_protocol_,
|
|
|
|
|
/// BR_OK,
|
|
|
|
|
/// BR_ERROR,
|
|
|
|
|
/// BR_TRANSACTION,
|
|
|
|
|
/// BR_REPLY,
|
|
|
|
|
/// BR_DEAD_REPLY,
|
|
|
|
|
/// BR_TRANSACTION_COMPLETE,
|
|
|
|
|
/// BR_INCREFS,
|
|
|
|
|
/// BR_ACQUIRE,
|
|
|
|
|
/// BR_RELEASE,
|
|
|
|
|
/// BR_DECREFS,
|
|
|
|
|
/// BR_NOOP,
|
|
|
|
|
/// BR_SPAWN_LOOPER,
|
|
|
|
|
/// BR_DEAD_BINDER,
|
|
|
|
|
/// BR_CLEAR_DEATH_NOTIFICATION_DONE,
|
|
|
|
|
/// BR_FAILED_REPLY
|
|
|
|
|
/// );
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK);
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
2023-11-17 20:39:59 -05:00
|
|
|
/// # Literals
|
|
|
|
|
///
|
|
|
|
|
/// Literals can also be concatenated with other identifiers:
|
|
|
|
|
///
|
2024-07-04 09:55:44 -05:00
|
|
|
/// ```
|
2023-11-17 20:39:59 -05:00
|
|
|
/// macro_rules! create_numbered_fn {
|
|
|
|
|
/// ($name:literal, $val:literal) => {
|
2025-05-19 17:45:53 +01:00
|
|
|
/// ::kernel::macros::paste! {
|
2023-11-17 20:39:59 -05:00
|
|
|
/// fn [<some_ $name _fn $val>]() -> u32 { $val }
|
|
|
|
|
/// }
|
|
|
|
|
/// };
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// create_numbered_fn!("foo", 100);
|
|
|
|
|
///
|
|
|
|
|
/// assert_eq!(some_foo_fn100(), 100)
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
2023-06-28 18:11:01 +01:00
|
|
|
/// [`paste`]: https://docs.rs/paste/
|
|
|
|
|
#[proc_macro]
|
|
|
|
|
pub fn paste(input: TokenStream) -> TokenStream {
|
2026-01-12 17:07:13 +00:00
|
|
|
let mut tokens = proc_macro2::TokenStream::from(input).into_iter().collect();
|
2023-06-28 18:11:01 +01:00
|
|
|
paste::expand(&mut tokens);
|
2026-01-12 17:07:13 +00:00
|
|
|
tokens
|
|
|
|
|
.into_iter()
|
|
|
|
|
.collect::<proc_macro2::TokenStream>()
|
|
|
|
|
.into()
|
2023-06-28 18:11:01 +01:00
|
|
|
}
|
2025-03-07 17:00:57 +08:00
|
|
|
|
|
|
|
|
/// Registers a KUnit test suite and its test cases using a user-space like syntax.
|
|
|
|
|
///
|
|
|
|
|
/// This macro should be used on modules. If `CONFIG_KUNIT` (in `.config`) is `n`, the target module
|
|
|
|
|
/// is ignored.
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```ignore
|
2025-05-02 23:51:28 +02:00
|
|
|
/// # use kernel::prelude::*;
|
2025-03-07 17:00:57 +08:00
|
|
|
/// #[kunit_tests(kunit_test_suit_name)]
|
|
|
|
|
/// mod tests {
|
|
|
|
|
/// #[test]
|
|
|
|
|
/// fn foo() {
|
|
|
|
|
/// assert_eq!(1, 1);
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// #[test]
|
|
|
|
|
/// fn bar() {
|
|
|
|
|
/// assert_eq!(2, 2);
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
/// ```
|
|
|
|
|
#[proc_macro_attribute]
|
2026-01-12 17:07:19 +00:00
|
|
|
pub fn kunit_tests(attr: TokenStream, input: TokenStream) -> TokenStream {
|
|
|
|
|
kunit::kunit_tests(parse_macro_input!(attr), parse_macro_input!(input))
|
|
|
|
|
.unwrap_or_else(|e| e.into_compile_error())
|
|
|
|
|
.into()
|
2025-03-07 17:00:57 +08:00
|
|
|
}
|