Commit | Line | Data |
---|---|---|
1fbde52b MO |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | ||
3 | //! Crate for all kernel procedural macros. | |
4 | ||
70a21e54 GG |
5 | #[macro_use] |
6 | mod quote; | |
60f18c22 | 7 | mod concat_idents; |
1fbde52b MO |
8 | mod helpers; |
9 | mod module; | |
fc6c6baa | 10 | mod pin_data; |
d0fdc396 | 11 | mod pinned_drop; |
b44becc5 | 12 | mod vtable; |
1fbde52b MO |
13 | |
14 | use 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, | |
b13c9880 GG |
32 | /// name: "my_kernel_module", |
33 | /// author: "Rust for Linux Contributors", | |
34 | /// description: "My very own kernel module!", | |
35 | /// license: "GPL", | |
1fbde52b MO |
36 | /// params: { |
37 | /// my_i32: i32 { | |
38 | /// default: 42, | |
39 | /// permissions: 0o000, | |
b13c9880 | 40 | /// description: "Example of i32", |
1fbde52b MO |
41 | /// }, |
42 | /// writeable_i32: i32 { | |
43 | /// default: 42, | |
44 | /// permissions: 0o644, | |
b13c9880 | 45 | /// description: "Example of i32", |
1fbde52b MO |
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] | |
76 | pub fn module(ts: TokenStream) -> TokenStream { | |
77 | module::module(ts) | |
78 | } | |
60f18c22 | 79 | |
b44becc5 GG |
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] | |
127 | pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream { | |
128 | vtable::vtable(attr, ts) | |
129 | } | |
130 | ||
60f18c22 BRB |
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] | |
170 | pub fn concat_idents(ts: TokenStream) -> TokenStream { | |
171 | concat_idents::concat_idents(ts) | |
172 | } | |
fc6c6baa BL |
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 | /// | |
d0fdc396 BL |
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 | /// | |
fc6c6baa BL |
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 | /// | |
d0fdc396 BL |
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 | /// | |
fc6c6baa BL |
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] | |
219 | pub fn pin_data(inner: TokenStream, item: TokenStream) -> TokenStream { | |
220 | pin_data::pin_data(inner, item) | |
221 | } | |
d0fdc396 BL |
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] | |
246 | pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream { | |
247 | pinned_drop::pinned_drop(args, input) | |
248 | } |