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 //! 70d43ddaeSPaolo Bonzini //! This module includes three families of macros: 80d43ddaeSPaolo Bonzini //! 90d43ddaeSPaolo Bonzini //! * [`vmstate_unused!`](crate::vmstate_unused) and 100d43ddaeSPaolo Bonzini //! [`vmstate_of!`](crate::vmstate_of), which are used to express the 110d43ddaeSPaolo Bonzini //! migration format for a struct. This is based on the [`VMState`] trait, 120d43ddaeSPaolo Bonzini //! which is defined by all migrateable types. 130d43ddaeSPaolo Bonzini //! 140d43ddaeSPaolo Bonzini //! * helper macros to declare a device model state struct, in particular 150a65e412SManos Pitsidianakis //! [`vmstate_subsections`](crate::vmstate_subsections) and 160d43ddaeSPaolo Bonzini //! [`vmstate_fields`](crate::vmstate_fields). 170d43ddaeSPaolo Bonzini //! 180d43ddaeSPaolo Bonzini //! * direct equivalents to the C macros declared in 190d43ddaeSPaolo Bonzini //! `include/migration/vmstate.h`. These are not type-safe and should not be 200d43ddaeSPaolo Bonzini //! used if the equivalent functionality is available with `vmstate_of!`. 210a65e412SManos Pitsidianakis 2280aa3045SPaolo Bonzini use core::{marker::PhantomData, mem, ptr::NonNull}; 230d43ddaeSPaolo Bonzini 240d43ddaeSPaolo Bonzini pub use crate::bindings::{VMStateDescription, VMStateField}; 25*f2cb78bdSPaolo Bonzini use crate::{ 26*f2cb78bdSPaolo Bonzini bindings::{self, VMStateFlags}, 27*f2cb78bdSPaolo Bonzini zeroable::Zeroable, 28*f2cb78bdSPaolo Bonzini }; 290d43ddaeSPaolo Bonzini 300d43ddaeSPaolo Bonzini /// This macro is used to call a function with a generic argument bound 310d43ddaeSPaolo Bonzini /// to the type of a field. The function must take a 320d43ddaeSPaolo Bonzini /// [`PhantomData`]`<T>` argument; `T` is the type of 330d43ddaeSPaolo Bonzini /// field `$field` in the `$typ` type. 340d43ddaeSPaolo Bonzini /// 350d43ddaeSPaolo Bonzini /// # Examples 360d43ddaeSPaolo Bonzini /// 370d43ddaeSPaolo Bonzini /// ``` 380d43ddaeSPaolo Bonzini /// # use qemu_api::call_func_with_field; 390d43ddaeSPaolo Bonzini /// # use core::marker::PhantomData; 400d43ddaeSPaolo Bonzini /// const fn size_of_field<T>(_: PhantomData<T>) -> usize { 410d43ddaeSPaolo Bonzini /// std::mem::size_of::<T>() 420d43ddaeSPaolo Bonzini /// } 430d43ddaeSPaolo Bonzini /// 440d43ddaeSPaolo Bonzini /// struct Foo { 450d43ddaeSPaolo Bonzini /// x: u16, 460d43ddaeSPaolo Bonzini /// }; 470d43ddaeSPaolo Bonzini /// // calls size_of_field::<u16>() 480d43ddaeSPaolo Bonzini /// assert_eq!(call_func_with_field!(size_of_field, Foo, x), 2); 490d43ddaeSPaolo Bonzini /// ``` 500d43ddaeSPaolo Bonzini #[macro_export] 510d43ddaeSPaolo Bonzini macro_rules! call_func_with_field { 520d43ddaeSPaolo Bonzini // Based on the answer by user steffahn (Frank Steffahn) at 530d43ddaeSPaolo Bonzini // https://users.rust-lang.org/t/inferring-type-of-field/122857 540d43ddaeSPaolo Bonzini // and used under MIT license 550d43ddaeSPaolo Bonzini ($func:expr, $typ:ty, $($field:tt).+) => { 560d43ddaeSPaolo Bonzini $func(loop { 570d43ddaeSPaolo Bonzini #![allow(unreachable_code)] 580d43ddaeSPaolo Bonzini const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> { ::core::marker::PhantomData } 590d43ddaeSPaolo Bonzini // Unreachable code is exempt from checks on uninitialized values. 600d43ddaeSPaolo Bonzini // Use that trick to infer the type of this PhantomData. 610d43ddaeSPaolo Bonzini break ::core::marker::PhantomData; 620d43ddaeSPaolo Bonzini break phantom__(&{ let value__: $typ; value__.$($field).+ }); 630d43ddaeSPaolo Bonzini }) 640d43ddaeSPaolo Bonzini }; 650d43ddaeSPaolo Bonzini } 660d43ddaeSPaolo Bonzini 67*f2cb78bdSPaolo Bonzini /// Workaround for lack of `const_refs_static`: references to global variables 68*f2cb78bdSPaolo Bonzini /// can be included in a `static`, but not in a `const`; unfortunately, this 69*f2cb78bdSPaolo Bonzini /// is exactly what would go in the `VMStateField`'s `info` member. 70*f2cb78bdSPaolo Bonzini /// 71*f2cb78bdSPaolo Bonzini /// This enum contains the contents of the `VMStateField`'s `info` member, 72*f2cb78bdSPaolo Bonzini /// but as an `enum` instead of a pointer. 73*f2cb78bdSPaolo Bonzini #[allow(non_camel_case_types)] 74*f2cb78bdSPaolo Bonzini pub enum VMStateFieldType { 75*f2cb78bdSPaolo Bonzini null, 76*f2cb78bdSPaolo Bonzini vmstate_info_bool, 77*f2cb78bdSPaolo Bonzini vmstate_info_int8, 78*f2cb78bdSPaolo Bonzini vmstate_info_int16, 79*f2cb78bdSPaolo Bonzini vmstate_info_int32, 80*f2cb78bdSPaolo Bonzini vmstate_info_int64, 81*f2cb78bdSPaolo Bonzini vmstate_info_uint8, 82*f2cb78bdSPaolo Bonzini vmstate_info_uint16, 83*f2cb78bdSPaolo Bonzini vmstate_info_uint32, 84*f2cb78bdSPaolo Bonzini vmstate_info_uint64, 85*f2cb78bdSPaolo Bonzini vmstate_info_timer, 86*f2cb78bdSPaolo Bonzini } 87*f2cb78bdSPaolo Bonzini 88*f2cb78bdSPaolo Bonzini /// Workaround for lack of `const_refs_static`. Converts a `VMStateFieldType` 89*f2cb78bdSPaolo Bonzini /// to a `*const VMStateInfo`, for inclusion in a `VMStateField`. 90*f2cb78bdSPaolo Bonzini #[macro_export] 91*f2cb78bdSPaolo Bonzini macro_rules! info_enum_to_ref { 92*f2cb78bdSPaolo Bonzini ($e:expr) => { 93*f2cb78bdSPaolo Bonzini unsafe { 94*f2cb78bdSPaolo Bonzini match $e { 95*f2cb78bdSPaolo Bonzini $crate::vmstate::VMStateFieldType::null => ::core::ptr::null(), 96*f2cb78bdSPaolo Bonzini $crate::vmstate::VMStateFieldType::vmstate_info_bool => { 97*f2cb78bdSPaolo Bonzini ::core::ptr::addr_of!($crate::bindings::vmstate_info_bool) 98*f2cb78bdSPaolo Bonzini } 99*f2cb78bdSPaolo Bonzini $crate::vmstate::VMStateFieldType::vmstate_info_int8 => { 100*f2cb78bdSPaolo Bonzini ::core::ptr::addr_of!($crate::bindings::vmstate_info_int8) 101*f2cb78bdSPaolo Bonzini } 102*f2cb78bdSPaolo Bonzini $crate::vmstate::VMStateFieldType::vmstate_info_int16 => { 103*f2cb78bdSPaolo Bonzini ::core::ptr::addr_of!($crate::bindings::vmstate_info_int16) 104*f2cb78bdSPaolo Bonzini } 105*f2cb78bdSPaolo Bonzini $crate::vmstate::VMStateFieldType::vmstate_info_int32 => { 106*f2cb78bdSPaolo Bonzini ::core::ptr::addr_of!($crate::bindings::vmstate_info_int32) 107*f2cb78bdSPaolo Bonzini } 108*f2cb78bdSPaolo Bonzini $crate::vmstate::VMStateFieldType::vmstate_info_int64 => { 109*f2cb78bdSPaolo Bonzini ::core::ptr::addr_of!($crate::bindings::vmstate_info_int64) 110*f2cb78bdSPaolo Bonzini } 111*f2cb78bdSPaolo Bonzini $crate::vmstate::VMStateFieldType::vmstate_info_uint8 => { 112*f2cb78bdSPaolo Bonzini ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint8) 113*f2cb78bdSPaolo Bonzini } 114*f2cb78bdSPaolo Bonzini $crate::vmstate::VMStateFieldType::vmstate_info_uint16 => { 115*f2cb78bdSPaolo Bonzini ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint16) 116*f2cb78bdSPaolo Bonzini } 117*f2cb78bdSPaolo Bonzini $crate::vmstate::VMStateFieldType::vmstate_info_uint32 => { 118*f2cb78bdSPaolo Bonzini ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32) 119*f2cb78bdSPaolo Bonzini } 120*f2cb78bdSPaolo Bonzini $crate::vmstate::VMStateFieldType::vmstate_info_uint64 => { 121*f2cb78bdSPaolo Bonzini ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint64) 122*f2cb78bdSPaolo Bonzini } 123*f2cb78bdSPaolo Bonzini $crate::vmstate::VMStateFieldType::vmstate_info_timer => { 124*f2cb78bdSPaolo Bonzini ::core::ptr::addr_of!($crate::bindings::vmstate_info_timer) 125*f2cb78bdSPaolo Bonzini } 126*f2cb78bdSPaolo Bonzini } 127*f2cb78bdSPaolo Bonzini } 128*f2cb78bdSPaolo Bonzini }; 129*f2cb78bdSPaolo Bonzini } 130*f2cb78bdSPaolo Bonzini 1310d43ddaeSPaolo Bonzini /// A trait for types that can be included in a device's migration stream. It 1320d43ddaeSPaolo Bonzini /// provides the base contents of a `VMStateField` (minus the name and offset). 1330d43ddaeSPaolo Bonzini /// 1340d43ddaeSPaolo Bonzini /// # Safety 1350d43ddaeSPaolo Bonzini /// 1360d43ddaeSPaolo Bonzini /// The contents of this trait go straight into structs that are parsed by C 1370d43ddaeSPaolo Bonzini /// code and used to introspect into other structs. Be careful. 1380d43ddaeSPaolo Bonzini pub unsafe trait VMState { 139*f2cb78bdSPaolo Bonzini /// The `info` member of a `VMStateField` is a pointer and as such cannot 140*f2cb78bdSPaolo Bonzini /// yet be included in the [`BASE`](VMState::BASE) associated constant; 141*f2cb78bdSPaolo Bonzini /// this is only allowed by Rust 1.83.0 and newer. For now, include the 142*f2cb78bdSPaolo Bonzini /// member as an enum which is stored in a separate constant. 143*f2cb78bdSPaolo Bonzini const SCALAR_TYPE: VMStateFieldType = VMStateFieldType::null; 144*f2cb78bdSPaolo Bonzini 1450d43ddaeSPaolo Bonzini /// The base contents of a `VMStateField` (minus the name and offset) for 1460d43ddaeSPaolo Bonzini /// the type that is implementing the trait. 1470d43ddaeSPaolo Bonzini const BASE: VMStateField; 1485b024b4eSPaolo Bonzini 1495b024b4eSPaolo Bonzini /// A flag that is added to another field's `VMStateField` to specify the 1505b024b4eSPaolo Bonzini /// length's type in a variable-sized array. If this is not a supported 1515b024b4eSPaolo Bonzini /// type for the length (i.e. if it is not `u8`, `u16`, `u32`), using it 1525b024b4eSPaolo Bonzini /// in a call to [`vmstate_of!`](crate::vmstate_of) will cause a 1535b024b4eSPaolo Bonzini /// compile-time error. 1545b024b4eSPaolo Bonzini const VARRAY_FLAG: VMStateFlags = { 1555b024b4eSPaolo Bonzini panic!("invalid type for variable-sized array"); 1565b024b4eSPaolo Bonzini }; 1570d43ddaeSPaolo Bonzini } 1580d43ddaeSPaolo Bonzini 159*f2cb78bdSPaolo Bonzini /// Internal utility function to retrieve a type's `VMStateFieldType`; 160*f2cb78bdSPaolo Bonzini /// used by [`vmstate_of!`](crate::vmstate_of). 161*f2cb78bdSPaolo Bonzini pub const fn vmstate_scalar_type<T: VMState>(_: PhantomData<T>) -> VMStateFieldType { 162*f2cb78bdSPaolo Bonzini T::SCALAR_TYPE 163*f2cb78bdSPaolo Bonzini } 164*f2cb78bdSPaolo Bonzini 1650d43ddaeSPaolo Bonzini /// Internal utility function to retrieve a type's `VMStateField`; 1660d43ddaeSPaolo Bonzini /// used by [`vmstate_of!`](crate::vmstate_of). 1670d43ddaeSPaolo Bonzini pub const fn vmstate_base<T: VMState>(_: PhantomData<T>) -> VMStateField { 1680d43ddaeSPaolo Bonzini T::BASE 1690d43ddaeSPaolo Bonzini } 1700d43ddaeSPaolo Bonzini 1715b024b4eSPaolo Bonzini /// Internal utility function to retrieve a type's `VMStateFlags` when it 1725b024b4eSPaolo Bonzini /// is used as the element count of a `VMSTATE_VARRAY`; used by 1735b024b4eSPaolo Bonzini /// [`vmstate_of!`](crate::vmstate_of). 1745b024b4eSPaolo Bonzini pub const fn vmstate_varray_flag<T: VMState>(_: PhantomData<T>) -> VMStateFlags { 1755b024b4eSPaolo Bonzini T::VARRAY_FLAG 1765b024b4eSPaolo Bonzini } 1775b024b4eSPaolo Bonzini 1780d43ddaeSPaolo Bonzini /// Return the `VMStateField` for a field of a struct. The field must be 1790d43ddaeSPaolo Bonzini /// visible in the current scope. 1800d43ddaeSPaolo Bonzini /// 181*f2cb78bdSPaolo Bonzini /// Only a limited set of types is supported out of the box: 182*f2cb78bdSPaolo Bonzini /// * scalar types (integer and `bool`) 183*f2cb78bdSPaolo Bonzini /// * the C struct `QEMUTimer` 184*f2cb78bdSPaolo Bonzini /// * a transparent wrapper for any of the above (`Cell`, `UnsafeCell`, 185*f2cb78bdSPaolo Bonzini /// [`BqlCell`](crate::cell::BqlCell), [`BqlRefCell`](crate::cell::BqlRefCell) 186*f2cb78bdSPaolo Bonzini /// * a raw pointer to any of the above 187*f2cb78bdSPaolo Bonzini /// * a `NonNull` pointer or a `Box` for any of the above 188*f2cb78bdSPaolo Bonzini /// * an array of any of the above 189*f2cb78bdSPaolo Bonzini /// 1900d43ddaeSPaolo Bonzini /// In order to support other types, the trait `VMState` must be implemented 1910d43ddaeSPaolo Bonzini /// for them. 1920d43ddaeSPaolo Bonzini #[macro_export] 1930d43ddaeSPaolo Bonzini macro_rules! vmstate_of { 1945b024b4eSPaolo Bonzini ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:expr)?])? $(,)?) => { 1950d43ddaeSPaolo Bonzini $crate::bindings::VMStateField { 1960d43ddaeSPaolo Bonzini name: ::core::concat!(::core::stringify!($field_name), "\0") 1970d43ddaeSPaolo Bonzini .as_bytes() 1980d43ddaeSPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 1990d43ddaeSPaolo Bonzini offset: $crate::offset_of!($struct_name, $field_name), 2005b024b4eSPaolo Bonzini $(.num_offset: $crate::offset_of!($struct_name, $num),)? 201*f2cb78bdSPaolo Bonzini // The calls to `call_func_with_field!` are the magic that 202*f2cb78bdSPaolo Bonzini // computes most of the VMStateField from the type of the field. 203*f2cb78bdSPaolo Bonzini info: $crate::info_enum_to_ref!($crate::call_func_with_field!( 204*f2cb78bdSPaolo Bonzini $crate::vmstate::vmstate_scalar_type, 205*f2cb78bdSPaolo Bonzini $struct_name, 206*f2cb78bdSPaolo Bonzini $field_name 207*f2cb78bdSPaolo Bonzini )), 2080d43ddaeSPaolo Bonzini ..$crate::call_func_with_field!( 2090d43ddaeSPaolo Bonzini $crate::vmstate::vmstate_base, 2100d43ddaeSPaolo Bonzini $struct_name, 2110d43ddaeSPaolo Bonzini $field_name 2125b024b4eSPaolo Bonzini )$(.with_varray_flag($crate::call_func_with_field!( 2135b024b4eSPaolo Bonzini $crate::vmstate::vmstate_varray_flag, 2145b024b4eSPaolo Bonzini $struct_name, 2155b024b4eSPaolo Bonzini $num)) 2165b024b4eSPaolo Bonzini $(.with_varray_multiply($factor))?)? 2170d43ddaeSPaolo Bonzini } 2180d43ddaeSPaolo Bonzini }; 2190d43ddaeSPaolo Bonzini } 2200d43ddaeSPaolo Bonzini 22180aa3045SPaolo Bonzini impl VMStateFlags { 22280aa3045SPaolo Bonzini const VMS_VARRAY_FLAGS: VMStateFlags = VMStateFlags( 22380aa3045SPaolo Bonzini VMStateFlags::VMS_VARRAY_INT32.0 22480aa3045SPaolo Bonzini | VMStateFlags::VMS_VARRAY_UINT8.0 22580aa3045SPaolo Bonzini | VMStateFlags::VMS_VARRAY_UINT16.0 22680aa3045SPaolo Bonzini | VMStateFlags::VMS_VARRAY_UINT32.0, 22780aa3045SPaolo Bonzini ); 22880aa3045SPaolo Bonzini } 22980aa3045SPaolo Bonzini 2300d43ddaeSPaolo Bonzini // Add a couple builder-style methods to VMStateField, allowing 2310d43ddaeSPaolo Bonzini // easy derivation of VMStateField constants from other types. 2320d43ddaeSPaolo Bonzini impl VMStateField { 2330d43ddaeSPaolo Bonzini #[must_use] 2340d43ddaeSPaolo Bonzini pub const fn with_version_id(mut self, version_id: i32) -> Self { 2350d43ddaeSPaolo Bonzini assert!(version_id >= 0); 2360d43ddaeSPaolo Bonzini self.version_id = version_id; 2370d43ddaeSPaolo Bonzini self 2380d43ddaeSPaolo Bonzini } 23980aa3045SPaolo Bonzini 24080aa3045SPaolo Bonzini #[must_use] 24180aa3045SPaolo Bonzini pub const fn with_array_flag(mut self, num: usize) -> Self { 24280aa3045SPaolo Bonzini assert!(num <= 0x7FFF_FFFFusize); 24380aa3045SPaolo Bonzini assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) == 0); 24480aa3045SPaolo Bonzini assert!((self.flags.0 & VMStateFlags::VMS_VARRAY_FLAGS.0) == 0); 24580aa3045SPaolo Bonzini if (self.flags.0 & VMStateFlags::VMS_POINTER.0) != 0 { 24680aa3045SPaolo Bonzini self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_POINTER.0); 24780aa3045SPaolo Bonzini self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0); 24880aa3045SPaolo Bonzini } 24980aa3045SPaolo Bonzini self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_SINGLE.0); 25080aa3045SPaolo Bonzini self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY.0); 25180aa3045SPaolo Bonzini self.num = num as i32; 25280aa3045SPaolo Bonzini self 25380aa3045SPaolo Bonzini } 25480aa3045SPaolo Bonzini 25580aa3045SPaolo Bonzini #[must_use] 25680aa3045SPaolo Bonzini pub const fn with_pointer_flag(mut self) -> Self { 25780aa3045SPaolo Bonzini assert!((self.flags.0 & VMStateFlags::VMS_POINTER.0) == 0); 25880aa3045SPaolo Bonzini self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_POINTER.0); 25980aa3045SPaolo Bonzini self 26080aa3045SPaolo Bonzini } 2615b024b4eSPaolo Bonzini 2625b024b4eSPaolo Bonzini #[must_use] 2635b024b4eSPaolo Bonzini pub const fn with_varray_flag<T: VMState>(mut self, flag: VMStateFlags) -> VMStateField { 2645b024b4eSPaolo Bonzini assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) != 0); 2655b024b4eSPaolo Bonzini self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_ARRAY.0); 2665b024b4eSPaolo Bonzini self.flags = VMStateFlags(self.flags.0 | flag.0); 2675b024b4eSPaolo Bonzini self 2685b024b4eSPaolo Bonzini } 2695b024b4eSPaolo Bonzini 2705b024b4eSPaolo Bonzini #[must_use] 2715b024b4eSPaolo Bonzini pub const fn with_varray_multiply(mut self, num: u32) -> VMStateField { 2725b024b4eSPaolo Bonzini assert!(num <= 0x7FFF_FFFFu32); 2735b024b4eSPaolo Bonzini self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0); 2745b024b4eSPaolo Bonzini self.num = num as i32; 2755b024b4eSPaolo Bonzini self 2765b024b4eSPaolo Bonzini } 27780aa3045SPaolo Bonzini } 27880aa3045SPaolo Bonzini 27980aa3045SPaolo Bonzini // Transparent wrappers: just use the internal type 28080aa3045SPaolo Bonzini 28180aa3045SPaolo Bonzini macro_rules! impl_vmstate_transparent { 28280aa3045SPaolo Bonzini ($type:ty where $base:tt: VMState $($where:tt)*) => { 28380aa3045SPaolo Bonzini unsafe impl<$base> VMState for $type where $base: VMState $($where)* { 284*f2cb78bdSPaolo Bonzini const SCALAR_TYPE: VMStateFieldType = <$base as VMState>::SCALAR_TYPE; 28580aa3045SPaolo Bonzini const BASE: VMStateField = VMStateField { 28680aa3045SPaolo Bonzini size: mem::size_of::<$type>(), 28780aa3045SPaolo Bonzini ..<$base as VMState>::BASE 28880aa3045SPaolo Bonzini }; 2895b024b4eSPaolo Bonzini const VARRAY_FLAG: VMStateFlags = <$base as VMState>::VARRAY_FLAG; 29080aa3045SPaolo Bonzini } 29180aa3045SPaolo Bonzini }; 29280aa3045SPaolo Bonzini } 29380aa3045SPaolo Bonzini 29480aa3045SPaolo Bonzini impl_vmstate_transparent!(std::cell::Cell<T> where T: VMState); 29580aa3045SPaolo Bonzini impl_vmstate_transparent!(std::cell::UnsafeCell<T> where T: VMState); 29680aa3045SPaolo Bonzini impl_vmstate_transparent!(crate::cell::BqlCell<T> where T: VMState); 29780aa3045SPaolo Bonzini impl_vmstate_transparent!(crate::cell::BqlRefCell<T> where T: VMState); 29880aa3045SPaolo Bonzini 299*f2cb78bdSPaolo Bonzini // Scalar types using predefined VMStateInfos 300*f2cb78bdSPaolo Bonzini 301*f2cb78bdSPaolo Bonzini macro_rules! impl_vmstate_scalar { 302*f2cb78bdSPaolo Bonzini ($info:ident, $type:ty$(, $varray_flag:ident)?) => { 303*f2cb78bdSPaolo Bonzini unsafe impl VMState for $type { 304*f2cb78bdSPaolo Bonzini const SCALAR_TYPE: VMStateFieldType = VMStateFieldType::$info; 305*f2cb78bdSPaolo Bonzini const BASE: VMStateField = VMStateField { 306*f2cb78bdSPaolo Bonzini size: mem::size_of::<$type>(), 307*f2cb78bdSPaolo Bonzini flags: VMStateFlags::VMS_SINGLE, 308*f2cb78bdSPaolo Bonzini ..Zeroable::ZERO 309*f2cb78bdSPaolo Bonzini }; 310*f2cb78bdSPaolo Bonzini $(const VARRAY_FLAG: VMStateFlags = VMStateFlags::$varray_flag;)? 311*f2cb78bdSPaolo Bonzini } 312*f2cb78bdSPaolo Bonzini }; 313*f2cb78bdSPaolo Bonzini } 314*f2cb78bdSPaolo Bonzini 315*f2cb78bdSPaolo Bonzini impl_vmstate_scalar!(vmstate_info_bool, bool); 316*f2cb78bdSPaolo Bonzini impl_vmstate_scalar!(vmstate_info_int8, i8); 317*f2cb78bdSPaolo Bonzini impl_vmstate_scalar!(vmstate_info_int16, i16); 318*f2cb78bdSPaolo Bonzini impl_vmstate_scalar!(vmstate_info_int32, i32); 319*f2cb78bdSPaolo Bonzini impl_vmstate_scalar!(vmstate_info_int64, i64); 320*f2cb78bdSPaolo Bonzini impl_vmstate_scalar!(vmstate_info_uint8, u8, VMS_VARRAY_UINT8); 321*f2cb78bdSPaolo Bonzini impl_vmstate_scalar!(vmstate_info_uint16, u16, VMS_VARRAY_UINT16); 322*f2cb78bdSPaolo Bonzini impl_vmstate_scalar!(vmstate_info_uint32, u32, VMS_VARRAY_UINT32); 323*f2cb78bdSPaolo Bonzini impl_vmstate_scalar!(vmstate_info_uint64, u64); 324*f2cb78bdSPaolo Bonzini impl_vmstate_scalar!(vmstate_info_timer, bindings::QEMUTimer); 325*f2cb78bdSPaolo Bonzini 32680aa3045SPaolo Bonzini // Pointer types using the underlying type's VMState plus VMS_POINTER 32780aa3045SPaolo Bonzini // Note that references are not supported, though references to cells 32880aa3045SPaolo Bonzini // could be allowed. 32980aa3045SPaolo Bonzini 33080aa3045SPaolo Bonzini macro_rules! impl_vmstate_pointer { 33180aa3045SPaolo Bonzini ($type:ty where $base:tt: VMState $($where:tt)*) => { 33280aa3045SPaolo Bonzini unsafe impl<$base> VMState for $type where $base: VMState $($where)* { 333*f2cb78bdSPaolo Bonzini const SCALAR_TYPE: VMStateFieldType = <T as VMState>::SCALAR_TYPE; 33480aa3045SPaolo Bonzini const BASE: VMStateField = <$base as VMState>::BASE.with_pointer_flag(); 33580aa3045SPaolo Bonzini } 33680aa3045SPaolo Bonzini }; 33780aa3045SPaolo Bonzini } 33880aa3045SPaolo Bonzini 33980aa3045SPaolo Bonzini impl_vmstate_pointer!(*const T where T: VMState); 34080aa3045SPaolo Bonzini impl_vmstate_pointer!(*mut T where T: VMState); 34180aa3045SPaolo Bonzini impl_vmstate_pointer!(NonNull<T> where T: VMState); 34280aa3045SPaolo Bonzini 34380aa3045SPaolo Bonzini // Unlike C pointers, Box is always non-null therefore there is no need 34480aa3045SPaolo Bonzini // to specify VMS_ALLOC. 34580aa3045SPaolo Bonzini impl_vmstate_pointer!(Box<T> where T: VMState); 34680aa3045SPaolo Bonzini 34780aa3045SPaolo Bonzini // Arrays using the underlying type's VMState plus 34880aa3045SPaolo Bonzini // VMS_ARRAY/VMS_ARRAY_OF_POINTER 34980aa3045SPaolo Bonzini 35080aa3045SPaolo Bonzini unsafe impl<T: VMState, const N: usize> VMState for [T; N] { 351*f2cb78bdSPaolo Bonzini const SCALAR_TYPE: VMStateFieldType = <T as VMState>::SCALAR_TYPE; 35280aa3045SPaolo Bonzini const BASE: VMStateField = <T as VMState>::BASE.with_array_flag(N); 3530d43ddaeSPaolo Bonzini } 354716d89f9SPaolo Bonzini 3550a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED_BUFFER")] 3560a65e412SManos Pitsidianakis #[macro_export] 3570a65e412SManos Pitsidianakis macro_rules! vmstate_unused_buffer { 3580a65e412SManos Pitsidianakis ($field_exists_fn:expr, $version_id:expr, $size:expr) => {{ 3590a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 360718e255fSPaolo Bonzini name: c_str!("unused").as_ptr(), 3610a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 3620a65e412SManos Pitsidianakis offset: 0, 3630a65e412SManos Pitsidianakis size: $size, 3640a65e412SManos Pitsidianakis start: 0, 3650a65e412SManos Pitsidianakis num: 0, 3660a65e412SManos Pitsidianakis num_offset: 0, 3670a65e412SManos Pitsidianakis size_offset: 0, 3680a65e412SManos Pitsidianakis info: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate_info_unused_buffer) }, 3690a65e412SManos Pitsidianakis flags: VMStateFlags::VMS_BUFFER, 3700a65e412SManos Pitsidianakis vmsd: ::core::ptr::null(), 3710a65e412SManos Pitsidianakis version_id: $version_id, 3720a65e412SManos Pitsidianakis struct_version_id: 0, 3730a65e412SManos Pitsidianakis field_exists: $field_exists_fn, 3740a65e412SManos Pitsidianakis } 3750a65e412SManos Pitsidianakis }}; 3760a65e412SManos Pitsidianakis } 3770a65e412SManos Pitsidianakis 3780a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED_V")] 3790a65e412SManos Pitsidianakis #[macro_export] 3800a65e412SManos Pitsidianakis macro_rules! vmstate_unused_v { 3810a65e412SManos Pitsidianakis ($version_id:expr, $size:expr) => {{ 3820a65e412SManos Pitsidianakis $crate::vmstate_unused_buffer!(None, $version_id, $size) 3830a65e412SManos Pitsidianakis }}; 3840a65e412SManos Pitsidianakis } 3850a65e412SManos Pitsidianakis 3860a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED")] 3870a65e412SManos Pitsidianakis #[macro_export] 3880a65e412SManos Pitsidianakis macro_rules! vmstate_unused { 3890a65e412SManos Pitsidianakis ($size:expr) => {{ 3900a65e412SManos Pitsidianakis $crate::vmstate_unused_v!(0, $size) 3910a65e412SManos Pitsidianakis }}; 3920a65e412SManos Pitsidianakis } 3930a65e412SManos Pitsidianakis 3940a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_SINGLE_TEST")] 3950a65e412SManos Pitsidianakis #[macro_export] 3960a65e412SManos Pitsidianakis macro_rules! vmstate_single_test { 3970a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $field_exists_fn:expr, $version_id:expr, $info:expr, $size:expr) => {{ 3980a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 3990a65e412SManos Pitsidianakis name: ::core::concat!(::core::stringify!($field_name), 0) 4000a65e412SManos Pitsidianakis .as_bytes() 4019f7d4520SPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 4020a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 403f3518400SJunjie Mao offset: $crate::offset_of!($struct_name, $field_name), 4040a65e412SManos Pitsidianakis size: $size, 4050a65e412SManos Pitsidianakis start: 0, 4060a65e412SManos Pitsidianakis num: 0, 4070a65e412SManos Pitsidianakis num_offset: 0, 4080a65e412SManos Pitsidianakis size_offset: 0, 4090a65e412SManos Pitsidianakis info: unsafe { $info }, 4100a65e412SManos Pitsidianakis flags: VMStateFlags::VMS_SINGLE, 4110a65e412SManos Pitsidianakis vmsd: ::core::ptr::null(), 4120a65e412SManos Pitsidianakis version_id: $version_id, 4130a65e412SManos Pitsidianakis struct_version_id: 0, 4140a65e412SManos Pitsidianakis field_exists: $field_exists_fn, 4150a65e412SManos Pitsidianakis } 4160a65e412SManos Pitsidianakis }}; 4170a65e412SManos Pitsidianakis } 4180a65e412SManos Pitsidianakis 4190a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_SINGLE")] 4200a65e412SManos Pitsidianakis #[macro_export] 4210a65e412SManos Pitsidianakis macro_rules! vmstate_single { 4220a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $version_id:expr, $info:expr, $size:expr) => {{ 4230a65e412SManos Pitsidianakis $crate::vmstate_single_test!($field_name, $struct_name, None, $version_id, $info, $size) 4240a65e412SManos Pitsidianakis }}; 4250a65e412SManos Pitsidianakis } 4260a65e412SManos Pitsidianakis 4270a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_V")] 4280a65e412SManos Pitsidianakis #[macro_export] 4290a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_v { 4300a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $version_id:expr) => {{ 4310a65e412SManos Pitsidianakis $crate::vmstate_single!( 4320a65e412SManos Pitsidianakis $field_name, 4330a65e412SManos Pitsidianakis $struct_name, 4340a65e412SManos Pitsidianakis $version_id, 4350a65e412SManos Pitsidianakis ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32), 4360a65e412SManos Pitsidianakis ::core::mem::size_of::<u32>() 4370a65e412SManos Pitsidianakis ) 4380a65e412SManos Pitsidianakis }}; 4390a65e412SManos Pitsidianakis } 4400a65e412SManos Pitsidianakis 4410a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32")] 4420a65e412SManos Pitsidianakis #[macro_export] 4430a65e412SManos Pitsidianakis macro_rules! vmstate_uint32 { 4440a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty) => {{ 4450a65e412SManos Pitsidianakis $crate::vmstate_uint32_v!($field_name, $struct_name, 0) 4460a65e412SManos Pitsidianakis }}; 4470a65e412SManos Pitsidianakis } 4480a65e412SManos Pitsidianakis 4490a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY")] 4500a65e412SManos Pitsidianakis #[macro_export] 4510a65e412SManos Pitsidianakis macro_rules! vmstate_array { 4520a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $length:expr, $version_id:expr, $info:expr, $size:expr) => {{ 4530a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 4540a65e412SManos Pitsidianakis name: ::core::concat!(::core::stringify!($field_name), 0) 4550a65e412SManos Pitsidianakis .as_bytes() 4569f7d4520SPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 4570a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 458f3518400SJunjie Mao offset: $crate::offset_of!($struct_name, $field_name), 4590a65e412SManos Pitsidianakis size: $size, 4600a65e412SManos Pitsidianakis start: 0, 4610a65e412SManos Pitsidianakis num: $length as _, 4620a65e412SManos Pitsidianakis num_offset: 0, 4630a65e412SManos Pitsidianakis size_offset: 0, 4640a65e412SManos Pitsidianakis info: unsafe { $info }, 4650a65e412SManos Pitsidianakis flags: VMStateFlags::VMS_ARRAY, 4660a65e412SManos Pitsidianakis vmsd: ::core::ptr::null(), 4670a65e412SManos Pitsidianakis version_id: $version_id, 4680a65e412SManos Pitsidianakis struct_version_id: 0, 4690a65e412SManos Pitsidianakis field_exists: None, 4700a65e412SManos Pitsidianakis } 4710a65e412SManos Pitsidianakis }}; 4720a65e412SManos Pitsidianakis } 4730a65e412SManos Pitsidianakis 4740a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_ARRAY_V")] 4750a65e412SManos Pitsidianakis #[macro_export] 4760a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_array_v { 4770a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $length:expr, $version_id:expr) => {{ 4780a65e412SManos Pitsidianakis $crate::vmstate_array!( 4790a65e412SManos Pitsidianakis $field_name, 4800a65e412SManos Pitsidianakis $struct_name, 4810a65e412SManos Pitsidianakis $length, 4820a65e412SManos Pitsidianakis $version_id, 4830a65e412SManos Pitsidianakis ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32), 4840a65e412SManos Pitsidianakis ::core::mem::size_of::<u32>() 4850a65e412SManos Pitsidianakis ) 4860a65e412SManos Pitsidianakis }}; 4870a65e412SManos Pitsidianakis } 4880a65e412SManos Pitsidianakis 4890a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_ARRAY")] 4900a65e412SManos Pitsidianakis #[macro_export] 4910a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_array { 4920a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $length:expr) => {{ 4930a65e412SManos Pitsidianakis $crate::vmstate_uint32_array_v!($field_name, $struct_name, $length, 0) 4940a65e412SManos Pitsidianakis }}; 4950a65e412SManos Pitsidianakis } 4960a65e412SManos Pitsidianakis 4970a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_STRUCT_POINTER_V")] 4980a65e412SManos Pitsidianakis #[macro_export] 4990a65e412SManos Pitsidianakis macro_rules! vmstate_struct_pointer_v { 5000a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $version_id:expr, $vmsd:expr, $type:ty) => {{ 5010a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 5020a65e412SManos Pitsidianakis name: ::core::concat!(::core::stringify!($field_name), 0) 5030a65e412SManos Pitsidianakis .as_bytes() 5049f7d4520SPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 5050a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 506f3518400SJunjie Mao offset: $crate::offset_of!($struct_name, $field_name), 5070a65e412SManos Pitsidianakis size: ::core::mem::size_of::<*const $type>(), 5080a65e412SManos Pitsidianakis start: 0, 5090a65e412SManos Pitsidianakis num: 0, 5100a65e412SManos Pitsidianakis num_offset: 0, 5110a65e412SManos Pitsidianakis size_offset: 0, 5120a65e412SManos Pitsidianakis info: ::core::ptr::null(), 5130a65e412SManos Pitsidianakis flags: VMStateFlags(VMStateFlags::VMS_STRUCT.0 | VMStateFlags::VMS_POINTER.0), 5140a65e412SManos Pitsidianakis vmsd: unsafe { $vmsd }, 5150a65e412SManos Pitsidianakis version_id: $version_id, 5160a65e412SManos Pitsidianakis struct_version_id: 0, 5170a65e412SManos Pitsidianakis field_exists: None, 5180a65e412SManos Pitsidianakis } 5190a65e412SManos Pitsidianakis }}; 5200a65e412SManos Pitsidianakis } 5210a65e412SManos Pitsidianakis 5220a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_OF_POINTER")] 5230a65e412SManos Pitsidianakis #[macro_export] 5240a65e412SManos Pitsidianakis macro_rules! vmstate_array_of_pointer { 5250a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr, $info:expr, $type:ty) => {{ 5260a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 5270a65e412SManos Pitsidianakis name: ::core::concat!(::core::stringify!($field_name), 0) 5280a65e412SManos Pitsidianakis .as_bytes() 5299f7d4520SPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 5300a65e412SManos Pitsidianakis version_id: $version_id, 5310a65e412SManos Pitsidianakis num: $num as _, 5320a65e412SManos Pitsidianakis info: unsafe { $info }, 5330a65e412SManos Pitsidianakis size: ::core::mem::size_of::<*const $type>(), 5340a65e412SManos Pitsidianakis flags: VMStateFlags(VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0), 535f3518400SJunjie Mao offset: $crate::offset_of!($struct_name, $field_name), 5360a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 5370a65e412SManos Pitsidianakis start: 0, 5380a65e412SManos Pitsidianakis num_offset: 0, 5390a65e412SManos Pitsidianakis size_offset: 0, 5400a65e412SManos Pitsidianakis vmsd: ::core::ptr::null(), 5410a65e412SManos Pitsidianakis struct_version_id: 0, 5420a65e412SManos Pitsidianakis field_exists: None, 5430a65e412SManos Pitsidianakis } 5440a65e412SManos Pitsidianakis }}; 5450a65e412SManos Pitsidianakis } 5460a65e412SManos Pitsidianakis 5470a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_OF_POINTER_TO_STRUCT")] 5480a65e412SManos Pitsidianakis #[macro_export] 5490a65e412SManos Pitsidianakis macro_rules! vmstate_array_of_pointer_to_struct { 5500a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr, $vmsd:expr, $type:ty) => {{ 5510a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 5520a65e412SManos Pitsidianakis name: ::core::concat!(::core::stringify!($field_name), 0) 5530a65e412SManos Pitsidianakis .as_bytes() 5549f7d4520SPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 5550a65e412SManos Pitsidianakis version_id: $version_id, 5560a65e412SManos Pitsidianakis num: $num as _, 5570a65e412SManos Pitsidianakis vmsd: unsafe { $vmsd }, 5580a65e412SManos Pitsidianakis size: ::core::mem::size_of::<*const $type>(), 5590a65e412SManos Pitsidianakis flags: VMStateFlags( 5600a65e412SManos Pitsidianakis VMStateFlags::VMS_ARRAY.0 5610a65e412SManos Pitsidianakis | VMStateFlags::VMS_STRUCT.0 5620a65e412SManos Pitsidianakis | VMStateFlags::VMS_ARRAY_OF_POINTER.0, 5630a65e412SManos Pitsidianakis ), 564f3518400SJunjie Mao offset: $crate::offset_of!($struct_name, $field_name), 5650a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 5660a65e412SManos Pitsidianakis start: 0, 5670a65e412SManos Pitsidianakis num_offset: 0, 5680a65e412SManos Pitsidianakis size_offset: 0, 5690a65e412SManos Pitsidianakis vmsd: ::core::ptr::null(), 5700a65e412SManos Pitsidianakis struct_version_id: 0, 5710a65e412SManos Pitsidianakis field_exists: None, 5720a65e412SManos Pitsidianakis } 5730a65e412SManos Pitsidianakis }}; 5740a65e412SManos Pitsidianakis } 5750a65e412SManos Pitsidianakis 5760a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_CLOCK_V")] 5770a65e412SManos Pitsidianakis #[macro_export] 5780a65e412SManos Pitsidianakis macro_rules! vmstate_clock_v { 5790a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $version_id:expr) => {{ 5800a65e412SManos Pitsidianakis $crate::vmstate_struct_pointer_v!( 5810a65e412SManos Pitsidianakis $field_name, 5820a65e412SManos Pitsidianakis $struct_name, 5830a65e412SManos Pitsidianakis $version_id, 5840a65e412SManos Pitsidianakis ::core::ptr::addr_of!($crate::bindings::vmstate_clock), 5850a65e412SManos Pitsidianakis $crate::bindings::Clock 5860a65e412SManos Pitsidianakis ) 5870a65e412SManos Pitsidianakis }}; 5880a65e412SManos Pitsidianakis } 5890a65e412SManos Pitsidianakis 5900a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_CLOCK")] 5910a65e412SManos Pitsidianakis #[macro_export] 5920a65e412SManos Pitsidianakis macro_rules! vmstate_clock { 5930a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty) => {{ 5940a65e412SManos Pitsidianakis $crate::vmstate_clock_v!($field_name, $struct_name, 0) 5950a65e412SManos Pitsidianakis }}; 5960a65e412SManos Pitsidianakis } 5970a65e412SManos Pitsidianakis 5980a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_CLOCK_V")] 5990a65e412SManos Pitsidianakis #[macro_export] 6000a65e412SManos Pitsidianakis macro_rules! vmstate_array_clock_v { 6010a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr) => {{ 6020a65e412SManos Pitsidianakis $crate::vmstate_array_of_pointer_to_struct!( 6030a65e412SManos Pitsidianakis $field_name, 6040a65e412SManos Pitsidianakis $struct_name, 6050a65e412SManos Pitsidianakis $num, 6060a65e412SManos Pitsidianakis $version_id, 6070a65e412SManos Pitsidianakis ::core::ptr::addr_of!($crate::bindings::vmstate_clock), 6080a65e412SManos Pitsidianakis $crate::bindings::Clock 6090a65e412SManos Pitsidianakis ) 6100a65e412SManos Pitsidianakis }}; 6110a65e412SManos Pitsidianakis } 6120a65e412SManos Pitsidianakis 6130a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_CLOCK")] 6140a65e412SManos Pitsidianakis #[macro_export] 6150a65e412SManos Pitsidianakis macro_rules! vmstate_array_clock { 6160a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $num:expr) => {{ 6170a65e412SManos Pitsidianakis $crate::vmstate_array_clock_v!($field_name, $struct_name, $name, 0) 6180a65e412SManos Pitsidianakis }}; 6190a65e412SManos Pitsidianakis } 6200a65e412SManos Pitsidianakis 6210a65e412SManos Pitsidianakis /// Helper macro to declare a list of 6220a65e412SManos Pitsidianakis /// ([`VMStateField`](`crate::bindings::VMStateField`)) into a static and return 6230a65e412SManos Pitsidianakis /// a pointer to the array of values it created. 6240a65e412SManos Pitsidianakis #[macro_export] 6250a65e412SManos Pitsidianakis macro_rules! vmstate_fields { 6260a65e412SManos Pitsidianakis ($($field:expr),*$(,)*) => {{ 6270a65e412SManos Pitsidianakis static _FIELDS: &[$crate::bindings::VMStateField] = &[ 6280a65e412SManos Pitsidianakis $($field),*, 6290a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 6302537f830SPaolo Bonzini flags: $crate::bindings::VMStateFlags::VMS_END, 6312537f830SPaolo Bonzini ..$crate::zeroable::Zeroable::ZERO 6320a65e412SManos Pitsidianakis } 6330a65e412SManos Pitsidianakis ]; 6340a65e412SManos Pitsidianakis _FIELDS.as_ptr() 6350a65e412SManos Pitsidianakis }} 6360a65e412SManos Pitsidianakis } 6370a65e412SManos Pitsidianakis 6380a65e412SManos Pitsidianakis /// A transparent wrapper type for the `subsections` field of 639716d89f9SPaolo Bonzini /// [`VMStateDescription`]. 6400a65e412SManos Pitsidianakis /// 6410a65e412SManos Pitsidianakis /// This is necessary to be able to declare subsection descriptions as statics, 6420a65e412SManos Pitsidianakis /// because the only way to implement `Sync` for a foreign type (and `*const` 6430a65e412SManos Pitsidianakis /// pointers are foreign types in Rust) is to create a wrapper struct and 6440a65e412SManos Pitsidianakis /// `unsafe impl Sync` for it. 6450a65e412SManos Pitsidianakis /// 6460a65e412SManos Pitsidianakis /// This struct is used in the 6470a65e412SManos Pitsidianakis /// [`vm_state_subsections`](crate::vmstate_subsections) macro implementation. 6480a65e412SManos Pitsidianakis #[repr(transparent)] 6490a65e412SManos Pitsidianakis pub struct VMStateSubsectionsWrapper(pub &'static [*const crate::bindings::VMStateDescription]); 6500a65e412SManos Pitsidianakis 6510a65e412SManos Pitsidianakis unsafe impl Sync for VMStateSubsectionsWrapper {} 6520a65e412SManos Pitsidianakis 653716d89f9SPaolo Bonzini /// Helper macro to declare a list of subsections ([`VMStateDescription`]) 654716d89f9SPaolo Bonzini /// into a static and return a pointer to the array of pointers it created. 6550a65e412SManos Pitsidianakis #[macro_export] 6560a65e412SManos Pitsidianakis macro_rules! vmstate_subsections { 6570a65e412SManos Pitsidianakis ($($subsection:expr),*$(,)*) => {{ 6580a65e412SManos Pitsidianakis static _SUBSECTIONS: $crate::vmstate::VMStateSubsectionsWrapper = $crate::vmstate::VMStateSubsectionsWrapper(&[ 6590a65e412SManos Pitsidianakis $({ 6600a65e412SManos Pitsidianakis static _SUBSECTION: $crate::bindings::VMStateDescription = $subsection; 6610a65e412SManos Pitsidianakis ::core::ptr::addr_of!(_SUBSECTION) 6620a65e412SManos Pitsidianakis }),*, 6630a65e412SManos Pitsidianakis ::core::ptr::null() 6640a65e412SManos Pitsidianakis ]); 6650a65e412SManos Pitsidianakis _SUBSECTIONS.0.as_ptr() 6660a65e412SManos Pitsidianakis }} 6670a65e412SManos Pitsidianakis } 668