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