at v6.6-rc2 10 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 paste; 11mod pin_data; 12mod pinned_drop; 13mod vtable; 14mod zeroable; 15 16use proc_macro::TokenStream; 17 18/// Declares a kernel module. 19/// 20/// The `type` argument should be a type which implements the [`Module`] 21/// trait. Also accepts various forms of kernel metadata. 22/// 23/// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h) 24/// 25/// [`Module`]: ../kernel/trait.Module.html 26/// 27/// # Examples 28/// 29/// ```ignore 30/// use kernel::prelude::*; 31/// 32/// module!{ 33/// type: MyModule, 34/// name: "my_kernel_module", 35/// author: "Rust for Linux Contributors", 36/// description: "My very own kernel module!", 37/// license: "GPL", 38/// params: { 39/// my_i32: i32 { 40/// default: 42, 41/// permissions: 0o000, 42/// description: "Example of i32", 43/// }, 44/// writeable_i32: i32 { 45/// default: 42, 46/// permissions: 0o644, 47/// description: "Example of i32", 48/// }, 49/// }, 50/// } 51/// 52/// struct MyModule; 53/// 54/// impl kernel::Module for MyModule { 55/// fn init() -> Result<Self> { 56/// // If the parameter is writeable, then the kparam lock must be 57/// // taken to read the parameter: 58/// { 59/// let lock = THIS_MODULE.kernel_param_lock(); 60/// pr_info!("i32 param is: {}\n", writeable_i32.read(&lock)); 61/// } 62/// // If the parameter is read only, it can be read without locking 63/// // the kernel parameters: 64/// pr_info!("i32 param is: {}\n", my_i32.read()); 65/// Ok(Self) 66/// } 67/// } 68/// ``` 69/// 70/// # Supported argument types 71/// - `type`: type which implements the [`Module`] trait (required). 72/// - `name`: byte array of the name of the kernel module (required). 73/// - `author`: byte array of the author of the kernel module. 74/// - `description`: byte array of the description of the kernel module. 75/// - `license`: byte array of the license of the kernel module (required). 76/// - `alias`: byte array of alias name of the kernel module. 77#[proc_macro] 78pub fn module(ts: TokenStream) -> TokenStream { 79 module::module(ts) 80} 81 82/// Declares or implements a vtable trait. 83/// 84/// Linux's use of pure vtables is very close to Rust traits, but they differ 85/// in how unimplemented functions are represented. In Rust, traits can provide 86/// default implementation for all non-required methods (and the default 87/// implementation could just return `Error::EINVAL`); Linux typically use C 88/// `NULL` pointers to represent these functions. 89/// 90/// This attribute is intended to close the gap. Traits can be declared and 91/// implemented with the `#[vtable]` attribute, and a `HAS_*` associated constant 92/// will be generated for each method in the trait, indicating if the implementor 93/// has overridden a method. 94/// 95/// This attribute is not needed if all methods are required. 96/// 97/// # Examples 98/// 99/// ```ignore 100/// use kernel::prelude::*; 101/// 102/// // Declares a `#[vtable]` trait 103/// #[vtable] 104/// pub trait Operations: Send + Sync + Sized { 105/// fn foo(&self) -> Result<()> { 106/// Err(EINVAL) 107/// } 108/// 109/// fn bar(&self) -> Result<()> { 110/// Err(EINVAL) 111/// } 112/// } 113/// 114/// struct Foo; 115/// 116/// // Implements the `#[vtable]` trait 117/// #[vtable] 118/// impl Operations for Foo { 119/// fn foo(&self) -> Result<()> { 120/// # Err(EINVAL) 121/// // ... 122/// } 123/// } 124/// 125/// assert_eq!(<Foo as Operations>::HAS_FOO, true); 126/// assert_eq!(<Foo as Operations>::HAS_BAR, false); 127/// ``` 128#[proc_macro_attribute] 129pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream { 130 vtable::vtable(attr, ts) 131} 132 133/// Concatenate two identifiers. 134/// 135/// This is useful in macros that need to declare or reference items with names 136/// starting with a fixed prefix and ending in a user specified name. The resulting 137/// identifier has the span of the second argument. 138/// 139/// # Examples 140/// 141/// ```ignore 142/// use kernel::macro::concat_idents; 143/// 144/// macro_rules! pub_no_prefix { 145/// ($prefix:ident, $($newname:ident),+) => { 146/// $(pub(crate) const $newname: u32 = kernel::macros::concat_idents!($prefix, $newname);)+ 147/// }; 148/// } 149/// 150/// pub_no_prefix!( 151/// binder_driver_return_protocol_, 152/// BR_OK, 153/// BR_ERROR, 154/// BR_TRANSACTION, 155/// BR_REPLY, 156/// BR_DEAD_REPLY, 157/// BR_TRANSACTION_COMPLETE, 158/// BR_INCREFS, 159/// BR_ACQUIRE, 160/// BR_RELEASE, 161/// BR_DECREFS, 162/// BR_NOOP, 163/// BR_SPAWN_LOOPER, 164/// BR_DEAD_BINDER, 165/// BR_CLEAR_DEATH_NOTIFICATION_DONE, 166/// BR_FAILED_REPLY 167/// ); 168/// 169/// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK); 170/// ``` 171#[proc_macro] 172pub fn concat_idents(ts: TokenStream) -> TokenStream { 173 concat_idents::concat_idents(ts) 174} 175 176/// Used to specify the pinning information of the fields of a struct. 177/// 178/// This is somewhat similar in purpose as 179/// [pin-project-lite](https://crates.io/crates/pin-project-lite). 180/// Place this macro on a struct definition and then `#[pin]` in front of the attributes of each 181/// field you want to structurally pin. 182/// 183/// This macro enables the use of the [`pin_init!`] macro. When pin-initializing a `struct`, 184/// then `#[pin]` directs the type of initializer that is required. 185/// 186/// If your `struct` implements `Drop`, then you need to add `PinnedDrop` as arguments to this 187/// macro, and change your `Drop` implementation to `PinnedDrop` annotated with 188/// `#[`[`macro@pinned_drop`]`]`, since dropping pinned values requires extra care. 189/// 190/// # Examples 191/// 192/// ```rust,ignore 193/// #[pin_data] 194/// struct DriverData { 195/// #[pin] 196/// queue: Mutex<Vec<Command>>, 197/// buf: Box<[u8; 1024 * 1024]>, 198/// } 199/// ``` 200/// 201/// ```rust,ignore 202/// #[pin_data(PinnedDrop)] 203/// struct DriverData { 204/// #[pin] 205/// queue: Mutex<Vec<Command>>, 206/// buf: Box<[u8; 1024 * 1024]>, 207/// raw_info: *mut Info, 208/// } 209/// 210/// #[pinned_drop] 211/// impl PinnedDrop for DriverData { 212/// fn drop(self: Pin<&mut Self>) { 213/// unsafe { bindings::destroy_info(self.raw_info) }; 214/// } 215/// } 216/// ``` 217/// 218/// [`pin_init!`]: ../kernel/macro.pin_init.html 219// ^ cannot use direct link, since `kernel` is not a dependency of `macros`. 220#[proc_macro_attribute] 221pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream { 222 pin_data::pin_data(inner, item) 223} 224 225/// Used to implement `PinnedDrop` safely. 226/// 227/// Only works on structs that are annotated via `#[`[`macro@pin_data`]`]`. 228/// 229/// # Examples 230/// 231/// ```rust,ignore 232/// #[pin_data(PinnedDrop)] 233/// struct DriverData { 234/// #[pin] 235/// queue: Mutex<Vec<Command>>, 236/// buf: Box<[u8; 1024 * 1024]>, 237/// raw_info: *mut Info, 238/// } 239/// 240/// #[pinned_drop] 241/// impl PinnedDrop for DriverData { 242/// fn drop(self: Pin<&mut Self>) { 243/// unsafe { bindings::destroy_info(self.raw_info) }; 244/// } 245/// } 246/// ``` 247#[proc_macro_attribute] 248pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { 249 pinned_drop::pinned_drop(args, input) 250} 251 252/// Paste identifiers together. 253/// 254/// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a 255/// single identifier. 256/// 257/// This is similar to the [`paste`] crate, but with pasting feature limited to identifiers 258/// (literals, lifetimes and documentation strings are not supported). There is a difference in 259/// supported modifiers as well. 260/// 261/// # Example 262/// 263/// ```ignore 264/// use kernel::macro::paste; 265/// 266/// macro_rules! pub_no_prefix { 267/// ($prefix:ident, $($newname:ident),+) => { 268/// paste! { 269/// $(pub(crate) const $newname: u32 = [<$prefix $newname>];)+ 270/// } 271/// }; 272/// } 273/// 274/// pub_no_prefix!( 275/// binder_driver_return_protocol_, 276/// BR_OK, 277/// BR_ERROR, 278/// BR_TRANSACTION, 279/// BR_REPLY, 280/// BR_DEAD_REPLY, 281/// BR_TRANSACTION_COMPLETE, 282/// BR_INCREFS, 283/// BR_ACQUIRE, 284/// BR_RELEASE, 285/// BR_DECREFS, 286/// BR_NOOP, 287/// BR_SPAWN_LOOPER, 288/// BR_DEAD_BINDER, 289/// BR_CLEAR_DEATH_NOTIFICATION_DONE, 290/// BR_FAILED_REPLY 291/// ); 292/// 293/// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK); 294/// ``` 295/// 296/// # Modifiers 297/// 298/// For each identifier, it is possible to attach one or multiple modifiers to 299/// it. 300/// 301/// Currently supported modifiers are: 302/// * `span`: change the span of concatenated identifier to the span of the specified token. By 303/// default the span of the `[< >]` group is used. 304/// * `lower`: change the identifier to lower case. 305/// * `upper`: change the identifier to upper case. 306/// 307/// ```ignore 308/// use kernel::macro::paste; 309/// 310/// macro_rules! pub_no_prefix { 311/// ($prefix:ident, $($newname:ident),+) => { 312/// kernel::macros::paste! { 313/// $(pub(crate) const fn [<$newname:lower:span>]: u32 = [<$prefix $newname:span>];)+ 314/// } 315/// }; 316/// } 317/// 318/// pub_no_prefix!( 319/// binder_driver_return_protocol_, 320/// BR_OK, 321/// BR_ERROR, 322/// BR_TRANSACTION, 323/// BR_REPLY, 324/// BR_DEAD_REPLY, 325/// BR_TRANSACTION_COMPLETE, 326/// BR_INCREFS, 327/// BR_ACQUIRE, 328/// BR_RELEASE, 329/// BR_DECREFS, 330/// BR_NOOP, 331/// BR_SPAWN_LOOPER, 332/// BR_DEAD_BINDER, 333/// BR_CLEAR_DEATH_NOTIFICATION_DONE, 334/// BR_FAILED_REPLY 335/// ); 336/// 337/// assert_eq!(br_ok(), binder_driver_return_protocol_BR_OK); 338/// ``` 339/// 340/// [`paste`]: https://docs.rs/paste/ 341#[proc_macro] 342pub fn paste(input: TokenStream) -> TokenStream { 343 let mut tokens = input.into_iter().collect(); 344 paste::expand(&mut tokens); 345 tokens.into_iter().collect() 346} 347 348/// Derives the [`Zeroable`] trait for the given struct. 349/// 350/// This can only be used for structs where every field implements the [`Zeroable`] trait. 351/// 352/// # Examples 353/// 354/// ```rust,ignore 355/// #[derive(Zeroable)] 356/// pub struct DriverData { 357/// id: i64, 358/// buf_ptr: *mut u8, 359/// len: usize, 360/// } 361/// ``` 362#[proc_macro_derive(Zeroable)] 363pub fn derive_zeroable(input: TokenStream) -> TokenStream { 364 zeroable::derive(input) 365}