xref: /openbmc/qemu/rust/qemu-api/src/vmstate.rs (revision 9f7d4520)
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 //!
70a65e412SManos Pitsidianakis //! Some macros are direct equivalents to the C macros declared in
80a65e412SManos Pitsidianakis //! `include/migration/vmstate.h` while
90a65e412SManos Pitsidianakis //! [`vmstate_subsections`](crate::vmstate_subsections) and
100a65e412SManos Pitsidianakis //! [`vmstate_fields`](crate::vmstate_fields) are meant to be used when
110a65e412SManos Pitsidianakis //! declaring a device model state struct.
120a65e412SManos Pitsidianakis 
130a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED_BUFFER")]
140a65e412SManos Pitsidianakis #[macro_export]
150a65e412SManos Pitsidianakis macro_rules! vmstate_unused_buffer {
160a65e412SManos Pitsidianakis     ($field_exists_fn:expr, $version_id:expr, $size:expr) => {{
170a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
180a65e412SManos Pitsidianakis             name: c"unused".as_ptr(),
190a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
200a65e412SManos Pitsidianakis             offset: 0,
210a65e412SManos Pitsidianakis             size: $size,
220a65e412SManos Pitsidianakis             start: 0,
230a65e412SManos Pitsidianakis             num: 0,
240a65e412SManos Pitsidianakis             num_offset: 0,
250a65e412SManos Pitsidianakis             size_offset: 0,
260a65e412SManos Pitsidianakis             info: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate_info_unused_buffer) },
270a65e412SManos Pitsidianakis             flags: VMStateFlags::VMS_BUFFER,
280a65e412SManos Pitsidianakis             vmsd: ::core::ptr::null(),
290a65e412SManos Pitsidianakis             version_id: $version_id,
300a65e412SManos Pitsidianakis             struct_version_id: 0,
310a65e412SManos Pitsidianakis             field_exists: $field_exists_fn,
320a65e412SManos Pitsidianakis         }
330a65e412SManos Pitsidianakis     }};
340a65e412SManos Pitsidianakis }
350a65e412SManos Pitsidianakis 
360a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED_V")]
370a65e412SManos Pitsidianakis #[macro_export]
380a65e412SManos Pitsidianakis macro_rules! vmstate_unused_v {
390a65e412SManos Pitsidianakis     ($version_id:expr, $size:expr) => {{
400a65e412SManos Pitsidianakis         $crate::vmstate_unused_buffer!(None, $version_id, $size)
410a65e412SManos Pitsidianakis     }};
420a65e412SManos Pitsidianakis }
430a65e412SManos Pitsidianakis 
440a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED")]
450a65e412SManos Pitsidianakis #[macro_export]
460a65e412SManos Pitsidianakis macro_rules! vmstate_unused {
470a65e412SManos Pitsidianakis     ($size:expr) => {{
480a65e412SManos Pitsidianakis         $crate::vmstate_unused_v!(0, $size)
490a65e412SManos Pitsidianakis     }};
500a65e412SManos Pitsidianakis }
510a65e412SManos Pitsidianakis 
520a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_SINGLE_TEST")]
530a65e412SManos Pitsidianakis #[macro_export]
540a65e412SManos Pitsidianakis macro_rules! vmstate_single_test {
550a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $field_exists_fn:expr, $version_id:expr, $info:expr, $size:expr) => {{
560a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
570a65e412SManos Pitsidianakis             name: ::core::concat!(::core::stringify!($field_name), 0)
580a65e412SManos Pitsidianakis                 .as_bytes()
59*9f7d4520SPaolo Bonzini                 .as_ptr() as *const ::std::os::raw::c_char,
600a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
610a65e412SManos Pitsidianakis             offset: ::core::mem::offset_of!($struct_name, $field_name),
620a65e412SManos Pitsidianakis             size: $size,
630a65e412SManos Pitsidianakis             start: 0,
640a65e412SManos Pitsidianakis             num: 0,
650a65e412SManos Pitsidianakis             num_offset: 0,
660a65e412SManos Pitsidianakis             size_offset: 0,
670a65e412SManos Pitsidianakis             info: unsafe { $info },
680a65e412SManos Pitsidianakis             flags: VMStateFlags::VMS_SINGLE,
690a65e412SManos Pitsidianakis             vmsd: ::core::ptr::null(),
700a65e412SManos Pitsidianakis             version_id: $version_id,
710a65e412SManos Pitsidianakis             struct_version_id: 0,
720a65e412SManos Pitsidianakis             field_exists: $field_exists_fn,
730a65e412SManos Pitsidianakis         }
740a65e412SManos Pitsidianakis     }};
750a65e412SManos Pitsidianakis }
760a65e412SManos Pitsidianakis 
770a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_SINGLE")]
780a65e412SManos Pitsidianakis #[macro_export]
790a65e412SManos Pitsidianakis macro_rules! vmstate_single {
800a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $version_id:expr, $info:expr, $size:expr) => {{
810a65e412SManos Pitsidianakis         $crate::vmstate_single_test!($field_name, $struct_name, None, $version_id, $info, $size)
820a65e412SManos Pitsidianakis     }};
830a65e412SManos Pitsidianakis }
840a65e412SManos Pitsidianakis 
850a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_V")]
860a65e412SManos Pitsidianakis #[macro_export]
870a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_v {
880a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $version_id:expr) => {{
890a65e412SManos Pitsidianakis         $crate::vmstate_single!(
900a65e412SManos Pitsidianakis             $field_name,
910a65e412SManos Pitsidianakis             $struct_name,
920a65e412SManos Pitsidianakis             $version_id,
930a65e412SManos Pitsidianakis             ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32),
940a65e412SManos Pitsidianakis             ::core::mem::size_of::<u32>()
950a65e412SManos Pitsidianakis         )
960a65e412SManos Pitsidianakis     }};
970a65e412SManos Pitsidianakis }
980a65e412SManos Pitsidianakis 
990a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32")]
1000a65e412SManos Pitsidianakis #[macro_export]
1010a65e412SManos Pitsidianakis macro_rules! vmstate_uint32 {
1020a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty) => {{
1030a65e412SManos Pitsidianakis         $crate::vmstate_uint32_v!($field_name, $struct_name, 0)
1040a65e412SManos Pitsidianakis     }};
1050a65e412SManos Pitsidianakis }
1060a65e412SManos Pitsidianakis 
1070a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_INT32_V")]
1080a65e412SManos Pitsidianakis #[macro_export]
1090a65e412SManos Pitsidianakis macro_rules! vmstate_int32_v {
1100a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $version_id:expr) => {{
1110a65e412SManos Pitsidianakis         $crate::vmstate_single!(
1120a65e412SManos Pitsidianakis             $field_name,
1130a65e412SManos Pitsidianakis             $struct_name,
1140a65e412SManos Pitsidianakis             $version_id,
1150a65e412SManos Pitsidianakis             ::core::ptr::addr_of!($crate::bindings::vmstate_info_int32),
1160a65e412SManos Pitsidianakis             ::core::mem::size_of::<i32>()
1170a65e412SManos Pitsidianakis         )
1180a65e412SManos Pitsidianakis     }};
1190a65e412SManos Pitsidianakis }
1200a65e412SManos Pitsidianakis 
1210a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_INT32")]
1220a65e412SManos Pitsidianakis #[macro_export]
1230a65e412SManos Pitsidianakis macro_rules! vmstate_int32 {
1240a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty) => {{
1250a65e412SManos Pitsidianakis         $crate::vmstate_int32_v!($field_name, $struct_name, 0)
1260a65e412SManos Pitsidianakis     }};
1270a65e412SManos Pitsidianakis }
1280a65e412SManos Pitsidianakis 
1290a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY")]
1300a65e412SManos Pitsidianakis #[macro_export]
1310a65e412SManos Pitsidianakis macro_rules! vmstate_array {
1320a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $length:expr, $version_id:expr, $info:expr, $size:expr) => {{
1330a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
1340a65e412SManos Pitsidianakis             name: ::core::concat!(::core::stringify!($field_name), 0)
1350a65e412SManos Pitsidianakis                 .as_bytes()
136*9f7d4520SPaolo Bonzini                 .as_ptr() as *const ::std::os::raw::c_char,
1370a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
1380a65e412SManos Pitsidianakis             offset: ::core::mem::offset_of!($struct_name, $field_name),
1390a65e412SManos Pitsidianakis             size: $size,
1400a65e412SManos Pitsidianakis             start: 0,
1410a65e412SManos Pitsidianakis             num: $length as _,
1420a65e412SManos Pitsidianakis             num_offset: 0,
1430a65e412SManos Pitsidianakis             size_offset: 0,
1440a65e412SManos Pitsidianakis             info: unsafe { $info },
1450a65e412SManos Pitsidianakis             flags: VMStateFlags::VMS_ARRAY,
1460a65e412SManos Pitsidianakis             vmsd: ::core::ptr::null(),
1470a65e412SManos Pitsidianakis             version_id: $version_id,
1480a65e412SManos Pitsidianakis             struct_version_id: 0,
1490a65e412SManos Pitsidianakis             field_exists: None,
1500a65e412SManos Pitsidianakis         }
1510a65e412SManos Pitsidianakis     }};
1520a65e412SManos Pitsidianakis }
1530a65e412SManos Pitsidianakis 
1540a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_ARRAY_V")]
1550a65e412SManos Pitsidianakis #[macro_export]
1560a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_array_v {
1570a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $length:expr, $version_id:expr) => {{
1580a65e412SManos Pitsidianakis         $crate::vmstate_array!(
1590a65e412SManos Pitsidianakis             $field_name,
1600a65e412SManos Pitsidianakis             $struct_name,
1610a65e412SManos Pitsidianakis             $length,
1620a65e412SManos Pitsidianakis             $version_id,
1630a65e412SManos Pitsidianakis             ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32),
1640a65e412SManos Pitsidianakis             ::core::mem::size_of::<u32>()
1650a65e412SManos Pitsidianakis         )
1660a65e412SManos Pitsidianakis     }};
1670a65e412SManos Pitsidianakis }
1680a65e412SManos Pitsidianakis 
1690a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_ARRAY")]
1700a65e412SManos Pitsidianakis #[macro_export]
1710a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_array {
1720a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $length:expr) => {{
1730a65e412SManos Pitsidianakis         $crate::vmstate_uint32_array_v!($field_name, $struct_name, $length, 0)
1740a65e412SManos Pitsidianakis     }};
1750a65e412SManos Pitsidianakis }
1760a65e412SManos Pitsidianakis 
1770a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_STRUCT_POINTER_V")]
1780a65e412SManos Pitsidianakis #[macro_export]
1790a65e412SManos Pitsidianakis macro_rules! vmstate_struct_pointer_v {
1800a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $version_id:expr, $vmsd:expr, $type:ty) => {{
1810a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
1820a65e412SManos Pitsidianakis             name: ::core::concat!(::core::stringify!($field_name), 0)
1830a65e412SManos Pitsidianakis                 .as_bytes()
184*9f7d4520SPaolo Bonzini                 .as_ptr() as *const ::std::os::raw::c_char,
1850a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
1860a65e412SManos Pitsidianakis             offset: ::core::mem::offset_of!($struct_name, $field_name),
1870a65e412SManos Pitsidianakis             size: ::core::mem::size_of::<*const $type>(),
1880a65e412SManos Pitsidianakis             start: 0,
1890a65e412SManos Pitsidianakis             num: 0,
1900a65e412SManos Pitsidianakis             num_offset: 0,
1910a65e412SManos Pitsidianakis             size_offset: 0,
1920a65e412SManos Pitsidianakis             info: ::core::ptr::null(),
1930a65e412SManos Pitsidianakis             flags: VMStateFlags(VMStateFlags::VMS_STRUCT.0 | VMStateFlags::VMS_POINTER.0),
1940a65e412SManos Pitsidianakis             vmsd: unsafe { $vmsd },
1950a65e412SManos Pitsidianakis             version_id: $version_id,
1960a65e412SManos Pitsidianakis             struct_version_id: 0,
1970a65e412SManos Pitsidianakis             field_exists: None,
1980a65e412SManos Pitsidianakis         }
1990a65e412SManos Pitsidianakis     }};
2000a65e412SManos Pitsidianakis }
2010a65e412SManos Pitsidianakis 
2020a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_OF_POINTER")]
2030a65e412SManos Pitsidianakis #[macro_export]
2040a65e412SManos Pitsidianakis macro_rules! vmstate_array_of_pointer {
2050a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr, $info:expr, $type:ty) => {{
2060a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
2070a65e412SManos Pitsidianakis             name: ::core::concat!(::core::stringify!($field_name), 0)
2080a65e412SManos Pitsidianakis                 .as_bytes()
209*9f7d4520SPaolo Bonzini                 .as_ptr() as *const ::std::os::raw::c_char,
2100a65e412SManos Pitsidianakis             version_id: $version_id,
2110a65e412SManos Pitsidianakis             num: $num as _,
2120a65e412SManos Pitsidianakis             info: unsafe { $info },
2130a65e412SManos Pitsidianakis             size: ::core::mem::size_of::<*const $type>(),
2140a65e412SManos Pitsidianakis             flags: VMStateFlags(VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0),
2150a65e412SManos Pitsidianakis             offset: ::core::mem::offset_of!($struct_name, $field_name),
2160a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
2170a65e412SManos Pitsidianakis             start: 0,
2180a65e412SManos Pitsidianakis             num_offset: 0,
2190a65e412SManos Pitsidianakis             size_offset: 0,
2200a65e412SManos Pitsidianakis             vmsd: ::core::ptr::null(),
2210a65e412SManos Pitsidianakis             struct_version_id: 0,
2220a65e412SManos Pitsidianakis             field_exists: None,
2230a65e412SManos Pitsidianakis         }
2240a65e412SManos Pitsidianakis     }};
2250a65e412SManos Pitsidianakis }
2260a65e412SManos Pitsidianakis 
2270a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_OF_POINTER_TO_STRUCT")]
2280a65e412SManos Pitsidianakis #[macro_export]
2290a65e412SManos Pitsidianakis macro_rules! vmstate_array_of_pointer_to_struct {
2300a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr, $vmsd:expr, $type:ty) => {{
2310a65e412SManos Pitsidianakis         $crate::bindings::VMStateField {
2320a65e412SManos Pitsidianakis             name: ::core::concat!(::core::stringify!($field_name), 0)
2330a65e412SManos Pitsidianakis                 .as_bytes()
234*9f7d4520SPaolo Bonzini                 .as_ptr() as *const ::std::os::raw::c_char,
2350a65e412SManos Pitsidianakis             version_id: $version_id,
2360a65e412SManos Pitsidianakis             num: $num as _,
2370a65e412SManos Pitsidianakis             vmsd: unsafe { $vmsd },
2380a65e412SManos Pitsidianakis             size: ::core::mem::size_of::<*const $type>(),
2390a65e412SManos Pitsidianakis             flags: VMStateFlags(
2400a65e412SManos Pitsidianakis                 VMStateFlags::VMS_ARRAY.0
2410a65e412SManos Pitsidianakis                     | VMStateFlags::VMS_STRUCT.0
2420a65e412SManos Pitsidianakis                     | VMStateFlags::VMS_ARRAY_OF_POINTER.0,
2430a65e412SManos Pitsidianakis             ),
2440a65e412SManos Pitsidianakis             offset: ::core::mem::offset_of!($struct_name, $field_name),
2450a65e412SManos Pitsidianakis             err_hint: ::core::ptr::null(),
2460a65e412SManos Pitsidianakis             start: 0,
2470a65e412SManos Pitsidianakis             num_offset: 0,
2480a65e412SManos Pitsidianakis             size_offset: 0,
2490a65e412SManos Pitsidianakis             vmsd: ::core::ptr::null(),
2500a65e412SManos Pitsidianakis             struct_version_id: 0,
2510a65e412SManos Pitsidianakis             field_exists: None,
2520a65e412SManos Pitsidianakis         }
2530a65e412SManos Pitsidianakis     }};
2540a65e412SManos Pitsidianakis }
2550a65e412SManos Pitsidianakis 
2560a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_CLOCK_V")]
2570a65e412SManos Pitsidianakis #[macro_export]
2580a65e412SManos Pitsidianakis macro_rules! vmstate_clock_v {
2590a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $version_id:expr) => {{
2600a65e412SManos Pitsidianakis         $crate::vmstate_struct_pointer_v!(
2610a65e412SManos Pitsidianakis             $field_name,
2620a65e412SManos Pitsidianakis             $struct_name,
2630a65e412SManos Pitsidianakis             $version_id,
2640a65e412SManos Pitsidianakis             ::core::ptr::addr_of!($crate::bindings::vmstate_clock),
2650a65e412SManos Pitsidianakis             $crate::bindings::Clock
2660a65e412SManos Pitsidianakis         )
2670a65e412SManos Pitsidianakis     }};
2680a65e412SManos Pitsidianakis }
2690a65e412SManos Pitsidianakis 
2700a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_CLOCK")]
2710a65e412SManos Pitsidianakis #[macro_export]
2720a65e412SManos Pitsidianakis macro_rules! vmstate_clock {
2730a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty) => {{
2740a65e412SManos Pitsidianakis         $crate::vmstate_clock_v!($field_name, $struct_name, 0)
2750a65e412SManos Pitsidianakis     }};
2760a65e412SManos Pitsidianakis }
2770a65e412SManos Pitsidianakis 
2780a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_CLOCK_V")]
2790a65e412SManos Pitsidianakis #[macro_export]
2800a65e412SManos Pitsidianakis macro_rules! vmstate_array_clock_v {
2810a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr) => {{
2820a65e412SManos Pitsidianakis         $crate::vmstate_array_of_pointer_to_struct!(
2830a65e412SManos Pitsidianakis             $field_name,
2840a65e412SManos Pitsidianakis             $struct_name,
2850a65e412SManos Pitsidianakis             $num,
2860a65e412SManos Pitsidianakis             $version_id,
2870a65e412SManos Pitsidianakis             ::core::ptr::addr_of!($crate::bindings::vmstate_clock),
2880a65e412SManos Pitsidianakis             $crate::bindings::Clock
2890a65e412SManos Pitsidianakis         )
2900a65e412SManos Pitsidianakis     }};
2910a65e412SManos Pitsidianakis }
2920a65e412SManos Pitsidianakis 
2930a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_CLOCK")]
2940a65e412SManos Pitsidianakis #[macro_export]
2950a65e412SManos Pitsidianakis macro_rules! vmstate_array_clock {
2960a65e412SManos Pitsidianakis     ($field_name:ident, $struct_name:ty, $num:expr) => {{
2970a65e412SManos Pitsidianakis         $crate::vmstate_array_clock_v!($field_name, $struct_name, $name, 0)
2980a65e412SManos Pitsidianakis     }};
2990a65e412SManos Pitsidianakis }
3000a65e412SManos Pitsidianakis 
3010a65e412SManos Pitsidianakis /// Helper macro to declare a list of
3020a65e412SManos Pitsidianakis /// ([`VMStateField`](`crate::bindings::VMStateField`)) into a static and return
3030a65e412SManos Pitsidianakis /// a pointer to the array of values it created.
3040a65e412SManos Pitsidianakis #[macro_export]
3050a65e412SManos Pitsidianakis macro_rules! vmstate_fields {
3060a65e412SManos Pitsidianakis     ($($field:expr),*$(,)*) => {{
3070a65e412SManos Pitsidianakis         static _FIELDS: &[$crate::bindings::VMStateField] = &[
3080a65e412SManos Pitsidianakis             $($field),*,
3090a65e412SManos Pitsidianakis             $crate::bindings::VMStateField {
3100a65e412SManos Pitsidianakis                 name: ::core::ptr::null(),
3110a65e412SManos Pitsidianakis                 err_hint: ::core::ptr::null(),
3120a65e412SManos Pitsidianakis                 offset: 0,
3130a65e412SManos Pitsidianakis                 size: 0,
3140a65e412SManos Pitsidianakis                 start: 0,
3150a65e412SManos Pitsidianakis                 num: 0,
3160a65e412SManos Pitsidianakis                 num_offset: 0,
3170a65e412SManos Pitsidianakis                 size_offset: 0,
3180a65e412SManos Pitsidianakis                 info: ::core::ptr::null(),
3190a65e412SManos Pitsidianakis                 flags: VMStateFlags::VMS_END,
3200a65e412SManos Pitsidianakis                 vmsd: ::core::ptr::null(),
3210a65e412SManos Pitsidianakis                 version_id: 0,
3220a65e412SManos Pitsidianakis                 struct_version_id: 0,
3230a65e412SManos Pitsidianakis                 field_exists: None,
3240a65e412SManos Pitsidianakis             }
3250a65e412SManos Pitsidianakis         ];
3260a65e412SManos Pitsidianakis         _FIELDS.as_ptr()
3270a65e412SManos Pitsidianakis     }}
3280a65e412SManos Pitsidianakis }
3290a65e412SManos Pitsidianakis 
3300a65e412SManos Pitsidianakis /// A transparent wrapper type for the `subsections` field of
3310a65e412SManos Pitsidianakis /// [`VMStateDescription`](crate::bindings::VMStateDescription).
3320a65e412SManos Pitsidianakis ///
3330a65e412SManos Pitsidianakis /// This is necessary to be able to declare subsection descriptions as statics,
3340a65e412SManos Pitsidianakis /// because the only way to implement `Sync` for a foreign type (and `*const`
3350a65e412SManos Pitsidianakis /// pointers are foreign types in Rust) is to create a wrapper struct and
3360a65e412SManos Pitsidianakis /// `unsafe impl Sync` for it.
3370a65e412SManos Pitsidianakis ///
3380a65e412SManos Pitsidianakis /// This struct is used in the
3390a65e412SManos Pitsidianakis /// [`vm_state_subsections`](crate::vmstate_subsections) macro implementation.
3400a65e412SManos Pitsidianakis #[repr(transparent)]
3410a65e412SManos Pitsidianakis pub struct VMStateSubsectionsWrapper(pub &'static [*const crate::bindings::VMStateDescription]);
3420a65e412SManos Pitsidianakis 
3430a65e412SManos Pitsidianakis unsafe impl Sync for VMStateSubsectionsWrapper {}
3440a65e412SManos Pitsidianakis 
3450a65e412SManos Pitsidianakis /// Helper macro to declare a list of subsections
3460a65e412SManos Pitsidianakis /// ([`VMStateDescription`](`crate::bindings::VMStateDescription`)) into a
3470a65e412SManos Pitsidianakis /// static and return a pointer to the array of pointers it created.
3480a65e412SManos Pitsidianakis #[macro_export]
3490a65e412SManos Pitsidianakis macro_rules! vmstate_subsections {
3500a65e412SManos Pitsidianakis     ($($subsection:expr),*$(,)*) => {{
3510a65e412SManos Pitsidianakis         static _SUBSECTIONS: $crate::vmstate::VMStateSubsectionsWrapper = $crate::vmstate::VMStateSubsectionsWrapper(&[
3520a65e412SManos Pitsidianakis             $({
3530a65e412SManos Pitsidianakis                 static _SUBSECTION: $crate::bindings::VMStateDescription = $subsection;
3540a65e412SManos Pitsidianakis                 ::core::ptr::addr_of!(_SUBSECTION)
3550a65e412SManos Pitsidianakis             }),*,
3560a65e412SManos Pitsidianakis             ::core::ptr::null()
3570a65e412SManos Pitsidianakis         ]);
3580a65e412SManos Pitsidianakis         _SUBSECTIONS.0.as_ptr()
3590a65e412SManos Pitsidianakis     }}
3600a65e412SManos Pitsidianakis }
361