at v6.4-rc7 248 lines 7.2 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2 3//! Crate for all kernel procedural macros. 4 5#[macro_use] 6mod quote; 7mod concat_idents; 8mod helpers; 9mod module; 10mod pin_data; 11mod pinned_drop; 12mod vtable; 13 14use proc_macro::TokenStream; 15 16/// Declares a kernel module. 17/// 18/// The `type` argument should be a type which implements the [`Module`] 19/// trait. Also accepts various forms of kernel metadata. 20/// 21/// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h) 22/// 23/// [`Module`]: ../kernel/trait.Module.html 24/// 25/// # Examples 26/// 27/// ```ignore 28/// use kernel::prelude::*; 29/// 30/// module!{ 31/// type: MyModule, 32/// name: "my_kernel_module", 33/// author: "Rust for Linux Contributors", 34/// description: "My very own kernel module!", 35/// license: "GPL", 36/// params: { 37/// my_i32: i32 { 38/// default: 42, 39/// permissions: 0o000, 40/// description: "Example of i32", 41/// }, 42/// writeable_i32: i32 { 43/// default: 42, 44/// permissions: 0o644, 45/// description: "Example of i32", 46/// }, 47/// }, 48/// } 49/// 50/// struct MyModule; 51/// 52/// impl kernel::Module for MyModule { 53/// fn init() -> Result<Self> { 54/// // If the parameter is writeable, then the kparam lock must be 55/// // taken to read the parameter: 56/// { 57/// let lock = THIS_MODULE.kernel_param_lock(); 58/// pr_info!("i32 param is: {}\n", writeable_i32.read(&lock)); 59/// } 60/// // If the parameter is read only, it can be read without locking 61/// // the kernel parameters: 62/// pr_info!("i32 param is: {}\n", my_i32.read()); 63/// Ok(Self) 64/// } 65/// } 66/// ``` 67/// 68/// # Supported argument types 69/// - `type`: type which implements the [`Module`] trait (required). 70/// - `name`: byte array of the name of the kernel module (required). 71/// - `author`: byte array of the author of the kernel module. 72/// - `description`: byte array of the description of the kernel module. 73/// - `license`: byte array of the license of the kernel module (required). 74/// - `alias`: byte array of alias name of the kernel module. 75#[proc_macro] 76pub fn module(ts: TokenStream) -> TokenStream { 77 module::module(ts) 78} 79 80/// Declares or implements a vtable trait. 81/// 82/// Linux's use of pure vtables is very close to Rust traits, but they differ 83/// in how unimplemented functions are represented. In Rust, traits can provide 84/// default implementation for all non-required methods (and the default 85/// implementation could just return `Error::EINVAL`); Linux typically use C 86/// `NULL` pointers to represent these functions. 87/// 88/// This attribute is intended to close the gap. Traits can be declared and 89/// implemented with the `#[vtable]` attribute, and a `HAS_*` associated constant 90/// will be generated for each method in the trait, indicating if the implementor 91/// has overridden a method. 92/// 93/// This attribute is not needed if all methods are required. 94/// 95/// # Examples 96/// 97/// ```ignore 98/// use kernel::prelude::*; 99/// 100/// // Declares a `#[vtable]` trait 101/// #[vtable] 102/// pub trait Operations: Send + Sync + Sized { 103/// fn foo(&self) -> Result<()> { 104/// Err(EINVAL) 105/// } 106/// 107/// fn bar(&self) -> Result<()> { 108/// Err(EINVAL) 109/// } 110/// } 111/// 112/// struct Foo; 113/// 114/// // Implements the `#[vtable]` trait 115/// #[vtable] 116/// impl Operations for Foo { 117/// fn foo(&self) -> Result<()> { 118/// # Err(EINVAL) 119/// // ... 120/// } 121/// } 122/// 123/// assert_eq!(<Foo as Operations>::HAS_FOO, true); 124/// assert_eq!(<Foo as Operations>::HAS_BAR, false); 125/// ``` 126#[proc_macro_attribute] 127pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream { 128 vtable::vtable(attr, ts) 129} 130 131/// Concatenate two identifiers. 132/// 133/// This is useful in macros that need to declare or reference items with names 134/// starting with a fixed prefix and ending in a user specified name. The resulting 135/// identifier has the span of the second argument. 136/// 137/// # Examples 138/// 139/// ```ignore 140/// use kernel::macro::concat_idents; 141/// 142/// macro_rules! pub_no_prefix { 143/// ($prefix:ident, $($newname:ident),+) => { 144/// $(pub(crate) const $newname: u32 = kernel::macros::concat_idents!($prefix, $newname);)+ 145/// }; 146/// } 147/// 148/// pub_no_prefix!( 149/// binder_driver_return_protocol_, 150/// BR_OK, 151/// BR_ERROR, 152/// BR_TRANSACTION, 153/// BR_REPLY, 154/// BR_DEAD_REPLY, 155/// BR_TRANSACTION_COMPLETE, 156/// BR_INCREFS, 157/// BR_ACQUIRE, 158/// BR_RELEASE, 159/// BR_DECREFS, 160/// BR_NOOP, 161/// BR_SPAWN_LOOPER, 162/// BR_DEAD_BINDER, 163/// BR_CLEAR_DEATH_NOTIFICATION_DONE, 164/// BR_FAILED_REPLY 165/// ); 166/// 167/// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK); 168/// ``` 169#[proc_macro] 170pub fn concat_idents(ts: TokenStream) -> TokenStream { 171 concat_idents::concat_idents(ts) 172} 173 174/// Used to specify the pinning information of the fields of a struct. 175/// 176/// This is somewhat similar in purpose as 177/// [pin-project-lite](https://crates.io/crates/pin-project-lite). 178/// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each 179/// field you want to structurally pin. 180/// 181/// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`, 182/// then `#[pin]` directs the type of initializer that is required. 183/// 184/// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this 185/// macro, and change your `Drop` implementation to `PinnedDrop` annotated with 186/// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care. 187/// 188/// # Examples 189/// 190/// ```rust,ignore 191/// #[pin_data] 192/// struct DriverData { 193/// #[pin] 194/// queue: Mutex<Vec<Command>>, 195/// buf: Box<[u8; 1024 * 1024]>, 196/// } 197/// ``` 198/// 199/// ```rust,ignore 200/// #[pin_data(PinnedDrop)] 201/// struct DriverData { 202/// #[pin] 203/// queue: Mutex<Vec<Command>>, 204/// buf: Box<[u8; 1024 * 1024]>, 205/// raw_info: *mut Info, 206/// } 207/// 208/// #[pinned_drop] 209/// impl PinnedDrop for DriverData { 210/// fn drop(self: Pin<&mut Self>) { 211/// unsafe { bindings::destroy_info(self.raw_info) }; 212/// } 213/// } 214/// ``` 215/// 216/// [`pin_init!`]: ../kernel/macro.pin_init.html 217// ^ cannot use direct link, since `kernel` is not a dependency of `macros`. 218#[proc_macro_attribute] 219pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream { 220 pin_data::pin_data(inner, item) 221} 222 223/// Used to implement `PinnedDrop` safely. 224/// 225/// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`. 226/// 227/// # Examples 228/// 229/// ```rust,ignore 230/// #[pin_data(PinnedDrop)] 231/// struct DriverData { 232/// #[pin] 233/// queue: Mutex<Vec<Command>>, 234/// buf: Box<[u8; 1024 * 1024]>, 235/// raw_info: *mut Info, 236/// } 237/// 238/// #[pinned_drop] 239/// impl PinnedDrop for DriverData { 240/// fn drop(self: Pin<&mut Self>) { 241/// unsafe { bindings::destroy_info(self.raw_info) }; 242/// } 243/// } 244/// ``` 245#[proc_macro_attribute] 246pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { 247 pinned_drop::pinned_drop(args, input) 248}