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 //! This module includes four families of macros: 8 //! 9 //! * [`vmstate_unused!`](crate::vmstate_unused) and 10 //! [`vmstate_of!`](crate::vmstate_of), which are used to express the 11 //! migration format for a struct. This is based on the [`VMState`] trait, 12 //! which is defined by all migratable types. 13 //! 14 //! * [`impl_vmstate_forward`](crate::impl_vmstate_forward), 15 //! [`impl_vmstate_bitsized`](crate::impl_vmstate_bitsized), and 16 //! [`impl_vmstate_struct`](crate::impl_vmstate_struct), which help with the 17 //! definition of the [`VMState`] trait (respectively for transparent structs, 18 //! nested structs and `bilge`-defined types) 19 //! 20 //! * helper macros to declare a device model state struct, in particular 21 //! [`vmstate_subsections`](crate::vmstate_subsections) and 22 //! [`vmstate_fields`](crate::vmstate_fields). 23 //! 24 //! * direct equivalents to the C macros declared in 25 //! `include/migration/vmstate.h`. These are not type-safe and only provide 26 //! functionality that is missing from `vmstate_of!`. 27 28 pub use std::convert::Infallible; 29 use std::{ 30 error::Error, 31 ffi::{c_int, c_void, CStr}, 32 fmt, io, 33 marker::PhantomData, 34 mem, 35 ptr::{addr_of, NonNull}, 36 }; 37 38 use common::{ 39 callbacks::FnCall, 40 errno::{into_neg_errno, Errno}, 41 Zeroable, 42 }; 43 44 use crate::bindings::{self, VMStateFlags}; 45 pub use crate::bindings::{MigrationPriority, VMStateField}; 46 47 /// This macro is used to call a function with a generic argument bound 48 /// to the type of a field. The function must take a 49 /// [`PhantomData`]`<T>` argument; `T` is the type of 50 /// field `$field` in the `$typ` type. 51 /// 52 /// # Examples 53 /// 54 /// ``` 55 /// # use migration::call_func_with_field; 56 /// # use core::marker::PhantomData; 57 /// const fn size_of_field<T>(_: PhantomData<T>) -> usize { 58 /// std::mem::size_of::<T>() 59 /// } 60 /// 61 /// struct Foo { 62 /// x: u16, 63 /// }; 64 /// // calls size_of_field::<u16>() 65 /// assert_eq!(call_func_with_field!(size_of_field, Foo, x), 2); 66 /// ``` 67 #[macro_export] 68 macro_rules! call_func_with_field { 69 // Based on the answer by user steffahn (Frank Steffahn) at 70 // https://users.rust-lang.org/t/inferring-type-of-field/122857 71 // and used under MIT license 72 ($func:expr, $typ:ty, $($field:tt).+) => { 73 $func(loop { 74 #![allow(unreachable_code)] 75 #![allow(unused_variables)] 76 const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> { ::core::marker::PhantomData } 77 // Unreachable code is exempt from checks on uninitialized values. 78 // Use that trick to infer the type of this PhantomData. 79 break ::core::marker::PhantomData; 80 break phantom__(&{ let value__: $typ; value__.$($field).+ }); 81 }) 82 }; 83 } 84 85 /// A trait for types that can be included in a device's migration stream. It 86 /// provides the base contents of a `VMStateField` (minus the name and offset). 87 /// 88 /// # Safety 89 /// 90 /// The contents of this trait go straight into structs that are parsed by C 91 /// code and used to introspect into other structs. Generally, you don't need 92 /// to implement it except via macros that do it for you, such as 93 /// `impl_vmstate_bitsized!`. 94 pub unsafe trait VMState { 95 /// The base contents of a `VMStateField` (minus the name and offset) for 96 /// the type that is implementing the trait. 97 const BASE: VMStateField; 98 99 /// A flag that is added to another field's `VMStateField` to specify the 100 /// length's type in a variable-sized array. If this is not a supported 101 /// type for the length (i.e. if it is not `u8`, `u16`, `u32`), using it 102 /// in a call to [`vmstate_of!`](crate::vmstate_of) will cause a 103 /// compile-time error. 104 const VARRAY_FLAG: VMStateFlags = { 105 panic!("invalid type for variable-sized array"); 106 }; 107 } 108 109 /// Internal utility function to retrieve a type's `VMStateField`; 110 /// used by [`vmstate_of!`](crate::vmstate_of). 111 pub const fn vmstate_base<T: VMState>(_: PhantomData<T>) -> VMStateField { 112 T::BASE 113 } 114 115 /// Internal utility function to retrieve a type's `VMStateFlags` when it 116 /// is used as the element count of a `VMSTATE_VARRAY`; used by 117 /// [`vmstate_of!`](crate::vmstate_of). 118 pub const fn vmstate_varray_flag<T: VMState>(_: PhantomData<T>) -> VMStateFlags { 119 T::VARRAY_FLAG 120 } 121 122 /// Return the `VMStateField` for a field of a struct. The field must be 123 /// visible in the current scope. 124 /// 125 /// Only a limited set of types is supported out of the box: 126 /// * scalar types (integer and `bool`) 127 /// * the C struct `QEMUTimer` 128 /// * a transparent wrapper for any of the above (`Cell`, `UnsafeCell`, 129 /// [`BqlCell`], [`BqlRefCell`]) 130 /// * a raw pointer to any of the above 131 /// * a `NonNull` pointer, a `Box` or an [`Owned`] for any of the above 132 /// * an array of any of the above 133 /// 134 /// In order to support other types, the trait `VMState` must be implemented 135 /// for them. The macros [`impl_vmstate_forward`](crate::impl_vmstate_forward), 136 /// [`impl_vmstate_bitsized`](crate::impl_vmstate_bitsized), and 137 /// [`impl_vmstate_struct`](crate::impl_vmstate_struct) help with this. 138 /// 139 /// [`BqlCell`]: ../../bql/cell/struct.BqlCell.html 140 /// [`BqlRefCell`]: ../../bql/cell/struct.BqlRefCell.html 141 /// [`Owned`]: ../../qom/qom/struct.Owned.html 142 #[macro_export] 143 macro_rules! vmstate_of { 144 ($struct_name:ty, $($field_name:ident).+ $([0 .. $($num:ident).+ $(* $factor:expr)?])? $(, $test_fn:expr)? $(,)?) => { 145 $crate::bindings::VMStateField { 146 name: ::core::concat!(::core::stringify!($($field_name).+), "\0") 147 .as_bytes() 148 .as_ptr().cast::<::std::os::raw::c_char>(), 149 offset: ::std::mem::offset_of!($struct_name, $($field_name).+), 150 $(num_offset: ::std::mem::offset_of!($struct_name, $($num).+),)? 151 $(field_exists: $crate::vmstate_exist_fn!($struct_name, $test_fn),)? 152 // The calls to `call_func_with_field!` are the magic that 153 // computes most of the VMStateField from the type of the field. 154 ..$crate::call_func_with_field!( 155 $crate::vmstate::vmstate_base, 156 $struct_name, 157 $($field_name).+ 158 )$(.with_varray_flag($crate::call_func_with_field!( 159 $crate::vmstate::vmstate_varray_flag, 160 $struct_name, 161 $($num).+)) 162 $(.with_varray_multiply($factor))?)? 163 } 164 }; 165 } 166 167 pub trait VMStateFlagsExt { 168 const VMS_VARRAY_FLAGS: VMStateFlags; 169 } 170 171 impl VMStateFlagsExt for VMStateFlags { 172 const VMS_VARRAY_FLAGS: VMStateFlags = VMStateFlags( 173 VMStateFlags::VMS_VARRAY_INT32.0 174 | VMStateFlags::VMS_VARRAY_UINT8.0 175 | VMStateFlags::VMS_VARRAY_UINT16.0 176 | VMStateFlags::VMS_VARRAY_UINT32.0, 177 ); 178 } 179 180 // Add a couple builder-style methods to VMStateField, allowing 181 // easy derivation of VMStateField constants from other types. 182 impl VMStateField { 183 #[must_use] 184 pub const fn with_version_id(mut self, version_id: i32) -> Self { 185 assert!(version_id >= 0); 186 self.version_id = version_id; 187 self 188 } 189 190 #[must_use] 191 pub const fn with_array_flag(mut self, num: usize) -> Self { 192 assert!(num <= 0x7FFF_FFFFusize); 193 assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) == 0); 194 assert!((self.flags.0 & VMStateFlags::VMS_VARRAY_FLAGS.0) == 0); 195 if (self.flags.0 & VMStateFlags::VMS_POINTER.0) != 0 { 196 self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_POINTER.0); 197 self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0); 198 // VMS_ARRAY_OF_POINTER flag stores the size of pointer. 199 // FIXME: *const, *mut, NonNull and Box<> have the same size as usize. 200 // Resize if more smart pointers are supported. 201 self.size = std::mem::size_of::<usize>(); 202 } 203 self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_SINGLE.0); 204 self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY.0); 205 self.num = num as i32; 206 self 207 } 208 209 #[must_use] 210 pub const fn with_pointer_flag(mut self) -> Self { 211 assert!((self.flags.0 & VMStateFlags::VMS_POINTER.0) == 0); 212 self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_POINTER.0); 213 self 214 } 215 216 #[must_use] 217 pub const fn with_varray_flag_unchecked(mut self, flag: VMStateFlags) -> Self { 218 self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_ARRAY.0); 219 self.flags = VMStateFlags(self.flags.0 | flag.0); 220 self.num = 0; // varray uses num_offset instead of num. 221 self 222 } 223 224 #[must_use] 225 #[allow(unused_mut)] 226 pub const fn with_varray_flag(mut self, flag: VMStateFlags) -> Self { 227 assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) != 0); 228 self.with_varray_flag_unchecked(flag) 229 } 230 231 #[must_use] 232 pub const fn with_varray_multiply(mut self, num: u32) -> Self { 233 assert!(num <= 0x7FFF_FFFFu32); 234 self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0); 235 self.num = num as i32; 236 self 237 } 238 } 239 240 /// This macro can be used (by just passing it a type) to forward the `VMState` 241 /// trait to the first field of a tuple. This is a workaround for lack of 242 /// support of nested [`offset_of`](core::mem::offset_of) until Rust 1.82.0. 243 /// 244 /// # Examples 245 /// 246 /// ``` 247 /// # use migration::impl_vmstate_forward; 248 /// pub struct Fifo([u8; 16]); 249 /// impl_vmstate_forward!(Fifo); 250 /// ``` 251 #[macro_export] 252 macro_rules! impl_vmstate_forward { 253 // This is similar to impl_vmstate_transparent below, but it 254 // uses the same trick as vmstate_of! to obtain the type of 255 // the first field of the tuple 256 ($tuple:ty) => { 257 unsafe impl $crate::vmstate::VMState for $tuple { 258 const BASE: $crate::bindings::VMStateField = 259 $crate::call_func_with_field!($crate::vmstate::vmstate_base, $tuple, 0); 260 } 261 }; 262 } 263 264 // Transparent wrappers: just use the internal type 265 266 #[macro_export] 267 macro_rules! impl_vmstate_transparent { 268 ($type:ty where $base:tt: VMState $($where:tt)*) => { 269 unsafe impl<$base> $crate::vmstate::VMState for $type where $base: $crate::vmstate::VMState $($where)* { 270 const BASE: $crate::vmstate::VMStateField = $crate::vmstate::VMStateField { 271 size: ::core::mem::size_of::<$type>(), 272 ..<$base as $crate::vmstate::VMState>::BASE 273 }; 274 const VARRAY_FLAG: $crate::bindings::VMStateFlags = <$base as $crate::vmstate::VMState>::VARRAY_FLAG; 275 } 276 }; 277 } 278 279 impl_vmstate_transparent!(bql::BqlCell<T> where T: VMState); 280 impl_vmstate_transparent!(bql::BqlRefCell<T> where T: VMState); 281 impl_vmstate_transparent!(std::cell::Cell<T> where T: VMState); 282 impl_vmstate_transparent!(std::cell::UnsafeCell<T> where T: VMState); 283 impl_vmstate_transparent!(std::pin::Pin<T> where T: VMState); 284 impl_vmstate_transparent!(common::Opaque<T> where T: VMState); 285 impl_vmstate_transparent!(std::mem::ManuallyDrop<T> where T: VMState); 286 287 #[macro_export] 288 macro_rules! impl_vmstate_bitsized { 289 ($type:ty) => { 290 unsafe impl $crate::vmstate::VMState for $type { 291 const BASE: $crate::bindings::VMStateField = 292 <<<$type as ::bilge::prelude::Bitsized>::ArbitraryInt 293 as ::bilge::prelude::Number>::UnderlyingType 294 as $crate::vmstate::VMState>::BASE; 295 const VARRAY_FLAG: $crate::bindings::VMStateFlags = 296 <<<$type as ::bilge::prelude::Bitsized>::ArbitraryInt 297 as ::bilge::prelude::Number>::UnderlyingType 298 as $crate::vmstate::VMState>::VARRAY_FLAG; 299 } 300 301 impl $crate::migratable::ToMigrationState for $type { 302 type Migrated = <<$type as ::bilge::prelude::Bitsized>::ArbitraryInt 303 as ::bilge::prelude::Number>::UnderlyingType; 304 305 fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), $crate::InvalidError> { 306 *target = Self::Migrated::from(*self); 307 Ok(()) 308 } 309 310 fn restore_migrated_state_mut( 311 &mut self, 312 source: Self::Migrated, 313 version_id: u8, 314 ) -> Result<(), $crate::InvalidError> { 315 *self = Self::from(source); 316 Ok(()) 317 } 318 } 319 }; 320 } 321 322 // Scalar types using predefined VMStateInfos 323 324 macro_rules! impl_vmstate_scalar { 325 ($info:ident, $type:ty$(, $varray_flag:ident)?) => { 326 unsafe impl $crate::vmstate::VMState for $type { 327 const BASE: $crate::vmstate::VMStateField = $crate::vmstate::VMStateField { 328 info: addr_of!(bindings::$info), 329 size: mem::size_of::<$type>(), 330 flags: $crate::vmstate::VMStateFlags::VMS_SINGLE, 331 ..::common::zeroable::Zeroable::ZERO 332 }; 333 $(const VARRAY_FLAG: VMStateFlags = VMStateFlags::$varray_flag;)? 334 } 335 }; 336 } 337 338 impl_vmstate_scalar!(vmstate_info_bool, bool); 339 impl_vmstate_scalar!(vmstate_info_int8, i8); 340 impl_vmstate_scalar!(vmstate_info_int16, i16); 341 impl_vmstate_scalar!(vmstate_info_int32, i32); 342 impl_vmstate_scalar!(vmstate_info_int64, i64); 343 impl_vmstate_scalar!(vmstate_info_uint8, u8, VMS_VARRAY_UINT8); 344 impl_vmstate_scalar!(vmstate_info_uint16, u16, VMS_VARRAY_UINT16); 345 impl_vmstate_scalar!(vmstate_info_uint32, u32, VMS_VARRAY_UINT32); 346 impl_vmstate_scalar!(vmstate_info_uint64, u64); 347 impl_vmstate_scalar!(vmstate_info_timer, util::timer::Timer); 348 349 #[macro_export] 350 macro_rules! impl_vmstate_c_struct { 351 ($type:ty, $vmsd:expr) => { 352 unsafe impl $crate::vmstate::VMState for $type { 353 const BASE: $crate::bindings::VMStateField = $crate::bindings::VMStateField { 354 vmsd: ::std::ptr::addr_of!($vmsd), 355 size: ::std::mem::size_of::<$type>(), 356 flags: $crate::bindings::VMStateFlags::VMS_STRUCT, 357 ..::common::zeroable::Zeroable::ZERO 358 }; 359 } 360 }; 361 } 362 363 // Pointer types using the underlying type's VMState plus VMS_POINTER 364 // Note that references are not supported, though references to cells 365 // could be allowed. 366 367 #[macro_export] 368 macro_rules! impl_vmstate_pointer { 369 ($type:ty where $base:tt: VMState $($where:tt)*) => { 370 unsafe impl<$base> $crate::vmstate::VMState for $type where $base: $crate::vmstate::VMState $($where)* { 371 const BASE: $crate::vmstate::VMStateField = <$base as $crate::vmstate::VMState>::BASE.with_pointer_flag(); 372 } 373 }; 374 } 375 376 impl_vmstate_pointer!(*const T where T: VMState); 377 impl_vmstate_pointer!(*mut T where T: VMState); 378 impl_vmstate_pointer!(NonNull<T> where T: VMState); 379 380 // Unlike C pointers, Box is always non-null therefore there is no need 381 // to specify VMS_ALLOC. 382 impl_vmstate_pointer!(Box<T> where T: VMState); 383 384 // Arrays using the underlying type's VMState plus 385 // VMS_ARRAY/VMS_ARRAY_OF_POINTER 386 387 unsafe impl<T: VMState, const N: usize> VMState for [T; N] { 388 const BASE: VMStateField = <T as VMState>::BASE.with_array_flag(N); 389 } 390 391 #[doc(alias = "VMSTATE_UNUSED")] 392 #[macro_export] 393 macro_rules! vmstate_unused { 394 ($size:expr) => {{ 395 $crate::bindings::VMStateField { 396 name: c"unused".as_ptr(), 397 size: $size, 398 info: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate_info_unused_buffer) }, 399 flags: $crate::bindings::VMStateFlags::VMS_BUFFER, 400 ..::common::Zeroable::ZERO 401 } 402 }}; 403 } 404 405 pub extern "C" fn rust_vms_test_field_exists<T, F: for<'a> FnCall<(&'a T, u8), bool>>( 406 opaque: *mut c_void, 407 version_id: c_int, 408 ) -> bool { 409 // SAFETY: the function is used in T's implementation of VMState 410 let owner: &T = unsafe { &*(opaque.cast::<T>()) }; 411 let version: u8 = version_id.try_into().unwrap(); 412 F::call((owner, version)) 413 } 414 415 pub type VMSFieldExistCb = unsafe extern "C" fn( 416 opaque: *mut std::os::raw::c_void, 417 version_id: std::os::raw::c_int, 418 ) -> bool; 419 420 #[macro_export] 421 macro_rules! vmstate_exist_fn { 422 ($struct_name:ty, $test_fn:expr) => {{ 423 const fn test_cb_builder__<T, F: for<'a> ::common::FnCall<(&'a T, u8), bool>>( 424 _phantom: ::core::marker::PhantomData<F>, 425 ) -> $crate::vmstate::VMSFieldExistCb { 426 const { assert!(F::IS_SOME) }; 427 $crate::vmstate::rust_vms_test_field_exists::<T, F> 428 } 429 430 const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> { 431 ::core::marker::PhantomData 432 } 433 Some(test_cb_builder__::<$struct_name, _>(phantom__(&$test_fn))) 434 }}; 435 } 436 437 /// Add a terminator to the fields in the arguments, and return 438 /// a reference to the resulting array of values. 439 #[macro_export] 440 macro_rules! vmstate_fields_ref { 441 ($($field:expr),*$(,)*) => { 442 &[ 443 $($field),*, 444 $crate::bindings::VMStateField { 445 flags: $crate::bindings::VMStateFlags::VMS_END, 446 ..::common::zeroable::Zeroable::ZERO 447 } 448 ] 449 } 450 } 451 452 /// Helper macro to declare a list of 453 /// ([`VMStateField`](`crate::bindings::VMStateField`)) into a static and return 454 /// a pointer to the array of values it created. 455 #[macro_export] 456 macro_rules! vmstate_fields { 457 ($($field:expr),*$(,)*) => {{ 458 static _FIELDS: &[$crate::bindings::VMStateField] = $crate::vmstate_fields_ref!( 459 $($field),*, 460 ); 461 _FIELDS 462 }} 463 } 464 465 #[doc(alias = "VMSTATE_VALIDATE")] 466 #[macro_export] 467 macro_rules! vmstate_validate { 468 ($struct_name:ty, $test_name:expr, $test_fn:expr $(,)?) => { 469 $crate::bindings::VMStateField { 470 name: ::std::ffi::CStr::as_ptr($test_name), 471 field_exists: $crate::vmstate_exist_fn!($struct_name, $test_fn), 472 flags: $crate::bindings::VMStateFlags( 473 $crate::bindings::VMStateFlags::VMS_MUST_EXIST.0 474 | $crate::bindings::VMStateFlags::VMS_ARRAY.0, 475 ), 476 num: 0, // 0 elements: no data, only run test_fn callback 477 ..::common::zeroable::Zeroable::ZERO 478 } 479 }; 480 } 481 482 /// Helper macro to allow using a struct in [`vmstate_of!`] 483 /// 484 /// # Safety 485 /// 486 /// The [`VMStateDescription`] constant `$vmsd` must be an accurate 487 /// description of the struct. 488 #[macro_export] 489 macro_rules! impl_vmstate_struct { 490 ($type:ty, $vmsd:expr) => { 491 unsafe impl $crate::vmstate::VMState for $type { 492 const BASE: $crate::bindings::VMStateField = { 493 static VMSD: &$crate::bindings::VMStateDescription = $vmsd.as_ref(); 494 495 $crate::bindings::VMStateField { 496 vmsd: ::core::ptr::addr_of!(*VMSD), 497 size: ::core::mem::size_of::<$type>(), 498 flags: $crate::bindings::VMStateFlags::VMS_STRUCT, 499 ..common::Zeroable::ZERO 500 } 501 }; 502 } 503 }; 504 } 505 506 /// The type returned by [`vmstate_subsections!`](crate::vmstate_subsections). 507 pub type VMStateSubsections = &'static [Option<&'static crate::bindings::VMStateDescription>]; 508 509 /// Helper macro to declare a list of subsections ([`VMStateDescription`]) 510 /// into a static and return a pointer to the array of pointers it created. 511 #[macro_export] 512 macro_rules! vmstate_subsections { 513 ($($subsection:expr),*$(,)*) => {{ 514 static _SUBSECTIONS: $crate::vmstate::VMStateSubsections = &[ 515 $({ 516 static _SUBSECTION: $crate::bindings::VMStateDescription = $subsection.get(); 517 Some(&_SUBSECTION) 518 }),*, 519 None, 520 ]; 521 &_SUBSECTIONS 522 }} 523 } 524 525 pub struct VMStateDescription<T>(bindings::VMStateDescription, PhantomData<fn(&T)>); 526 527 // SAFETY: When a *const T is passed to the callbacks, the call itself 528 // is done in a thread-safe manner. The invocation is okay as long as 529 // T itself is `Sync`. 530 unsafe impl<T: Sync> Sync for VMStateDescription<T> {} 531 532 #[derive(Clone)] 533 pub struct VMStateDescriptionBuilder<T>(bindings::VMStateDescription, PhantomData<fn(&T)>); 534 535 #[derive(Debug)] 536 pub struct InvalidError; 537 538 impl Error for InvalidError {} 539 540 impl std::fmt::Display for InvalidError { 541 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 542 write!(f, "invalid migration data") 543 } 544 } 545 546 impl From<InvalidError> for Errno { 547 fn from(_value: InvalidError) -> Errno { 548 io::ErrorKind::InvalidInput.into() 549 } 550 } 551 552 unsafe extern "C" fn vmstate_no_version_cb< 553 T, 554 F: for<'a> FnCall<(&'a T,), Result<(), impl Into<Errno>>>, 555 >( 556 opaque: *mut c_void, 557 ) -> c_int { 558 // SAFETY: the function is used in T's implementation of VMState 559 let result = F::call((unsafe { &*(opaque.cast::<T>()) },)); 560 into_neg_errno(result) 561 } 562 563 unsafe extern "C" fn vmstate_post_load_cb< 564 T, 565 F: for<'a> FnCall<(&'a T, u8), Result<(), impl Into<Errno>>>, 566 >( 567 opaque: *mut c_void, 568 version_id: c_int, 569 ) -> c_int { 570 // SAFETY: the function is used in T's implementation of VMState 571 let owner: &T = unsafe { &*(opaque.cast::<T>()) }; 572 let version: u8 = version_id.try_into().unwrap(); 573 let result = F::call((owner, version)); 574 into_neg_errno(result) 575 } 576 577 unsafe extern "C" fn vmstate_needed_cb<T, F: for<'a> FnCall<(&'a T,), bool>>( 578 opaque: *mut c_void, 579 ) -> bool { 580 // SAFETY: the function is used in T's implementation of VMState 581 F::call((unsafe { &*(opaque.cast::<T>()) },)) 582 } 583 584 unsafe extern "C" fn vmstate_dev_unplug_pending_cb<T, F: for<'a> FnCall<(&'a T,), bool>>( 585 opaque: *mut c_void, 586 ) -> bool { 587 // SAFETY: the function is used in T's implementation of VMState 588 F::call((unsafe { &*(opaque.cast::<T>()) },)) 589 } 590 591 impl<T> VMStateDescriptionBuilder<T> { 592 #[must_use] 593 pub const fn name(mut self, name_str: &CStr) -> Self { 594 self.0.name = ::std::ffi::CStr::as_ptr(name_str); 595 self 596 } 597 598 #[must_use] 599 pub const fn unmigratable(mut self) -> Self { 600 self.0.unmigratable = true; 601 self 602 } 603 604 #[must_use] 605 pub const fn early_setup(mut self) -> Self { 606 self.0.early_setup = true; 607 self 608 } 609 610 #[must_use] 611 pub const fn version_id(mut self, version: u8) -> Self { 612 self.0.version_id = version as c_int; 613 self 614 } 615 616 #[must_use] 617 pub const fn minimum_version_id(mut self, min_version: u8) -> Self { 618 self.0.minimum_version_id = min_version as c_int; 619 self 620 } 621 622 #[must_use] 623 pub const fn priority(mut self, priority: MigrationPriority) -> Self { 624 self.0.priority = priority; 625 self 626 } 627 628 #[must_use] 629 pub const fn pre_load<F: for<'a> FnCall<(&'a T,), Result<(), impl Into<Errno>>>>( 630 mut self, 631 _f: &F, 632 ) -> Self { 633 self.0.pre_load = if F::IS_SOME { 634 Some(vmstate_no_version_cb::<T, F>) 635 } else { 636 None 637 }; 638 self 639 } 640 641 #[must_use] 642 pub const fn post_load<F: for<'a> FnCall<(&'a T, u8), Result<(), impl Into<Errno>>>>( 643 mut self, 644 _f: &F, 645 ) -> Self { 646 self.0.post_load = if F::IS_SOME { 647 Some(vmstate_post_load_cb::<T, F>) 648 } else { 649 None 650 }; 651 self 652 } 653 654 #[must_use] 655 pub const fn pre_save<F: for<'a> FnCall<(&'a T,), Result<(), impl Into<Errno>>>>( 656 mut self, 657 _f: &F, 658 ) -> Self { 659 self.0.pre_save = if F::IS_SOME { 660 Some(vmstate_no_version_cb::<T, F>) 661 } else { 662 None 663 }; 664 self 665 } 666 667 #[must_use] 668 pub const fn post_save<F: for<'a> FnCall<(&'a T,), Result<(), impl Into<Errno>>>>( 669 mut self, 670 _f: &F, 671 ) -> Self { 672 self.0.post_save = if F::IS_SOME { 673 Some(vmstate_no_version_cb::<T, F>) 674 } else { 675 None 676 }; 677 self 678 } 679 680 #[must_use] 681 pub const fn needed<F: for<'a> FnCall<(&'a T,), bool>>(mut self, _f: &F) -> Self { 682 self.0.needed = if F::IS_SOME { 683 Some(vmstate_needed_cb::<T, F>) 684 } else { 685 None 686 }; 687 self 688 } 689 690 #[must_use] 691 pub const fn unplug_pending<F: for<'a> FnCall<(&'a T,), bool>>(mut self, _f: &F) -> Self { 692 self.0.dev_unplug_pending = if F::IS_SOME { 693 Some(vmstate_dev_unplug_pending_cb::<T, F>) 694 } else { 695 None 696 }; 697 self 698 } 699 700 #[must_use] 701 pub const fn fields(mut self, fields: &'static [VMStateField]) -> Self { 702 if fields[fields.len() - 1].flags.0 != VMStateFlags::VMS_END.0 { 703 panic!("fields are not terminated, use vmstate_fields!"); 704 } 705 self.0.fields = fields.as_ptr(); 706 self 707 } 708 709 #[must_use] 710 pub const fn subsections(mut self, subs: &'static VMStateSubsections) -> Self { 711 if subs[subs.len() - 1].is_some() { 712 panic!("subsections are not terminated, use vmstate_subsections!"); 713 } 714 let subs: *const Option<&bindings::VMStateDescription> = subs.as_ptr(); 715 self.0.subsections = subs.cast::<*const bindings::VMStateDescription>(); 716 self 717 } 718 719 #[must_use] 720 pub const fn build(self) -> VMStateDescription<T> { 721 VMStateDescription::<T>(self.0, PhantomData) 722 } 723 724 #[must_use] 725 pub const fn new() -> Self { 726 Self(bindings::VMStateDescription::ZERO, PhantomData) 727 } 728 } 729 730 impl<T> Default for VMStateDescriptionBuilder<T> { 731 fn default() -> Self { 732 Self::new() 733 } 734 } 735 736 impl<T> VMStateDescription<T> { 737 pub const fn get(&self) -> bindings::VMStateDescription { 738 self.0 739 } 740 741 pub const fn as_ref(&self) -> &bindings::VMStateDescription { 742 &self.0 743 } 744 } 745