xref: /qemu/rust/qemu-api/src/vmstate.rs (revision 0d43ddae35a29d1822ec3f35a31bfe7c91618ef4)
10a65e412SManos Pitsidianakis // Copyright 2024, Linaro Limited
20a65e412SManos Pitsidianakis // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
30a65e412SManos Pitsidianakis // SPDX-License-Identifier: GPL-2.0-or-later
40a65e412SManos Pitsidianakis 
50a65e412SManos Pitsidianakis //! Helper macros to declare migration state for device models.
60a65e412SManos Pitsidianakis //!
7*0d43ddaeSPaolo Bonzini //! This module includes three families of macros:
8*0d43ddaeSPaolo Bonzini //!
9*0d43ddaeSPaolo Bonzini //! * [`vmstate_unused!`](crate::vmstate_unused) and
10*0d43ddaeSPaolo Bonzini //!   [`vmstate_of!`](crate::vmstate_of), which are used to express the
11*0d43ddaeSPaolo Bonzini //!   migration format for a struct.  This is based on the [`VMState`] trait,
12*0d43ddaeSPaolo Bonzini //!   which is defined by all migrateable types.
13*0d43ddaeSPaolo Bonzini //!
14*0d43ddaeSPaolo Bonzini //! * helper macros to declare a device model state struct, in particular
150a65e412SManos Pitsidianakis //!   [`vmstate_subsections`](crate::vmstate_subsections) and
16*0d43ddaeSPaolo Bonzini //!   [`vmstate_fields`](crate::vmstate_fields).
17*0d43ddaeSPaolo Bonzini //!
18*0d43ddaeSPaolo Bonzini //! * direct equivalents to the C macros declared in
19*0d43ddaeSPaolo Bonzini //!   `include/migration/vmstate.h`. These are not type-safe and should not be
20*0d43ddaeSPaolo Bonzini //!   used if the equivalent functionality is available with `vmstate_of!`.
210a65e412SManos Pitsidianakis 
22*0d43ddaeSPaolo Bonzini use core::marker::PhantomData;
23*0d43ddaeSPaolo Bonzini 
24*0d43ddaeSPaolo Bonzini pub use crate::bindings::{VMStateDescription, VMStateField};
25*0d43ddaeSPaolo Bonzini 
26*0d43ddaeSPaolo Bonzini /// This macro is used to call a function with a generic argument bound
27*0d43ddaeSPaolo Bonzini /// to the type of a field.  The function must take a
28*0d43ddaeSPaolo Bonzini /// [`PhantomData`]`<T>` argument; `T` is the type of
29*0d43ddaeSPaolo Bonzini /// field `$field` in the `$typ` type.
30*0d43ddaeSPaolo Bonzini ///
31*0d43ddaeSPaolo Bonzini /// # Examples
32*0d43ddaeSPaolo Bonzini ///
33*0d43ddaeSPaolo Bonzini /// ```
34*0d43ddaeSPaolo Bonzini /// # use qemu_api::call_func_with_field;
35*0d43ddaeSPaolo Bonzini /// # use core::marker::PhantomData;
36*0d43ddaeSPaolo Bonzini /// const fn size_of_field<T>(_: PhantomData<T>) -> usize {
37*0d43ddaeSPaolo Bonzini ///     std::mem::size_of::<T>()
38*0d43ddaeSPaolo Bonzini /// }
39*0d43ddaeSPaolo Bonzini ///
40*0d43ddaeSPaolo Bonzini /// struct Foo {
41*0d43ddaeSPaolo Bonzini ///     x: u16,
42*0d43ddaeSPaolo Bonzini /// };
43*0d43ddaeSPaolo Bonzini /// // calls size_of_field::<u16>()
44*0d43ddaeSPaolo Bonzini /// assert_eq!(call_func_with_field!(size_of_field, Foo, x), 2);
45*0d43ddaeSPaolo Bonzini /// ```
46*0d43ddaeSPaolo Bonzini #[macro_export]
47*0d43ddaeSPaolo Bonzini macro_rules! call_func_with_field {
48*0d43ddaeSPaolo Bonzini     // Based on the answer by user steffahn (Frank Steffahn) at
49*0d43ddaeSPaolo Bonzini     // https://users.rust-lang.org/t/inferring-type-of-field/122857
50*0d43ddaeSPaolo Bonzini     // and used under MIT license
51*0d43ddaeSPaolo Bonzini     ($func:expr, $typ:ty, $($field:tt).+) => {
52*0d43ddaeSPaolo Bonzini         $func(loop {
53*0d43ddaeSPaolo Bonzini             #![allow(unreachable_code)]
54*0d43ddaeSPaolo Bonzini             const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> { ::core::marker::PhantomData }
55*0d43ddaeSPaolo Bonzini             // Unreachable code is exempt from checks on uninitialized values.
56*0d43ddaeSPaolo Bonzini             // Use that trick to infer the type of this PhantomData.
57*0d43ddaeSPaolo Bonzini             break ::core::marker::PhantomData;
58*0d43ddaeSPaolo Bonzini             break phantom__(&{ let value__: $typ; value__.$($field).+ });
59*0d43ddaeSPaolo Bonzini         })
60*0d43ddaeSPaolo Bonzini     };
61*0d43ddaeSPaolo Bonzini }
62*0d43ddaeSPaolo Bonzini 
63*0d43ddaeSPaolo Bonzini /// A trait for types that can be included in a device's migration stream.  It
64*0d43ddaeSPaolo Bonzini /// provides the base contents of a `VMStateField` (minus the name and offset).
65*0d43ddaeSPaolo Bonzini ///
66*0d43ddaeSPaolo Bonzini /// # Safety
67*0d43ddaeSPaolo Bonzini ///
68*0d43ddaeSPaolo Bonzini /// The contents of this trait go straight into structs that are parsed by C
69*0d43ddaeSPaolo Bonzini /// code and used to introspect into other structs.  Be careful.
70*0d43ddaeSPaolo Bonzini pub unsafe trait VMState {
71*0d43ddaeSPaolo Bonzini     /// The base contents of a `VMStateField` (minus the name and offset) for
72*0d43ddaeSPaolo Bonzini     /// the type that is implementing the trait.
73*0d43ddaeSPaolo Bonzini     const BASE: VMStateField;
74*0d43ddaeSPaolo Bonzini }
75*0d43ddaeSPaolo Bonzini 
76*0d43ddaeSPaolo Bonzini /// Internal utility function to retrieve a type's `VMStateField`;
77*0d43ddaeSPaolo Bonzini /// used by [`vmstate_of!`](crate::vmstate_of).
78*0d43ddaeSPaolo Bonzini pub const fn vmstate_base<T: VMState>(_: PhantomData<T>) -> VMStateField {
79*0d43ddaeSPaolo Bonzini     T::BASE
80*0d43ddaeSPaolo Bonzini }
81*0d43ddaeSPaolo Bonzini 
82*0d43ddaeSPaolo Bonzini /// Return the `VMStateField` for a field of a struct.  The field must be
83*0d43ddaeSPaolo Bonzini /// visible in the current scope.
84*0d43ddaeSPaolo Bonzini ///
85*0d43ddaeSPaolo Bonzini /// In order to support other types, the trait `VMState` must be implemented
86*0d43ddaeSPaolo Bonzini /// for them.
87*0d43ddaeSPaolo Bonzini #[macro_export]
88*0d43ddaeSPaolo Bonzini macro_rules! vmstate_of {
89*0d43ddaeSPaolo Bonzini     ($struct_name:ty, $field_name:ident $(,)?) => {
90*0d43ddaeSPaolo Bonzini         $crate::bindings::VMStateField {
91*0d43ddaeSPaolo Bonzini             name: ::core::concat!(::core::stringify!($field_name), "\0")
92*0d43ddaeSPaolo Bonzini                 .as_bytes()
93*0d43ddaeSPaolo Bonzini                 .as_ptr() as *const ::std::os::raw::c_char,
94*0d43ddaeSPaolo Bonzini             offset: $crate::offset_of!($struct_name, $field_name),
95*0d43ddaeSPaolo Bonzini             // Compute most of the VMStateField from the type of the field.
96*0d43ddaeSPaolo Bonzini             ..$crate::call_func_with_field!(
97*0d43ddaeSPaolo Bonzini                 $crate::vmstate::vmstate_base,
98*0d43ddaeSPaolo Bonzini                 $struct_name,
99*0d43ddaeSPaolo Bonzini                 $field_name
100*0d43ddaeSPaolo Bonzini             )
101*0d43ddaeSPaolo Bonzini         }
102*0d43ddaeSPaolo Bonzini     };
103*0d43ddaeSPaolo Bonzini }
104*0d43ddaeSPaolo Bonzini 
105*0d43ddaeSPaolo Bonzini // Add a couple builder-style methods to VMStateField, allowing
106*0d43ddaeSPaolo Bonzini // easy derivation of VMStateField constants from other types.
107*0d43ddaeSPaolo Bonzini impl VMStateField {
108*0d43ddaeSPaolo Bonzini     #[must_use]
109*0d43ddaeSPaolo Bonzini     pub const fn with_version_id(mut self, version_id: i32) -> Self {
110*0d43ddaeSPaolo Bonzini         assert!(version_id >= 0);
111*0d43ddaeSPaolo Bonzini         self.version_id = version_id;
112*0d43ddaeSPaolo Bonzini         self
113*0d43ddaeSPaolo Bonzini     }
114*0d43ddaeSPaolo Bonzini }
115716d89f9SPaolo Bonzini 
1160a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED_BUFFER")]
1170a65e412SManos Pitsidianakis #[macro_export]
1180a65e412SManos Pitsidianakis macro_rules! vmstate_unused_buffer {
1190a65e412SManos Pitsidianakis     ($field_exists_fn:expr, $version_id:expr, $size:expr) => {{
1200a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
121718e255fSPaolo Bonzini             name: c_str!("unused").as_ptr(),
1220a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
1230a65e412SManos Pitsidianakis             offset: 0,
1240a65e412SManos Pitsidianakis             size: $size,
1250a65e412SManos Pitsidianakis             start: 0,
1260a65e412SManos Pitsidianakis             num: 0,
1270a65e412SManos Pitsidianakis             num_offset: 0,
1280a65e412SManos Pitsidianakis             size_offset: 0,
1290a65e412SManos Pitsidianakis             info: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate_info_unused_buffer) },
1300a65e412SManos Pitsidianakis             flags: VMStateFlags::VMS_BUFFER,
1310a65e412SManos Pitsidianakis             vmsd: ::core::ptr::null(),
1320a65e412SManos Pitsidianakis             version_id: $version_id,
1330a65e412SManos Pitsidianakis             struct_version_id: 0,
1340a65e412SManos Pitsidianakis             field_exists: $field_exists_fn,
1350a65e412SManos Pitsidianakis         }
1360a65e412SManos Pitsidianakis     }};
1370a65e412SManos Pitsidianakis }
1380a65e412SManos Pitsidianakis 
1390a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED_V")]
1400a65e412SManos Pitsidianakis #[macro_export]
1410a65e412SManos Pitsidianakis macro_rules! vmstate_unused_v {
1420a65e412SManos Pitsidianakis     ($version_id:expr, $size:expr) => {{
1430a65e412SManos Pitsidianakis         $crate::vmstate_unused_buffer!(None, $version_id, $size)
1440a65e412SManos Pitsidianakis     }};
1450a65e412SManos Pitsidianakis }
1460a65e412SManos Pitsidianakis 
1470a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED")]
1480a65e412SManos Pitsidianakis #[macro_export]
1490a65e412SManos Pitsidianakis macro_rules! vmstate_unused {
1500a65e412SManos Pitsidianakis     ($size:expr) => {{
1510a65e412SManos Pitsidianakis         $crate::vmstate_unused_v!(0, $size)
1520a65e412SManos Pitsidianakis     }};
1530a65e412SManos Pitsidianakis }
1540a65e412SManos Pitsidianakis 
1550a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_SINGLE_TEST")]
1560a65e412SManos Pitsidianakis #[macro_export]
1570a65e412SManos Pitsidianakis macro_rules! vmstate_single_test {
1580a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $field_exists_fn:expr, $version_id:expr, $info:expr, $size:expr) => {{
1590a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
1600a65e412SManos Pitsidianakis             name: ::core::concat!(::core::stringify!($field_name), 0)
1610a65e412SManos Pitsidianakis                 .as_bytes()
1629f7d4520SPaolo Bonzini                 .as_ptr() as *const ::std::os::raw::c_char,
1630a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
164f3518400SJunjie Mao             offset: $crate::offset_of!($struct_name, $field_name),
1650a65e412SManos Pitsidianakis             size: $size,
1660a65e412SManos Pitsidianakis             start: 0,
1670a65e412SManos Pitsidianakis             num: 0,
1680a65e412SManos Pitsidianakis             num_offset: 0,
1690a65e412SManos Pitsidianakis             size_offset: 0,
1700a65e412SManos Pitsidianakis             info: unsafe { $info },
1710a65e412SManos Pitsidianakis             flags: VMStateFlags::VMS_SINGLE,
1720a65e412SManos Pitsidianakis             vmsd: ::core::ptr::null(),
1730a65e412SManos Pitsidianakis             version_id: $version_id,
1740a65e412SManos Pitsidianakis             struct_version_id: 0,
1750a65e412SManos Pitsidianakis             field_exists: $field_exists_fn,
1760a65e412SManos Pitsidianakis         }
1770a65e412SManos Pitsidianakis     }};
1780a65e412SManos Pitsidianakis }
1790a65e412SManos Pitsidianakis 
1800a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_SINGLE")]
1810a65e412SManos Pitsidianakis #[macro_export]
1820a65e412SManos Pitsidianakis macro_rules! vmstate_single {
1830a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $version_id:expr, $info:expr, $size:expr) => {{
1840a65e412SManos Pitsidianakis         $crate::vmstate_single_test!($field_name, $struct_name, None, $version_id, $info, $size)
1850a65e412SManos Pitsidianakis     }};
1860a65e412SManos Pitsidianakis }
1870a65e412SManos Pitsidianakis 
1880a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_V")]
1890a65e412SManos Pitsidianakis #[macro_export]
1900a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_v {
1910a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $version_id:expr) => {{
1920a65e412SManos Pitsidianakis         $crate::vmstate_single!(
1930a65e412SManos Pitsidianakis             $field_name,
1940a65e412SManos Pitsidianakis             $struct_name,
1950a65e412SManos Pitsidianakis             $version_id,
1960a65e412SManos Pitsidianakis             ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32),
1970a65e412SManos Pitsidianakis             ::core::mem::size_of::<u32>()
1980a65e412SManos Pitsidianakis         )
1990a65e412SManos Pitsidianakis     }};
2000a65e412SManos Pitsidianakis }
2010a65e412SManos Pitsidianakis 
2020a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32")]
2030a65e412SManos Pitsidianakis #[macro_export]
2040a65e412SManos Pitsidianakis macro_rules! vmstate_uint32 {
2050a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty) => {{
2060a65e412SManos Pitsidianakis         $crate::vmstate_uint32_v!($field_name, $struct_name, 0)
2070a65e412SManos Pitsidianakis     }};
2080a65e412SManos Pitsidianakis }
2090a65e412SManos Pitsidianakis 
2100a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY")]
2110a65e412SManos Pitsidianakis #[macro_export]
2120a65e412SManos Pitsidianakis macro_rules! vmstate_array {
2130a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $length:expr, $version_id:expr, $info:expr, $size:expr) => {{
2140a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
2150a65e412SManos Pitsidianakis             name: ::core::concat!(::core::stringify!($field_name), 0)
2160a65e412SManos Pitsidianakis                 .as_bytes()
2179f7d4520SPaolo Bonzini                 .as_ptr() as *const ::std::os::raw::c_char,
2180a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
219f3518400SJunjie Mao             offset: $crate::offset_of!($struct_name, $field_name),
2200a65e412SManos Pitsidianakis             size: $size,
2210a65e412SManos Pitsidianakis             start: 0,
2220a65e412SManos Pitsidianakis             num: $length as _,
2230a65e412SManos Pitsidianakis             num_offset: 0,
2240a65e412SManos Pitsidianakis             size_offset: 0,
2250a65e412SManos Pitsidianakis             info: unsafe { $info },
2260a65e412SManos Pitsidianakis             flags: VMStateFlags::VMS_ARRAY,
2270a65e412SManos Pitsidianakis             vmsd: ::core::ptr::null(),
2280a65e412SManos Pitsidianakis             version_id: $version_id,
2290a65e412SManos Pitsidianakis             struct_version_id: 0,
2300a65e412SManos Pitsidianakis             field_exists: None,
2310a65e412SManos Pitsidianakis         }
2320a65e412SManos Pitsidianakis     }};
2330a65e412SManos Pitsidianakis }
2340a65e412SManos Pitsidianakis 
2350a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_ARRAY_V")]
2360a65e412SManos Pitsidianakis #[macro_export]
2370a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_array_v {
2380a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $length:expr, $version_id:expr) => {{
2390a65e412SManos Pitsidianakis         $crate::vmstate_array!(
2400a65e412SManos Pitsidianakis             $field_name,
2410a65e412SManos Pitsidianakis             $struct_name,
2420a65e412SManos Pitsidianakis             $length,
2430a65e412SManos Pitsidianakis             $version_id,
2440a65e412SManos Pitsidianakis             ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32),
2450a65e412SManos Pitsidianakis             ::core::mem::size_of::<u32>()
2460a65e412SManos Pitsidianakis         )
2470a65e412SManos Pitsidianakis     }};
2480a65e412SManos Pitsidianakis }
2490a65e412SManos Pitsidianakis 
2500a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_ARRAY")]
2510a65e412SManos Pitsidianakis #[macro_export]
2520a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_array {
2530a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $length:expr) => {{
2540a65e412SManos Pitsidianakis         $crate::vmstate_uint32_array_v!($field_name, $struct_name, $length, 0)
2550a65e412SManos Pitsidianakis     }};
2560a65e412SManos Pitsidianakis }
2570a65e412SManos Pitsidianakis 
2580a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_STRUCT_POINTER_V")]
2590a65e412SManos Pitsidianakis #[macro_export]
2600a65e412SManos Pitsidianakis macro_rules! vmstate_struct_pointer_v {
2610a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $version_id:expr, $vmsd:expr, $type:ty) => {{
2620a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
2630a65e412SManos Pitsidianakis             name: ::core::concat!(::core::stringify!($field_name), 0)
2640a65e412SManos Pitsidianakis                 .as_bytes()
2659f7d4520SPaolo Bonzini                 .as_ptr() as *const ::std::os::raw::c_char,
2660a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
267f3518400SJunjie Mao             offset: $crate::offset_of!($struct_name, $field_name),
2680a65e412SManos Pitsidianakis             size: ::core::mem::size_of::<*const $type>(),
2690a65e412SManos Pitsidianakis             start: 0,
2700a65e412SManos Pitsidianakis             num: 0,
2710a65e412SManos Pitsidianakis             num_offset: 0,
2720a65e412SManos Pitsidianakis             size_offset: 0,
2730a65e412SManos Pitsidianakis             info: ::core::ptr::null(),
2740a65e412SManos Pitsidianakis             flags: VMStateFlags(VMStateFlags::VMS_STRUCT.0 | VMStateFlags::VMS_POINTER.0),
2750a65e412SManos Pitsidianakis             vmsd: unsafe { $vmsd },
2760a65e412SManos Pitsidianakis             version_id: $version_id,
2770a65e412SManos Pitsidianakis             struct_version_id: 0,
2780a65e412SManos Pitsidianakis             field_exists: None,
2790a65e412SManos Pitsidianakis         }
2800a65e412SManos Pitsidianakis     }};
2810a65e412SManos Pitsidianakis }
2820a65e412SManos Pitsidianakis 
2830a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_OF_POINTER")]
2840a65e412SManos Pitsidianakis #[macro_export]
2850a65e412SManos Pitsidianakis macro_rules! vmstate_array_of_pointer {
2860a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr, $info:expr, $type:ty) => {{
2870a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
2880a65e412SManos Pitsidianakis             name: ::core::concat!(::core::stringify!($field_name), 0)
2890a65e412SManos Pitsidianakis                 .as_bytes()
2909f7d4520SPaolo Bonzini                 .as_ptr() as *const ::std::os::raw::c_char,
2910a65e412SManos Pitsidianakis             version_id: $version_id,
2920a65e412SManos Pitsidianakis             num: $num as _,
2930a65e412SManos Pitsidianakis             info: unsafe { $info },
2940a65e412SManos Pitsidianakis             size: ::core::mem::size_of::<*const $type>(),
2950a65e412SManos Pitsidianakis             flags: VMStateFlags(VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0),
296f3518400SJunjie Mao             offset: $crate::offset_of!($struct_name, $field_name),
2970a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
2980a65e412SManos Pitsidianakis             start: 0,
2990a65e412SManos Pitsidianakis             num_offset: 0,
3000a65e412SManos Pitsidianakis             size_offset: 0,
3010a65e412SManos Pitsidianakis             vmsd: ::core::ptr::null(),
3020a65e412SManos Pitsidianakis             struct_version_id: 0,
3030a65e412SManos Pitsidianakis             field_exists: None,
3040a65e412SManos Pitsidianakis         }
3050a65e412SManos Pitsidianakis     }};
3060a65e412SManos Pitsidianakis }
3070a65e412SManos Pitsidianakis 
3080a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_OF_POINTER_TO_STRUCT")]
3090a65e412SManos Pitsidianakis #[macro_export]
3100a65e412SManos Pitsidianakis macro_rules! vmstate_array_of_pointer_to_struct {
3110a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr, $vmsd:expr, $type:ty) => {{
3120a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
3130a65e412SManos Pitsidianakis             name: ::core::concat!(::core::stringify!($field_name), 0)
3140a65e412SManos Pitsidianakis                 .as_bytes()
3159f7d4520SPaolo Bonzini                 .as_ptr() as *const ::std::os::raw::c_char,
3160a65e412SManos Pitsidianakis             version_id: $version_id,
3170a65e412SManos Pitsidianakis             num: $num as _,
3180a65e412SManos Pitsidianakis             vmsd: unsafe { $vmsd },
3190a65e412SManos Pitsidianakis             size: ::core::mem::size_of::<*const $type>(),
3200a65e412SManos Pitsidianakis             flags: VMStateFlags(
3210a65e412SManos Pitsidianakis                 VMStateFlags::VMS_ARRAY.0
3220a65e412SManos Pitsidianakis                     | VMStateFlags::VMS_STRUCT.0
3230a65e412SManos Pitsidianakis                     | VMStateFlags::VMS_ARRAY_OF_POINTER.0,
3240a65e412SManos Pitsidianakis             ),
325f3518400SJunjie Mao             offset: $crate::offset_of!($struct_name, $field_name),
3260a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
3270a65e412SManos Pitsidianakis             start: 0,
3280a65e412SManos Pitsidianakis             num_offset: 0,
3290a65e412SManos Pitsidianakis             size_offset: 0,
3300a65e412SManos Pitsidianakis             vmsd: ::core::ptr::null(),
3310a65e412SManos Pitsidianakis             struct_version_id: 0,
3320a65e412SManos Pitsidianakis             field_exists: None,
3330a65e412SManos Pitsidianakis         }
3340a65e412SManos Pitsidianakis     }};
3350a65e412SManos Pitsidianakis }
3360a65e412SManos Pitsidianakis 
3370a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_CLOCK_V")]
3380a65e412SManos Pitsidianakis #[macro_export]
3390a65e412SManos Pitsidianakis macro_rules! vmstate_clock_v {
3400a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $version_id:expr) => {{
3410a65e412SManos Pitsidianakis         $crate::vmstate_struct_pointer_v!(
3420a65e412SManos Pitsidianakis             $field_name,
3430a65e412SManos Pitsidianakis             $struct_name,
3440a65e412SManos Pitsidianakis             $version_id,
3450a65e412SManos Pitsidianakis             ::core::ptr::addr_of!($crate::bindings::vmstate_clock),
3460a65e412SManos Pitsidianakis             $crate::bindings::Clock
3470a65e412SManos Pitsidianakis         )
3480a65e412SManos Pitsidianakis     }};
3490a65e412SManos Pitsidianakis }
3500a65e412SManos Pitsidianakis 
3510a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_CLOCK")]
3520a65e412SManos Pitsidianakis #[macro_export]
3530a65e412SManos Pitsidianakis macro_rules! vmstate_clock {
3540a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty) => {{
3550a65e412SManos Pitsidianakis         $crate::vmstate_clock_v!($field_name, $struct_name, 0)
3560a65e412SManos Pitsidianakis     }};
3570a65e412SManos Pitsidianakis }
3580a65e412SManos Pitsidianakis 
3590a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_CLOCK_V")]
3600a65e412SManos Pitsidianakis #[macro_export]
3610a65e412SManos Pitsidianakis macro_rules! vmstate_array_clock_v {
3620a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr) => {{
3630a65e412SManos Pitsidianakis         $crate::vmstate_array_of_pointer_to_struct!(
3640a65e412SManos Pitsidianakis             $field_name,
3650a65e412SManos Pitsidianakis             $struct_name,
3660a65e412SManos Pitsidianakis             $num,
3670a65e412SManos Pitsidianakis             $version_id,
3680a65e412SManos Pitsidianakis             ::core::ptr::addr_of!($crate::bindings::vmstate_clock),
3690a65e412SManos Pitsidianakis             $crate::bindings::Clock
3700a65e412SManos Pitsidianakis         )
3710a65e412SManos Pitsidianakis     }};
3720a65e412SManos Pitsidianakis }
3730a65e412SManos Pitsidianakis 
3740a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_CLOCK")]
3750a65e412SManos Pitsidianakis #[macro_export]
3760a65e412SManos Pitsidianakis macro_rules! vmstate_array_clock {
3770a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $num:expr) => {{
3780a65e412SManos Pitsidianakis         $crate::vmstate_array_clock_v!($field_name, $struct_name, $name, 0)
3790a65e412SManos Pitsidianakis     }};
3800a65e412SManos Pitsidianakis }
3810a65e412SManos Pitsidianakis 
3820a65e412SManos Pitsidianakis /// Helper macro to declare a list of
3830a65e412SManos Pitsidianakis /// ([`VMStateField`](`crate::bindings::VMStateField`)) into a static and return
3840a65e412SManos Pitsidianakis /// a pointer to the array of values it created.
3850a65e412SManos Pitsidianakis #[macro_export]
3860a65e412SManos Pitsidianakis macro_rules! vmstate_fields {
3870a65e412SManos Pitsidianakis     ($($field:expr),*$(,)*) => {{
3880a65e412SManos Pitsidianakis         static _FIELDS: &[$crate::bindings::VMStateField] = &[
3890a65e412SManos Pitsidianakis             $($field),*,
3900a65e412SManos Pitsidianakis             $crate::bindings::VMStateField {
3910a65e412SManos Pitsidianakis                 name: ::core::ptr::null(),
3920a65e412SManos Pitsidianakis                 err_hint: ::core::ptr::null(),
3930a65e412SManos Pitsidianakis                 offset: 0,
3940a65e412SManos Pitsidianakis                 size: 0,
3950a65e412SManos Pitsidianakis                 start: 0,
3960a65e412SManos Pitsidianakis                 num: 0,
3970a65e412SManos Pitsidianakis                 num_offset: 0,
3980a65e412SManos Pitsidianakis                 size_offset: 0,
3990a65e412SManos Pitsidianakis                 info: ::core::ptr::null(),
4000a65e412SManos Pitsidianakis                 flags: VMStateFlags::VMS_END,
4010a65e412SManos Pitsidianakis                 vmsd: ::core::ptr::null(),
4020a65e412SManos Pitsidianakis                 version_id: 0,
4030a65e412SManos Pitsidianakis                 struct_version_id: 0,
4040a65e412SManos Pitsidianakis                 field_exists: None,
4050a65e412SManos Pitsidianakis             }
4060a65e412SManos Pitsidianakis         ];
4070a65e412SManos Pitsidianakis         _FIELDS.as_ptr()
4080a65e412SManos Pitsidianakis     }}
4090a65e412SManos Pitsidianakis }
4100a65e412SManos Pitsidianakis 
4110a65e412SManos Pitsidianakis /// A transparent wrapper type for the `subsections` field of
412716d89f9SPaolo Bonzini /// [`VMStateDescription`].
4130a65e412SManos Pitsidianakis ///
4140a65e412SManos Pitsidianakis /// This is necessary to be able to declare subsection descriptions as statics,
4150a65e412SManos Pitsidianakis /// because the only way to implement `Sync` for a foreign type (and `*const`
4160a65e412SManos Pitsidianakis /// pointers are foreign types in Rust) is to create a wrapper struct and
4170a65e412SManos Pitsidianakis /// `unsafe impl Sync` for it.
4180a65e412SManos Pitsidianakis ///
4190a65e412SManos Pitsidianakis /// This struct is used in the
4200a65e412SManos Pitsidianakis /// [`vm_state_subsections`](crate::vmstate_subsections) macro implementation.
4210a65e412SManos Pitsidianakis #[repr(transparent)]
4220a65e412SManos Pitsidianakis pub struct VMStateSubsectionsWrapper(pub &'static [*const crate::bindings::VMStateDescription]);
4230a65e412SManos Pitsidianakis 
4240a65e412SManos Pitsidianakis unsafe impl Sync for VMStateSubsectionsWrapper {}
4250a65e412SManos Pitsidianakis 
426716d89f9SPaolo Bonzini /// Helper macro to declare a list of subsections ([`VMStateDescription`])
427716d89f9SPaolo Bonzini /// into a static and return a pointer to the array of pointers it created.
4280a65e412SManos Pitsidianakis #[macro_export]
4290a65e412SManos Pitsidianakis macro_rules! vmstate_subsections {
4300a65e412SManos Pitsidianakis     ($($subsection:expr),*$(,)*) => {{
4310a65e412SManos Pitsidianakis         static _SUBSECTIONS: $crate::vmstate::VMStateSubsectionsWrapper = $crate::vmstate::VMStateSubsectionsWrapper(&[
4320a65e412SManos Pitsidianakis             $({
4330a65e412SManos Pitsidianakis                 static _SUBSECTION: $crate::bindings::VMStateDescription = $subsection;
4340a65e412SManos Pitsidianakis                 ::core::ptr::addr_of!(_SUBSECTION)
4350a65e412SManos Pitsidianakis             }),*,
4360a65e412SManos Pitsidianakis             ::core::ptr::null()
4370a65e412SManos Pitsidianakis         ]);
4380a65e412SManos Pitsidianakis         _SUBSECTIONS.0.as_ptr()
4390a65e412SManos Pitsidianakis     }}
4400a65e412SManos Pitsidianakis }
441