Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/nova-core/bitfield.rs
38184 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
//! Bitfield library for Rust structures
4
//!
5
//! Support for defining bitfields in Rust structures. Also used by the [`register!`] macro.
6
7
/// Defines a struct with accessors to access bits within an inner unsigned integer.
8
///
9
/// # Syntax
10
///
11
/// ```rust
12
/// use nova_core::bitfield;
13
///
14
/// #[derive(Debug, Clone, Copy, Default)]
15
/// enum Mode {
16
/// #[default]
17
/// Low = 0,
18
/// High = 1,
19
/// Auto = 2,
20
/// }
21
///
22
/// impl TryFrom<u8> for Mode {
23
/// type Error = u8;
24
/// fn try_from(value: u8) -> Result<Self, Self::Error> {
25
/// match value {
26
/// 0 => Ok(Mode::Low),
27
/// 1 => Ok(Mode::High),
28
/// 2 => Ok(Mode::Auto),
29
/// _ => Err(value),
30
/// }
31
/// }
32
/// }
33
///
34
/// impl From<Mode> for u8 {
35
/// fn from(mode: Mode) -> u8 {
36
/// mode as u8
37
/// }
38
/// }
39
///
40
/// #[derive(Debug, Clone, Copy, Default)]
41
/// enum State {
42
/// #[default]
43
/// Inactive = 0,
44
/// Active = 1,
45
/// }
46
///
47
/// impl From<bool> for State {
48
/// fn from(value: bool) -> Self {
49
/// if value { State::Active } else { State::Inactive }
50
/// }
51
/// }
52
///
53
/// impl From<State> for bool {
54
/// fn from(state: State) -> bool {
55
/// match state {
56
/// State::Inactive => false,
57
/// State::Active => true,
58
/// }
59
/// }
60
/// }
61
///
62
/// bitfield! {
63
/// pub struct ControlReg(u32) {
64
/// 7:7 state as bool => State;
65
/// 3:0 mode as u8 ?=> Mode;
66
/// }
67
/// }
68
/// ```
69
///
70
/// This generates a struct with:
71
/// - Field accessors: `mode()`, `state()`, etc.
72
/// - Field setters: `set_mode()`, `set_state()`, etc. (supports chaining with builder pattern).
73
/// Note that the compiler will error out if the size of the setter's arg exceeds the
74
/// struct's storage size.
75
/// - Debug and Default implementations.
76
///
77
/// Note: Field accessors and setters inherit the same visibility as the struct itself.
78
/// In the example above, both `mode()` and `set_mode()` methods will be `pub`.
79
///
80
/// Fields are defined as follows:
81
///
82
/// - `as <type>` simply returns the field value casted to <type>, typically `u32`, `u16`, `u8` or
83
/// `bool`. Note that `bool` fields must have a range of 1 bit.
84
/// - `as <type> => <into_type>` calls `<into_type>`'s `From::<<type>>` implementation and returns
85
/// the result.
86
/// - `as <type> ?=> <try_into_type>` calls `<try_into_type>`'s `TryFrom::<<type>>` implementation
87
/// and returns the result. This is useful with fields for which not all values are valid.
88
macro_rules! bitfield {
89
// Main entry point - defines the bitfield struct with fields
90
($vis:vis struct $name:ident($storage:ty) $(, $comment:literal)? { $($fields:tt)* }) => {
91
bitfield!(@core $vis $name $storage $(, $comment)? { $($fields)* });
92
};
93
94
// All rules below are helpers.
95
96
// Defines the wrapper `$name` type, as well as its relevant implementations (`Debug`,
97
// `Default`, and conversion to the value type) and field accessor methods.
98
(@core $vis:vis $name:ident $storage:ty $(, $comment:literal)? { $($fields:tt)* }) => {
99
$(
100
#[doc=$comment]
101
)?
102
#[repr(transparent)]
103
#[derive(Clone, Copy)]
104
$vis struct $name($storage);
105
106
impl ::core::convert::From<$name> for $storage {
107
fn from(val: $name) -> $storage {
108
val.0
109
}
110
}
111
112
bitfield!(@fields_dispatcher $vis $name $storage { $($fields)* });
113
};
114
115
// Captures the fields and passes them to all the implementers that require field information.
116
//
117
// Used to simplify the matching rules for implementers, so they don't need to match the entire
118
// complex fields rule even though they only make use of part of it.
119
(@fields_dispatcher $vis:vis $name:ident $storage:ty {
120
$($hi:tt:$lo:tt $field:ident as $type:tt
121
$(?=> $try_into_type:ty)?
122
$(=> $into_type:ty)?
123
$(, $comment:literal)?
124
;
125
)*
126
}
127
) => {
128
bitfield!(@field_accessors $vis $name $storage {
129
$(
130
$hi:$lo $field as $type
131
$(?=> $try_into_type)?
132
$(=> $into_type)?
133
$(, $comment)?
134
;
135
)*
136
});
137
bitfield!(@debug $name { $($field;)* });
138
bitfield!(@default $name { $($field;)* });
139
};
140
141
// Defines all the field getter/setter methods for `$name`.
142
(
143
@field_accessors $vis:vis $name:ident $storage:ty {
144
$($hi:tt:$lo:tt $field:ident as $type:tt
145
$(?=> $try_into_type:ty)?
146
$(=> $into_type:ty)?
147
$(, $comment:literal)?
148
;
149
)*
150
}
151
) => {
152
$(
153
bitfield!(@check_field_bounds $hi:$lo $field as $type);
154
)*
155
156
#[allow(dead_code)]
157
impl $name {
158
$(
159
bitfield!(@field_accessor $vis $name $storage, $hi:$lo $field as $type
160
$(?=> $try_into_type)?
161
$(=> $into_type)?
162
$(, $comment)?
163
;
164
);
165
)*
166
}
167
};
168
169
// Boolean fields must have `$hi == $lo`.
170
(@check_field_bounds $hi:tt:$lo:tt $field:ident as bool) => {
171
#[allow(clippy::eq_op)]
172
const _: () = {
173
::kernel::build_assert!(
174
$hi == $lo,
175
concat!("boolean field `", stringify!($field), "` covers more than one bit")
176
);
177
};
178
};
179
180
// Non-boolean fields must have `$hi >= $lo`.
181
(@check_field_bounds $hi:tt:$lo:tt $field:ident as $type:tt) => {
182
#[allow(clippy::eq_op)]
183
const _: () = {
184
::kernel::build_assert!(
185
$hi >= $lo,
186
concat!("field `", stringify!($field), "`'s MSB is smaller than its LSB")
187
);
188
};
189
};
190
191
// Catches fields defined as `bool` and convert them into a boolean value.
192
(
193
@field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as bool
194
=> $into_type:ty $(, $comment:literal)?;
195
) => {
196
bitfield!(
197
@leaf_accessor $vis $name $storage, $hi:$lo $field
198
{ |f| <$into_type>::from(f != 0) }
199
bool $into_type => $into_type $(, $comment)?;
200
);
201
};
202
203
// Shortcut for fields defined as `bool` without the `=>` syntax.
204
(
205
@field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as bool
206
$(, $comment:literal)?;
207
) => {
208
bitfield!(
209
@field_accessor $vis $name $storage, $hi:$lo $field as bool => bool $(, $comment)?;
210
);
211
};
212
213
// Catches the `?=>` syntax for non-boolean fields.
214
(
215
@field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt
216
?=> $try_into_type:ty $(, $comment:literal)?;
217
) => {
218
bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field
219
{ |f| <$try_into_type>::try_from(f as $type) } $type $try_into_type =>
220
::core::result::Result<
221
$try_into_type,
222
<$try_into_type as ::core::convert::TryFrom<$type>>::Error
223
>
224
$(, $comment)?;);
225
};
226
227
// Catches the `=>` syntax for non-boolean fields.
228
(
229
@field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt
230
=> $into_type:ty $(, $comment:literal)?;
231
) => {
232
bitfield!(@leaf_accessor $vis $name $storage, $hi:$lo $field
233
{ |f| <$into_type>::from(f as $type) } $type $into_type => $into_type $(, $comment)?;);
234
};
235
236
// Shortcut for non-boolean fields defined without the `=>` or `?=>` syntax.
237
(
238
@field_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident as $type:tt
239
$(, $comment:literal)?;
240
) => {
241
bitfield!(
242
@field_accessor $vis $name $storage, $hi:$lo $field as $type => $type $(, $comment)?;
243
);
244
};
245
246
// Generates the accessor methods for a single field.
247
(
248
@leaf_accessor $vis:vis $name:ident $storage:ty, $hi:tt:$lo:tt $field:ident
249
{ $process:expr } $prim_type:tt $to_type:ty => $res_type:ty $(, $comment:literal)?;
250
) => {
251
::kernel::macros::paste!(
252
const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi;
253
const [<$field:upper _MASK>]: $storage = {
254
// Generate mask for shifting
255
match ::core::mem::size_of::<$storage>() {
256
1 => ::kernel::bits::genmask_u8($lo..=$hi) as $storage,
257
2 => ::kernel::bits::genmask_u16($lo..=$hi) as $storage,
258
4 => ::kernel::bits::genmask_u32($lo..=$hi) as $storage,
259
8 => ::kernel::bits::genmask_u64($lo..=$hi) as $storage,
260
_ => ::kernel::build_error!("Unsupported storage type size")
261
}
262
};
263
const [<$field:upper _SHIFT>]: u32 = $lo;
264
);
265
266
$(
267
#[doc="Returns the value of this field:"]
268
#[doc=$comment]
269
)?
270
#[inline(always)]
271
$vis fn $field(self) -> $res_type {
272
::kernel::macros::paste!(
273
const MASK: $storage = $name::[<$field:upper _MASK>];
274
const SHIFT: u32 = $name::[<$field:upper _SHIFT>];
275
);
276
let field = ((self.0 & MASK) >> SHIFT);
277
278
$process(field)
279
}
280
281
::kernel::macros::paste!(
282
$(
283
#[doc="Sets the value of this field:"]
284
#[doc=$comment]
285
)?
286
#[inline(always)]
287
$vis fn [<set_ $field>](mut self, value: $to_type) -> Self {
288
const MASK: $storage = $name::[<$field:upper _MASK>];
289
const SHIFT: u32 = $name::[<$field:upper _SHIFT>];
290
let value = ($storage::from($prim_type::from(value)) << SHIFT) & MASK;
291
self.0 = (self.0 & !MASK) | value;
292
293
self
294
}
295
);
296
};
297
298
// Generates the `Debug` implementation for `$name`.
299
(@debug $name:ident { $($field:ident;)* }) => {
300
impl ::kernel::fmt::Debug for $name {
301
fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result {
302
f.debug_struct(stringify!($name))
303
.field("<raw>", &::kernel::prelude::fmt!("{:#x}", &self.0))
304
$(
305
.field(stringify!($field), &self.$field())
306
)*
307
.finish()
308
}
309
}
310
};
311
312
// Generates the `Default` implementation for `$name`.
313
(@default $name:ident { $($field:ident;)* }) => {
314
/// Returns a value for the bitfield where all fields are set to their default value.
315
impl ::core::default::Default for $name {
316
fn default() -> Self {
317
#[allow(unused_mut)]
318
let mut value = Self(Default::default());
319
320
::kernel::macros::paste!(
321
$(
322
value.[<set_ $field>](Default::default());
323
)*
324
);
325
326
value
327
}
328
}
329
};
330
}
331
332