xref: /openbmc/qemu/rust/qemu-api/src/vmstate.rs (revision 7d87775f)
1 // Copyright 2024, Linaro Limited
2 // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
3 // SPDX-License-Identifier: GPL-2.0-or-later
4 
5 //! Helper macros to declare migration state for device models.
6 //!
7 //! Some macros are direct equivalents to the C macros declared in
8 //! `include/migration/vmstate.h` while
9 //! [`vmstate_subsections`](crate::vmstate_subsections) and
10 //! [`vmstate_fields`](crate::vmstate_fields) are meant to be used when
11 //! declaring a device model state struct.
12 
13 #[doc(alias = "VMSTATE_UNUSED_BUFFER")]
14 #[macro_export]
15 macro_rules! vmstate_unused_buffer {
16     ($field_exists_fn:expr, $version_id:expr, $size:expr) => {{
17         $crate::bindings::VMStateField {
18             name: c_str!("unused").as_ptr(),
19             err_hint: ::core::ptr::null(),
20             offset: 0,
21             size: $size,
22             start: 0,
23             num: 0,
24             num_offset: 0,
25             size_offset: 0,
26             info: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate_info_unused_buffer) },
27             flags: VMStateFlags::VMS_BUFFER,
28             vmsd: ::core::ptr::null(),
29             version_id: $version_id,
30             struct_version_id: 0,
31             field_exists: $field_exists_fn,
32         }
33     }};
34 }
35 
36 #[doc(alias = "VMSTATE_UNUSED_V")]
37 #[macro_export]
38 macro_rules! vmstate_unused_v {
39     ($version_id:expr, $size:expr) => {{
40         $crate::vmstate_unused_buffer!(None, $version_id, $size)
41     }};
42 }
43 
44 #[doc(alias = "VMSTATE_UNUSED")]
45 #[macro_export]
46 macro_rules! vmstate_unused {
47     ($size:expr) => {{
48         $crate::vmstate_unused_v!(0, $size)
49     }};
50 }
51 
52 #[doc(alias = "VMSTATE_SINGLE_TEST")]
53 #[macro_export]
54 macro_rules! vmstate_single_test {
55     ($field_name:ident, $struct_name:ty, $field_exists_fn:expr, $version_id:expr, $info:expr, $size:expr) => {{
56         $crate::bindings::VMStateField {
57             name: ::core::concat!(::core::stringify!($field_name), 0)
58                 .as_bytes()
59                 .as_ptr() as *const ::std::os::raw::c_char,
60             err_hint: ::core::ptr::null(),
61             offset: $crate::offset_of!($struct_name, $field_name),
62             size: $size,
63             start: 0,
64             num: 0,
65             num_offset: 0,
66             size_offset: 0,
67             info: unsafe { $info },
68             flags: VMStateFlags::VMS_SINGLE,
69             vmsd: ::core::ptr::null(),
70             version_id: $version_id,
71             struct_version_id: 0,
72             field_exists: $field_exists_fn,
73         }
74     }};
75 }
76 
77 #[doc(alias = "VMSTATE_SINGLE")]
78 #[macro_export]
79 macro_rules! vmstate_single {
80     ($field_name:ident, $struct_name:ty, $version_id:expr, $info:expr, $size:expr) => {{
81         $crate::vmstate_single_test!($field_name, $struct_name, None, $version_id, $info, $size)
82     }};
83 }
84 
85 #[doc(alias = "VMSTATE_UINT32_V")]
86 #[macro_export]
87 macro_rules! vmstate_uint32_v {
88     ($field_name:ident, $struct_name:ty, $version_id:expr) => {{
89         $crate::vmstate_single!(
90             $field_name,
91             $struct_name,
92             $version_id,
93             ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32),
94             ::core::mem::size_of::<u32>()
95         )
96     }};
97 }
98 
99 #[doc(alias = "VMSTATE_UINT32")]
100 #[macro_export]
101 macro_rules! vmstate_uint32 {
102     ($field_name:ident, $struct_name:ty) => {{
103         $crate::vmstate_uint32_v!($field_name, $struct_name, 0)
104     }};
105 }
106 
107 #[doc(alias = "VMSTATE_INT32_V")]
108 #[macro_export]
109 macro_rules! vmstate_int32_v {
110     ($field_name:ident, $struct_name:ty, $version_id:expr) => {{
111         $crate::vmstate_single!(
112             $field_name,
113             $struct_name,
114             $version_id,
115             ::core::ptr::addr_of!($crate::bindings::vmstate_info_int32),
116             ::core::mem::size_of::<i32>()
117         )
118     }};
119 }
120 
121 #[doc(alias = "VMSTATE_INT32")]
122 #[macro_export]
123 macro_rules! vmstate_int32 {
124     ($field_name:ident, $struct_name:ty) => {{
125         $crate::vmstate_int32_v!($field_name, $struct_name, 0)
126     }};
127 }
128 
129 #[doc(alias = "VMSTATE_ARRAY")]
130 #[macro_export]
131 macro_rules! vmstate_array {
132     ($field_name:ident, $struct_name:ty, $length:expr, $version_id:expr, $info:expr, $size:expr) => {{
133         $crate::bindings::VMStateField {
134             name: ::core::concat!(::core::stringify!($field_name), 0)
135                 .as_bytes()
136                 .as_ptr() as *const ::std::os::raw::c_char,
137             err_hint: ::core::ptr::null(),
138             offset: $crate::offset_of!($struct_name, $field_name),
139             size: $size,
140             start: 0,
141             num: $length as _,
142             num_offset: 0,
143             size_offset: 0,
144             info: unsafe { $info },
145             flags: VMStateFlags::VMS_ARRAY,
146             vmsd: ::core::ptr::null(),
147             version_id: $version_id,
148             struct_version_id: 0,
149             field_exists: None,
150         }
151     }};
152 }
153 
154 #[doc(alias = "VMSTATE_UINT32_ARRAY_V")]
155 #[macro_export]
156 macro_rules! vmstate_uint32_array_v {
157     ($field_name:ident, $struct_name:ty, $length:expr, $version_id:expr) => {{
158         $crate::vmstate_array!(
159             $field_name,
160             $struct_name,
161             $length,
162             $version_id,
163             ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32),
164             ::core::mem::size_of::<u32>()
165         )
166     }};
167 }
168 
169 #[doc(alias = "VMSTATE_UINT32_ARRAY")]
170 #[macro_export]
171 macro_rules! vmstate_uint32_array {
172     ($field_name:ident, $struct_name:ty, $length:expr) => {{
173         $crate::vmstate_uint32_array_v!($field_name, $struct_name, $length, 0)
174     }};
175 }
176 
177 #[doc(alias = "VMSTATE_STRUCT_POINTER_V")]
178 #[macro_export]
179 macro_rules! vmstate_struct_pointer_v {
180     ($field_name:ident, $struct_name:ty, $version_id:expr, $vmsd:expr, $type:ty) => {{
181         $crate::bindings::VMStateField {
182             name: ::core::concat!(::core::stringify!($field_name), 0)
183                 .as_bytes()
184                 .as_ptr() as *const ::std::os::raw::c_char,
185             err_hint: ::core::ptr::null(),
186             offset: $crate::offset_of!($struct_name, $field_name),
187             size: ::core::mem::size_of::<*const $type>(),
188             start: 0,
189             num: 0,
190             num_offset: 0,
191             size_offset: 0,
192             info: ::core::ptr::null(),
193             flags: VMStateFlags(VMStateFlags::VMS_STRUCT.0 | VMStateFlags::VMS_POINTER.0),
194             vmsd: unsafe { $vmsd },
195             version_id: $version_id,
196             struct_version_id: 0,
197             field_exists: None,
198         }
199     }};
200 }
201 
202 #[doc(alias = "VMSTATE_ARRAY_OF_POINTER")]
203 #[macro_export]
204 macro_rules! vmstate_array_of_pointer {
205     ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr, $info:expr, $type:ty) => {{
206         $crate::bindings::VMStateField {
207             name: ::core::concat!(::core::stringify!($field_name), 0)
208                 .as_bytes()
209                 .as_ptr() as *const ::std::os::raw::c_char,
210             version_id: $version_id,
211             num: $num as _,
212             info: unsafe { $info },
213             size: ::core::mem::size_of::<*const $type>(),
214             flags: VMStateFlags(VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0),
215             offset: $crate::offset_of!($struct_name, $field_name),
216             err_hint: ::core::ptr::null(),
217             start: 0,
218             num_offset: 0,
219             size_offset: 0,
220             vmsd: ::core::ptr::null(),
221             struct_version_id: 0,
222             field_exists: None,
223         }
224     }};
225 }
226 
227 #[doc(alias = "VMSTATE_ARRAY_OF_POINTER_TO_STRUCT")]
228 #[macro_export]
229 macro_rules! vmstate_array_of_pointer_to_struct {
230     ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr, $vmsd:expr, $type:ty) => {{
231         $crate::bindings::VMStateField {
232             name: ::core::concat!(::core::stringify!($field_name), 0)
233                 .as_bytes()
234                 .as_ptr() as *const ::std::os::raw::c_char,
235             version_id: $version_id,
236             num: $num as _,
237             vmsd: unsafe { $vmsd },
238             size: ::core::mem::size_of::<*const $type>(),
239             flags: VMStateFlags(
240                 VMStateFlags::VMS_ARRAY.0
241                     | VMStateFlags::VMS_STRUCT.0
242                     | VMStateFlags::VMS_ARRAY_OF_POINTER.0,
243             ),
244             offset: $crate::offset_of!($struct_name, $field_name),
245             err_hint: ::core::ptr::null(),
246             start: 0,
247             num_offset: 0,
248             size_offset: 0,
249             vmsd: ::core::ptr::null(),
250             struct_version_id: 0,
251             field_exists: None,
252         }
253     }};
254 }
255 
256 #[doc(alias = "VMSTATE_CLOCK_V")]
257 #[macro_export]
258 macro_rules! vmstate_clock_v {
259     ($field_name:ident, $struct_name:ty, $version_id:expr) => {{
260         $crate::vmstate_struct_pointer_v!(
261             $field_name,
262             $struct_name,
263             $version_id,
264             ::core::ptr::addr_of!($crate::bindings::vmstate_clock),
265             $crate::bindings::Clock
266         )
267     }};
268 }
269 
270 #[doc(alias = "VMSTATE_CLOCK")]
271 #[macro_export]
272 macro_rules! vmstate_clock {
273     ($field_name:ident, $struct_name:ty) => {{
274         $crate::vmstate_clock_v!($field_name, $struct_name, 0)
275     }};
276 }
277 
278 #[doc(alias = "VMSTATE_ARRAY_CLOCK_V")]
279 #[macro_export]
280 macro_rules! vmstate_array_clock_v {
281     ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr) => {{
282         $crate::vmstate_array_of_pointer_to_struct!(
283             $field_name,
284             $struct_name,
285             $num,
286             $version_id,
287             ::core::ptr::addr_of!($crate::bindings::vmstate_clock),
288             $crate::bindings::Clock
289         )
290     }};
291 }
292 
293 #[doc(alias = "VMSTATE_ARRAY_CLOCK")]
294 #[macro_export]
295 macro_rules! vmstate_array_clock {
296     ($field_name:ident, $struct_name:ty, $num:expr) => {{
297         $crate::vmstate_array_clock_v!($field_name, $struct_name, $name, 0)
298     }};
299 }
300 
301 /// Helper macro to declare a list of
302 /// ([`VMStateField`](`crate::bindings::VMStateField`)) into a static and return
303 /// a pointer to the array of values it created.
304 #[macro_export]
305 macro_rules! vmstate_fields {
306     ($($field:expr),*$(,)*) => {{
307         static _FIELDS: &[$crate::bindings::VMStateField] = &[
308             $($field),*,
309             $crate::bindings::VMStateField {
310                 name: ::core::ptr::null(),
311                 err_hint: ::core::ptr::null(),
312                 offset: 0,
313                 size: 0,
314                 start: 0,
315                 num: 0,
316                 num_offset: 0,
317                 size_offset: 0,
318                 info: ::core::ptr::null(),
319                 flags: VMStateFlags::VMS_END,
320                 vmsd: ::core::ptr::null(),
321                 version_id: 0,
322                 struct_version_id: 0,
323                 field_exists: None,
324             }
325         ];
326         _FIELDS.as_ptr()
327     }}
328 }
329 
330 /// A transparent wrapper type for the `subsections` field of
331 /// [`VMStateDescription`](crate::bindings::VMStateDescription).
332 ///
333 /// This is necessary to be able to declare subsection descriptions as statics,
334 /// because the only way to implement `Sync` for a foreign type (and `*const`
335 /// pointers are foreign types in Rust) is to create a wrapper struct and
336 /// `unsafe impl Sync` for it.
337 ///
338 /// This struct is used in the
339 /// [`vm_state_subsections`](crate::vmstate_subsections) macro implementation.
340 #[repr(transparent)]
341 pub struct VMStateSubsectionsWrapper(pub &'static [*const crate::bindings::VMStateDescription]);
342 
343 unsafe impl Sync for VMStateSubsectionsWrapper {}
344 
345 /// Helper macro to declare a list of subsections
346 /// ([`VMStateDescription`](`crate::bindings::VMStateDescription`)) into a
347 /// static and return a pointer to the array of pointers it created.
348 #[macro_export]
349 macro_rules! vmstate_subsections {
350     ($($subsection:expr),*$(,)*) => {{
351         static _SUBSECTIONS: $crate::vmstate::VMStateSubsectionsWrapper = $crate::vmstate::VMStateSubsectionsWrapper(&[
352             $({
353                 static _SUBSECTION: $crate::bindings::VMStateDescription = $subsection;
354                 ::core::ptr::addr_of!(_SUBSECTION)
355             }),*,
356             ::core::ptr::null()
357         ]);
358         _SUBSECTIONS.0.as_ptr()
359     }}
360 }
361