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