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*2537f830SPaolo Bonzini use crate::bindings::VMStateFlags; 260d43ddaeSPaolo Bonzini 270d43ddaeSPaolo Bonzini /// This macro is used to call a function with a generic argument bound 280d43ddaeSPaolo Bonzini /// to the type of a field. The function must take a 290d43ddaeSPaolo Bonzini /// [`PhantomData`]`<T>` argument; `T` is the type of 300d43ddaeSPaolo Bonzini /// field `$field` in the `$typ` type. 310d43ddaeSPaolo Bonzini /// 320d43ddaeSPaolo Bonzini /// # Examples 330d43ddaeSPaolo Bonzini /// 340d43ddaeSPaolo Bonzini /// ``` 350d43ddaeSPaolo Bonzini /// # use qemu_api::call_func_with_field; 360d43ddaeSPaolo Bonzini /// # use core::marker::PhantomData; 370d43ddaeSPaolo Bonzini /// const fn size_of_field<T>(_: PhantomData<T>) -> usize { 380d43ddaeSPaolo Bonzini /// std::mem::size_of::<T>() 390d43ddaeSPaolo Bonzini /// } 400d43ddaeSPaolo Bonzini /// 410d43ddaeSPaolo Bonzini /// struct Foo { 420d43ddaeSPaolo Bonzini /// x: u16, 430d43ddaeSPaolo Bonzini /// }; 440d43ddaeSPaolo Bonzini /// // calls size_of_field::<u16>() 450d43ddaeSPaolo Bonzini /// assert_eq!(call_func_with_field!(size_of_field, Foo, x), 2); 460d43ddaeSPaolo Bonzini /// ``` 470d43ddaeSPaolo Bonzini #[macro_export] 480d43ddaeSPaolo Bonzini macro_rules! call_func_with_field { 490d43ddaeSPaolo Bonzini // Based on the answer by user steffahn (Frank Steffahn) at 500d43ddaeSPaolo Bonzini // https://users.rust-lang.org/t/inferring-type-of-field/122857 510d43ddaeSPaolo Bonzini // and used under MIT license 520d43ddaeSPaolo Bonzini ($func:expr, $typ:ty, $($field:tt).+) => { 530d43ddaeSPaolo Bonzini $func(loop { 540d43ddaeSPaolo Bonzini #![allow(unreachable_code)] 550d43ddaeSPaolo Bonzini const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> { ::core::marker::PhantomData } 560d43ddaeSPaolo Bonzini // Unreachable code is exempt from checks on uninitialized values. 570d43ddaeSPaolo Bonzini // Use that trick to infer the type of this PhantomData. 580d43ddaeSPaolo Bonzini break ::core::marker::PhantomData; 590d43ddaeSPaolo Bonzini break phantom__(&{ let value__: $typ; value__.$($field).+ }); 600d43ddaeSPaolo Bonzini }) 610d43ddaeSPaolo Bonzini }; 620d43ddaeSPaolo Bonzini } 630d43ddaeSPaolo Bonzini 640d43ddaeSPaolo Bonzini /// A trait for types that can be included in a device's migration stream. It 650d43ddaeSPaolo Bonzini /// provides the base contents of a `VMStateField` (minus the name and offset). 660d43ddaeSPaolo Bonzini /// 670d43ddaeSPaolo Bonzini /// # Safety 680d43ddaeSPaolo Bonzini /// 690d43ddaeSPaolo Bonzini /// The contents of this trait go straight into structs that are parsed by C 700d43ddaeSPaolo Bonzini /// code and used to introspect into other structs. Be careful. 710d43ddaeSPaolo Bonzini pub unsafe trait VMState { 720d43ddaeSPaolo Bonzini /// The base contents of a `VMStateField` (minus the name and offset) for 730d43ddaeSPaolo Bonzini /// the type that is implementing the trait. 740d43ddaeSPaolo Bonzini const BASE: VMStateField; 755b024b4eSPaolo Bonzini 765b024b4eSPaolo Bonzini /// A flag that is added to another field's `VMStateField` to specify the 775b024b4eSPaolo Bonzini /// length's type in a variable-sized array. If this is not a supported 785b024b4eSPaolo Bonzini /// type for the length (i.e. if it is not `u8`, `u16`, `u32`), using it 795b024b4eSPaolo Bonzini /// in a call to [`vmstate_of!`](crate::vmstate_of) will cause a 805b024b4eSPaolo Bonzini /// compile-time error. 815b024b4eSPaolo Bonzini const VARRAY_FLAG: VMStateFlags = { 825b024b4eSPaolo Bonzini panic!("invalid type for variable-sized array"); 835b024b4eSPaolo Bonzini }; 840d43ddaeSPaolo Bonzini } 850d43ddaeSPaolo Bonzini 860d43ddaeSPaolo Bonzini /// Internal utility function to retrieve a type's `VMStateField`; 870d43ddaeSPaolo Bonzini /// used by [`vmstate_of!`](crate::vmstate_of). 880d43ddaeSPaolo Bonzini pub const fn vmstate_base<T: VMState>(_: PhantomData<T>) -> VMStateField { 890d43ddaeSPaolo Bonzini T::BASE 900d43ddaeSPaolo Bonzini } 910d43ddaeSPaolo Bonzini 925b024b4eSPaolo Bonzini /// Internal utility function to retrieve a type's `VMStateFlags` when it 935b024b4eSPaolo Bonzini /// is used as the element count of a `VMSTATE_VARRAY`; used by 945b024b4eSPaolo Bonzini /// [`vmstate_of!`](crate::vmstate_of). 955b024b4eSPaolo Bonzini pub const fn vmstate_varray_flag<T: VMState>(_: PhantomData<T>) -> VMStateFlags { 965b024b4eSPaolo Bonzini T::VARRAY_FLAG 975b024b4eSPaolo Bonzini } 985b024b4eSPaolo Bonzini 990d43ddaeSPaolo Bonzini /// Return the `VMStateField` for a field of a struct. The field must be 1000d43ddaeSPaolo Bonzini /// visible in the current scope. 1010d43ddaeSPaolo Bonzini /// 1020d43ddaeSPaolo Bonzini /// In order to support other types, the trait `VMState` must be implemented 1030d43ddaeSPaolo Bonzini /// for them. 1040d43ddaeSPaolo Bonzini #[macro_export] 1050d43ddaeSPaolo Bonzini macro_rules! vmstate_of { 1065b024b4eSPaolo Bonzini ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:expr)?])? $(,)?) => { 1070d43ddaeSPaolo Bonzini $crate::bindings::VMStateField { 1080d43ddaeSPaolo Bonzini name: ::core::concat!(::core::stringify!($field_name), "\0") 1090d43ddaeSPaolo Bonzini .as_bytes() 1100d43ddaeSPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 1110d43ddaeSPaolo Bonzini offset: $crate::offset_of!($struct_name, $field_name), 1120d43ddaeSPaolo Bonzini // Compute most of the VMStateField from the type of the field. 1135b024b4eSPaolo Bonzini $(.num_offset: $crate::offset_of!($struct_name, $num),)? 1140d43ddaeSPaolo Bonzini ..$crate::call_func_with_field!( 1150d43ddaeSPaolo Bonzini $crate::vmstate::vmstate_base, 1160d43ddaeSPaolo Bonzini $struct_name, 1170d43ddaeSPaolo Bonzini $field_name 1185b024b4eSPaolo Bonzini )$(.with_varray_flag($crate::call_func_with_field!( 1195b024b4eSPaolo Bonzini $crate::vmstate::vmstate_varray_flag, 1205b024b4eSPaolo Bonzini $struct_name, 1215b024b4eSPaolo Bonzini $num)) 1225b024b4eSPaolo Bonzini $(.with_varray_multiply($factor))?)? 1230d43ddaeSPaolo Bonzini } 1240d43ddaeSPaolo Bonzini }; 1250d43ddaeSPaolo Bonzini } 1260d43ddaeSPaolo Bonzini 12780aa3045SPaolo Bonzini impl VMStateFlags { 12880aa3045SPaolo Bonzini const VMS_VARRAY_FLAGS: VMStateFlags = VMStateFlags( 12980aa3045SPaolo Bonzini VMStateFlags::VMS_VARRAY_INT32.0 13080aa3045SPaolo Bonzini | VMStateFlags::VMS_VARRAY_UINT8.0 13180aa3045SPaolo Bonzini | VMStateFlags::VMS_VARRAY_UINT16.0 13280aa3045SPaolo Bonzini | VMStateFlags::VMS_VARRAY_UINT32.0, 13380aa3045SPaolo Bonzini ); 13480aa3045SPaolo Bonzini } 13580aa3045SPaolo Bonzini 1360d43ddaeSPaolo Bonzini // Add a couple builder-style methods to VMStateField, allowing 1370d43ddaeSPaolo Bonzini // easy derivation of VMStateField constants from other types. 1380d43ddaeSPaolo Bonzini impl VMStateField { 1390d43ddaeSPaolo Bonzini #[must_use] 1400d43ddaeSPaolo Bonzini pub const fn with_version_id(mut self, version_id: i32) -> Self { 1410d43ddaeSPaolo Bonzini assert!(version_id >= 0); 1420d43ddaeSPaolo Bonzini self.version_id = version_id; 1430d43ddaeSPaolo Bonzini self 1440d43ddaeSPaolo Bonzini } 14580aa3045SPaolo Bonzini 14680aa3045SPaolo Bonzini #[must_use] 14780aa3045SPaolo Bonzini pub const fn with_array_flag(mut self, num: usize) -> Self { 14880aa3045SPaolo Bonzini assert!(num <= 0x7FFF_FFFFusize); 14980aa3045SPaolo Bonzini assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) == 0); 15080aa3045SPaolo Bonzini assert!((self.flags.0 & VMStateFlags::VMS_VARRAY_FLAGS.0) == 0); 15180aa3045SPaolo Bonzini if (self.flags.0 & VMStateFlags::VMS_POINTER.0) != 0 { 15280aa3045SPaolo Bonzini self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_POINTER.0); 15380aa3045SPaolo Bonzini self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0); 15480aa3045SPaolo Bonzini } 15580aa3045SPaolo Bonzini self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_SINGLE.0); 15680aa3045SPaolo Bonzini self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY.0); 15780aa3045SPaolo Bonzini self.num = num as i32; 15880aa3045SPaolo Bonzini self 15980aa3045SPaolo Bonzini } 16080aa3045SPaolo Bonzini 16180aa3045SPaolo Bonzini #[must_use] 16280aa3045SPaolo Bonzini pub const fn with_pointer_flag(mut self) -> Self { 16380aa3045SPaolo Bonzini assert!((self.flags.0 & VMStateFlags::VMS_POINTER.0) == 0); 16480aa3045SPaolo Bonzini self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_POINTER.0); 16580aa3045SPaolo Bonzini self 16680aa3045SPaolo Bonzini } 1675b024b4eSPaolo Bonzini 1685b024b4eSPaolo Bonzini #[must_use] 1695b024b4eSPaolo Bonzini pub const fn with_varray_flag<T: VMState>(mut self, flag: VMStateFlags) -> VMStateField { 1705b024b4eSPaolo Bonzini assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) != 0); 1715b024b4eSPaolo Bonzini self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_ARRAY.0); 1725b024b4eSPaolo Bonzini self.flags = VMStateFlags(self.flags.0 | flag.0); 1735b024b4eSPaolo Bonzini self 1745b024b4eSPaolo Bonzini } 1755b024b4eSPaolo Bonzini 1765b024b4eSPaolo Bonzini #[must_use] 1775b024b4eSPaolo Bonzini pub const fn with_varray_multiply(mut self, num: u32) -> VMStateField { 1785b024b4eSPaolo Bonzini assert!(num <= 0x7FFF_FFFFu32); 1795b024b4eSPaolo Bonzini self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0); 1805b024b4eSPaolo Bonzini self.num = num as i32; 1815b024b4eSPaolo Bonzini self 1825b024b4eSPaolo Bonzini } 18380aa3045SPaolo Bonzini } 18480aa3045SPaolo Bonzini 18580aa3045SPaolo Bonzini // Transparent wrappers: just use the internal type 18680aa3045SPaolo Bonzini 18780aa3045SPaolo Bonzini macro_rules! impl_vmstate_transparent { 18880aa3045SPaolo Bonzini ($type:ty where $base:tt: VMState $($where:tt)*) => { 18980aa3045SPaolo Bonzini unsafe impl<$base> VMState for $type where $base: VMState $($where)* { 19080aa3045SPaolo Bonzini const BASE: VMStateField = VMStateField { 19180aa3045SPaolo Bonzini size: mem::size_of::<$type>(), 19280aa3045SPaolo Bonzini ..<$base as VMState>::BASE 19380aa3045SPaolo Bonzini }; 1945b024b4eSPaolo Bonzini const VARRAY_FLAG: VMStateFlags = <$base as VMState>::VARRAY_FLAG; 19580aa3045SPaolo Bonzini } 19680aa3045SPaolo Bonzini }; 19780aa3045SPaolo Bonzini } 19880aa3045SPaolo Bonzini 19980aa3045SPaolo Bonzini impl_vmstate_transparent!(std::cell::Cell<T> where T: VMState); 20080aa3045SPaolo Bonzini impl_vmstate_transparent!(std::cell::UnsafeCell<T> where T: VMState); 20180aa3045SPaolo Bonzini impl_vmstate_transparent!(crate::cell::BqlCell<T> where T: VMState); 20280aa3045SPaolo Bonzini impl_vmstate_transparent!(crate::cell::BqlRefCell<T> where T: VMState); 20380aa3045SPaolo Bonzini 20480aa3045SPaolo Bonzini // Pointer types using the underlying type's VMState plus VMS_POINTER 20580aa3045SPaolo Bonzini // Note that references are not supported, though references to cells 20680aa3045SPaolo Bonzini // could be allowed. 20780aa3045SPaolo Bonzini 20880aa3045SPaolo Bonzini macro_rules! impl_vmstate_pointer { 20980aa3045SPaolo Bonzini ($type:ty where $base:tt: VMState $($where:tt)*) => { 21080aa3045SPaolo Bonzini unsafe impl<$base> VMState for $type where $base: VMState $($where)* { 21180aa3045SPaolo Bonzini const BASE: VMStateField = <$base as VMState>::BASE.with_pointer_flag(); 21280aa3045SPaolo Bonzini } 21380aa3045SPaolo Bonzini }; 21480aa3045SPaolo Bonzini } 21580aa3045SPaolo Bonzini 21680aa3045SPaolo Bonzini impl_vmstate_pointer!(*const T where T: VMState); 21780aa3045SPaolo Bonzini impl_vmstate_pointer!(*mut T where T: VMState); 21880aa3045SPaolo Bonzini impl_vmstate_pointer!(NonNull<T> where T: VMState); 21980aa3045SPaolo Bonzini 22080aa3045SPaolo Bonzini // Unlike C pointers, Box is always non-null therefore there is no need 22180aa3045SPaolo Bonzini // to specify VMS_ALLOC. 22280aa3045SPaolo Bonzini impl_vmstate_pointer!(Box<T> where T: VMState); 22380aa3045SPaolo Bonzini 22480aa3045SPaolo Bonzini // Arrays using the underlying type's VMState plus 22580aa3045SPaolo Bonzini // VMS_ARRAY/VMS_ARRAY_OF_POINTER 22680aa3045SPaolo Bonzini 22780aa3045SPaolo Bonzini unsafe impl<T: VMState, const N: usize> VMState for [T; N] { 22880aa3045SPaolo Bonzini const BASE: VMStateField = <T as VMState>::BASE.with_array_flag(N); 2290d43ddaeSPaolo Bonzini } 230716d89f9SPaolo Bonzini 2310a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED_BUFFER")] 2320a65e412SManos Pitsidianakis #[macro_export] 2330a65e412SManos Pitsidianakis macro_rules! vmstate_unused_buffer { 2340a65e412SManos Pitsidianakis ($field_exists_fn:expr, $version_id:expr, $size:expr) => {{ 2350a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 236718e255fSPaolo Bonzini name: c_str!("unused").as_ptr(), 2370a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 2380a65e412SManos Pitsidianakis offset: 0, 2390a65e412SManos Pitsidianakis size: $size, 2400a65e412SManos Pitsidianakis start: 0, 2410a65e412SManos Pitsidianakis num: 0, 2420a65e412SManos Pitsidianakis num_offset: 0, 2430a65e412SManos Pitsidianakis size_offset: 0, 2440a65e412SManos Pitsidianakis info: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate_info_unused_buffer) }, 2450a65e412SManos Pitsidianakis flags: VMStateFlags::VMS_BUFFER, 2460a65e412SManos Pitsidianakis vmsd: ::core::ptr::null(), 2470a65e412SManos Pitsidianakis version_id: $version_id, 2480a65e412SManos Pitsidianakis struct_version_id: 0, 2490a65e412SManos Pitsidianakis field_exists: $field_exists_fn, 2500a65e412SManos Pitsidianakis } 2510a65e412SManos Pitsidianakis }}; 2520a65e412SManos Pitsidianakis } 2530a65e412SManos Pitsidianakis 2540a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED_V")] 2550a65e412SManos Pitsidianakis #[macro_export] 2560a65e412SManos Pitsidianakis macro_rules! vmstate_unused_v { 2570a65e412SManos Pitsidianakis ($version_id:expr, $size:expr) => {{ 2580a65e412SManos Pitsidianakis $crate::vmstate_unused_buffer!(None, $version_id, $size) 2590a65e412SManos Pitsidianakis }}; 2600a65e412SManos Pitsidianakis } 2610a65e412SManos Pitsidianakis 2620a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UNUSED")] 2630a65e412SManos Pitsidianakis #[macro_export] 2640a65e412SManos Pitsidianakis macro_rules! vmstate_unused { 2650a65e412SManos Pitsidianakis ($size:expr) => {{ 2660a65e412SManos Pitsidianakis $crate::vmstate_unused_v!(0, $size) 2670a65e412SManos Pitsidianakis }}; 2680a65e412SManos Pitsidianakis } 2690a65e412SManos Pitsidianakis 2700a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_SINGLE_TEST")] 2710a65e412SManos Pitsidianakis #[macro_export] 2720a65e412SManos Pitsidianakis macro_rules! vmstate_single_test { 2730a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $field_exists_fn:expr, $version_id:expr, $info:expr, $size:expr) => {{ 2740a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 2750a65e412SManos Pitsidianakis name: ::core::concat!(::core::stringify!($field_name), 0) 2760a65e412SManos Pitsidianakis .as_bytes() 2779f7d4520SPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 2780a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 279f3518400SJunjie Mao offset: $crate::offset_of!($struct_name, $field_name), 2800a65e412SManos Pitsidianakis size: $size, 2810a65e412SManos Pitsidianakis start: 0, 2820a65e412SManos Pitsidianakis num: 0, 2830a65e412SManos Pitsidianakis num_offset: 0, 2840a65e412SManos Pitsidianakis size_offset: 0, 2850a65e412SManos Pitsidianakis info: unsafe { $info }, 2860a65e412SManos Pitsidianakis flags: VMStateFlags::VMS_SINGLE, 2870a65e412SManos Pitsidianakis vmsd: ::core::ptr::null(), 2880a65e412SManos Pitsidianakis version_id: $version_id, 2890a65e412SManos Pitsidianakis struct_version_id: 0, 2900a65e412SManos Pitsidianakis field_exists: $field_exists_fn, 2910a65e412SManos Pitsidianakis } 2920a65e412SManos Pitsidianakis }}; 2930a65e412SManos Pitsidianakis } 2940a65e412SManos Pitsidianakis 2950a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_SINGLE")] 2960a65e412SManos Pitsidianakis #[macro_export] 2970a65e412SManos Pitsidianakis macro_rules! vmstate_single { 2980a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $version_id:expr, $info:expr, $size:expr) => {{ 2990a65e412SManos Pitsidianakis $crate::vmstate_single_test!($field_name, $struct_name, None, $version_id, $info, $size) 3000a65e412SManos Pitsidianakis }}; 3010a65e412SManos Pitsidianakis } 3020a65e412SManos Pitsidianakis 3030a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_V")] 3040a65e412SManos Pitsidianakis #[macro_export] 3050a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_v { 3060a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $version_id:expr) => {{ 3070a65e412SManos Pitsidianakis $crate::vmstate_single!( 3080a65e412SManos Pitsidianakis $field_name, 3090a65e412SManos Pitsidianakis $struct_name, 3100a65e412SManos Pitsidianakis $version_id, 3110a65e412SManos Pitsidianakis ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32), 3120a65e412SManos Pitsidianakis ::core::mem::size_of::<u32>() 3130a65e412SManos Pitsidianakis ) 3140a65e412SManos Pitsidianakis }}; 3150a65e412SManos Pitsidianakis } 3160a65e412SManos Pitsidianakis 3170a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32")] 3180a65e412SManos Pitsidianakis #[macro_export] 3190a65e412SManos Pitsidianakis macro_rules! vmstate_uint32 { 3200a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty) => {{ 3210a65e412SManos Pitsidianakis $crate::vmstate_uint32_v!($field_name, $struct_name, 0) 3220a65e412SManos Pitsidianakis }}; 3230a65e412SManos Pitsidianakis } 3240a65e412SManos Pitsidianakis 3250a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY")] 3260a65e412SManos Pitsidianakis #[macro_export] 3270a65e412SManos Pitsidianakis macro_rules! vmstate_array { 3280a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $length:expr, $version_id:expr, $info:expr, $size:expr) => {{ 3290a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 3300a65e412SManos Pitsidianakis name: ::core::concat!(::core::stringify!($field_name), 0) 3310a65e412SManos Pitsidianakis .as_bytes() 3329f7d4520SPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 3330a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 334f3518400SJunjie Mao offset: $crate::offset_of!($struct_name, $field_name), 3350a65e412SManos Pitsidianakis size: $size, 3360a65e412SManos Pitsidianakis start: 0, 3370a65e412SManos Pitsidianakis num: $length as _, 3380a65e412SManos Pitsidianakis num_offset: 0, 3390a65e412SManos Pitsidianakis size_offset: 0, 3400a65e412SManos Pitsidianakis info: unsafe { $info }, 3410a65e412SManos Pitsidianakis flags: VMStateFlags::VMS_ARRAY, 3420a65e412SManos Pitsidianakis vmsd: ::core::ptr::null(), 3430a65e412SManos Pitsidianakis version_id: $version_id, 3440a65e412SManos Pitsidianakis struct_version_id: 0, 3450a65e412SManos Pitsidianakis field_exists: None, 3460a65e412SManos Pitsidianakis } 3470a65e412SManos Pitsidianakis }}; 3480a65e412SManos Pitsidianakis } 3490a65e412SManos Pitsidianakis 3500a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_ARRAY_V")] 3510a65e412SManos Pitsidianakis #[macro_export] 3520a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_array_v { 3530a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $length:expr, $version_id:expr) => {{ 3540a65e412SManos Pitsidianakis $crate::vmstate_array!( 3550a65e412SManos Pitsidianakis $field_name, 3560a65e412SManos Pitsidianakis $struct_name, 3570a65e412SManos Pitsidianakis $length, 3580a65e412SManos Pitsidianakis $version_id, 3590a65e412SManos Pitsidianakis ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32), 3600a65e412SManos Pitsidianakis ::core::mem::size_of::<u32>() 3610a65e412SManos Pitsidianakis ) 3620a65e412SManos Pitsidianakis }}; 3630a65e412SManos Pitsidianakis } 3640a65e412SManos Pitsidianakis 3650a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_UINT32_ARRAY")] 3660a65e412SManos Pitsidianakis #[macro_export] 3670a65e412SManos Pitsidianakis macro_rules! vmstate_uint32_array { 3680a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $length:expr) => {{ 3690a65e412SManos Pitsidianakis $crate::vmstate_uint32_array_v!($field_name, $struct_name, $length, 0) 3700a65e412SManos Pitsidianakis }}; 3710a65e412SManos Pitsidianakis } 3720a65e412SManos Pitsidianakis 3730a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_STRUCT_POINTER_V")] 3740a65e412SManos Pitsidianakis #[macro_export] 3750a65e412SManos Pitsidianakis macro_rules! vmstate_struct_pointer_v { 3760a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $version_id:expr, $vmsd:expr, $type:ty) => {{ 3770a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 3780a65e412SManos Pitsidianakis name: ::core::concat!(::core::stringify!($field_name), 0) 3790a65e412SManos Pitsidianakis .as_bytes() 3809f7d4520SPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 3810a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 382f3518400SJunjie Mao offset: $crate::offset_of!($struct_name, $field_name), 3830a65e412SManos Pitsidianakis size: ::core::mem::size_of::<*const $type>(), 3840a65e412SManos Pitsidianakis start: 0, 3850a65e412SManos Pitsidianakis num: 0, 3860a65e412SManos Pitsidianakis num_offset: 0, 3870a65e412SManos Pitsidianakis size_offset: 0, 3880a65e412SManos Pitsidianakis info: ::core::ptr::null(), 3890a65e412SManos Pitsidianakis flags: VMStateFlags(VMStateFlags::VMS_STRUCT.0 | VMStateFlags::VMS_POINTER.0), 3900a65e412SManos Pitsidianakis vmsd: unsafe { $vmsd }, 3910a65e412SManos Pitsidianakis version_id: $version_id, 3920a65e412SManos Pitsidianakis struct_version_id: 0, 3930a65e412SManos Pitsidianakis field_exists: None, 3940a65e412SManos Pitsidianakis } 3950a65e412SManos Pitsidianakis }}; 3960a65e412SManos Pitsidianakis } 3970a65e412SManos Pitsidianakis 3980a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_OF_POINTER")] 3990a65e412SManos Pitsidianakis #[macro_export] 4000a65e412SManos Pitsidianakis macro_rules! vmstate_array_of_pointer { 4010a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr, $info:expr, $type:ty) => {{ 4020a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 4030a65e412SManos Pitsidianakis name: ::core::concat!(::core::stringify!($field_name), 0) 4040a65e412SManos Pitsidianakis .as_bytes() 4059f7d4520SPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 4060a65e412SManos Pitsidianakis version_id: $version_id, 4070a65e412SManos Pitsidianakis num: $num as _, 4080a65e412SManos Pitsidianakis info: unsafe { $info }, 4090a65e412SManos Pitsidianakis size: ::core::mem::size_of::<*const $type>(), 4100a65e412SManos Pitsidianakis flags: VMStateFlags(VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0), 411f3518400SJunjie Mao offset: $crate::offset_of!($struct_name, $field_name), 4120a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 4130a65e412SManos Pitsidianakis start: 0, 4140a65e412SManos Pitsidianakis num_offset: 0, 4150a65e412SManos Pitsidianakis size_offset: 0, 4160a65e412SManos Pitsidianakis vmsd: ::core::ptr::null(), 4170a65e412SManos Pitsidianakis struct_version_id: 0, 4180a65e412SManos Pitsidianakis field_exists: None, 4190a65e412SManos Pitsidianakis } 4200a65e412SManos Pitsidianakis }}; 4210a65e412SManos Pitsidianakis } 4220a65e412SManos Pitsidianakis 4230a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_OF_POINTER_TO_STRUCT")] 4240a65e412SManos Pitsidianakis #[macro_export] 4250a65e412SManos Pitsidianakis macro_rules! vmstate_array_of_pointer_to_struct { 4260a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr, $vmsd:expr, $type:ty) => {{ 4270a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 4280a65e412SManos Pitsidianakis name: ::core::concat!(::core::stringify!($field_name), 0) 4290a65e412SManos Pitsidianakis .as_bytes() 4309f7d4520SPaolo Bonzini .as_ptr() as *const ::std::os::raw::c_char, 4310a65e412SManos Pitsidianakis version_id: $version_id, 4320a65e412SManos Pitsidianakis num: $num as _, 4330a65e412SManos Pitsidianakis vmsd: unsafe { $vmsd }, 4340a65e412SManos Pitsidianakis size: ::core::mem::size_of::<*const $type>(), 4350a65e412SManos Pitsidianakis flags: VMStateFlags( 4360a65e412SManos Pitsidianakis VMStateFlags::VMS_ARRAY.0 4370a65e412SManos Pitsidianakis | VMStateFlags::VMS_STRUCT.0 4380a65e412SManos Pitsidianakis | VMStateFlags::VMS_ARRAY_OF_POINTER.0, 4390a65e412SManos Pitsidianakis ), 440f3518400SJunjie Mao offset: $crate::offset_of!($struct_name, $field_name), 4410a65e412SManos Pitsidianakis err_hint: ::core::ptr::null(), 4420a65e412SManos Pitsidianakis start: 0, 4430a65e412SManos Pitsidianakis num_offset: 0, 4440a65e412SManos Pitsidianakis size_offset: 0, 4450a65e412SManos Pitsidianakis vmsd: ::core::ptr::null(), 4460a65e412SManos Pitsidianakis struct_version_id: 0, 4470a65e412SManos Pitsidianakis field_exists: None, 4480a65e412SManos Pitsidianakis } 4490a65e412SManos Pitsidianakis }}; 4500a65e412SManos Pitsidianakis } 4510a65e412SManos Pitsidianakis 4520a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_CLOCK_V")] 4530a65e412SManos Pitsidianakis #[macro_export] 4540a65e412SManos Pitsidianakis macro_rules! vmstate_clock_v { 4550a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $version_id:expr) => {{ 4560a65e412SManos Pitsidianakis $crate::vmstate_struct_pointer_v!( 4570a65e412SManos Pitsidianakis $field_name, 4580a65e412SManos Pitsidianakis $struct_name, 4590a65e412SManos Pitsidianakis $version_id, 4600a65e412SManos Pitsidianakis ::core::ptr::addr_of!($crate::bindings::vmstate_clock), 4610a65e412SManos Pitsidianakis $crate::bindings::Clock 4620a65e412SManos Pitsidianakis ) 4630a65e412SManos Pitsidianakis }}; 4640a65e412SManos Pitsidianakis } 4650a65e412SManos Pitsidianakis 4660a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_CLOCK")] 4670a65e412SManos Pitsidianakis #[macro_export] 4680a65e412SManos Pitsidianakis macro_rules! vmstate_clock { 4690a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty) => {{ 4700a65e412SManos Pitsidianakis $crate::vmstate_clock_v!($field_name, $struct_name, 0) 4710a65e412SManos Pitsidianakis }}; 4720a65e412SManos Pitsidianakis } 4730a65e412SManos Pitsidianakis 4740a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_CLOCK_V")] 4750a65e412SManos Pitsidianakis #[macro_export] 4760a65e412SManos Pitsidianakis macro_rules! vmstate_array_clock_v { 4770a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $num:expr, $version_id:expr) => {{ 4780a65e412SManos Pitsidianakis $crate::vmstate_array_of_pointer_to_struct!( 4790a65e412SManos Pitsidianakis $field_name, 4800a65e412SManos Pitsidianakis $struct_name, 4810a65e412SManos Pitsidianakis $num, 4820a65e412SManos Pitsidianakis $version_id, 4830a65e412SManos Pitsidianakis ::core::ptr::addr_of!($crate::bindings::vmstate_clock), 4840a65e412SManos Pitsidianakis $crate::bindings::Clock 4850a65e412SManos Pitsidianakis ) 4860a65e412SManos Pitsidianakis }}; 4870a65e412SManos Pitsidianakis } 4880a65e412SManos Pitsidianakis 4890a65e412SManos Pitsidianakis #[doc(alias = "VMSTATE_ARRAY_CLOCK")] 4900a65e412SManos Pitsidianakis #[macro_export] 4910a65e412SManos Pitsidianakis macro_rules! vmstate_array_clock { 4920a65e412SManos Pitsidianakis ($field_name:ident, $struct_name:ty, $num:expr) => {{ 4930a65e412SManos Pitsidianakis $crate::vmstate_array_clock_v!($field_name, $struct_name, $name, 0) 4940a65e412SManos Pitsidianakis }}; 4950a65e412SManos Pitsidianakis } 4960a65e412SManos Pitsidianakis 4970a65e412SManos Pitsidianakis /// Helper macro to declare a list of 4980a65e412SManos Pitsidianakis /// ([`VMStateField`](`crate::bindings::VMStateField`)) into a static and return 4990a65e412SManos Pitsidianakis /// a pointer to the array of values it created. 5000a65e412SManos Pitsidianakis #[macro_export] 5010a65e412SManos Pitsidianakis macro_rules! vmstate_fields { 5020a65e412SManos Pitsidianakis ($($field:expr),*$(,)*) => {{ 5030a65e412SManos Pitsidianakis static _FIELDS: &[$crate::bindings::VMStateField] = &[ 5040a65e412SManos Pitsidianakis $($field),*, 5050a65e412SManos Pitsidianakis $crate::bindings::VMStateField { 506*2537f830SPaolo Bonzini flags: $crate::bindings::VMStateFlags::VMS_END, 507*2537f830SPaolo Bonzini ..$crate::zeroable::Zeroable::ZERO 5080a65e412SManos Pitsidianakis } 5090a65e412SManos Pitsidianakis ]; 5100a65e412SManos Pitsidianakis _FIELDS.as_ptr() 5110a65e412SManos Pitsidianakis }} 5120a65e412SManos Pitsidianakis } 5130a65e412SManos Pitsidianakis 5140a65e412SManos Pitsidianakis /// A transparent wrapper type for the `subsections` field of 515716d89f9SPaolo Bonzini /// [`VMStateDescription`]. 5160a65e412SManos Pitsidianakis /// 5170a65e412SManos Pitsidianakis /// This is necessary to be able to declare subsection descriptions as statics, 5180a65e412SManos Pitsidianakis /// because the only way to implement `Sync` for a foreign type (and `*const` 5190a65e412SManos Pitsidianakis /// pointers are foreign types in Rust) is to create a wrapper struct and 5200a65e412SManos Pitsidianakis /// `unsafe impl Sync` for it. 5210a65e412SManos Pitsidianakis /// 5220a65e412SManos Pitsidianakis /// This struct is used in the 5230a65e412SManos Pitsidianakis /// [`vm_state_subsections`](crate::vmstate_subsections) macro implementation. 5240a65e412SManos Pitsidianakis #[repr(transparent)] 5250a65e412SManos Pitsidianakis pub struct VMStateSubsectionsWrapper(pub &'static [*const crate::bindings::VMStateDescription]); 5260a65e412SManos Pitsidianakis 5270a65e412SManos Pitsidianakis unsafe impl Sync for VMStateSubsectionsWrapper {} 5280a65e412SManos Pitsidianakis 529716d89f9SPaolo Bonzini /// Helper macro to declare a list of subsections ([`VMStateDescription`]) 530716d89f9SPaolo Bonzini /// into a static and return a pointer to the array of pointers it created. 5310a65e412SManos Pitsidianakis #[macro_export] 5320a65e412SManos Pitsidianakis macro_rules! vmstate_subsections { 5330a65e412SManos Pitsidianakis ($($subsection:expr),*$(,)*) => {{ 5340a65e412SManos Pitsidianakis static _SUBSECTIONS: $crate::vmstate::VMStateSubsectionsWrapper = $crate::vmstate::VMStateSubsectionsWrapper(&[ 5350a65e412SManos Pitsidianakis $({ 5360a65e412SManos Pitsidianakis static _SUBSECTION: $crate::bindings::VMStateDescription = $subsection; 5370a65e412SManos Pitsidianakis ::core::ptr::addr_of!(_SUBSECTION) 5380a65e412SManos Pitsidianakis }),*, 5390a65e412SManos Pitsidianakis ::core::ptr::null() 5400a65e412SManos Pitsidianakis ]); 5410a65e412SManos Pitsidianakis _SUBSECTIONS.0.as_ptr() 5420a65e412SManos Pitsidianakis }} 5430a65e412SManos Pitsidianakis } 544