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