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