xref: /openbmc/qemu/rust/qemu-api/src/vmstate.rs (revision a1dacb66915eb7d08a0596cc97068a37c39930d3)
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