1 // Copyright 2025 Red Hat, Inc. 2 // Author(s): Paolo Bonzini <pbonzini@redhat.com> 3 // SPDX-License-Identifier: GPL-2.0-or-later 4 5 use std::{ 6 fmt, 7 mem::size_of, 8 ptr::{self, addr_of, NonNull}, 9 sync::{Arc, Mutex}, 10 }; 11 12 use bql::{BqlCell, BqlRefCell}; 13 use common::Zeroable; 14 15 use crate::{ 16 bindings, vmstate_fields_ref, vmstate_of, InvalidError, VMState, VMStateDescriptionBuilder, 17 }; 18 19 /// Enables QEMU migration support even when a type is wrapped with 20 /// synchronization primitives (like `Mutex`) that the C migration 21 /// code cannot directly handle. The trait provides methods to 22 /// extract essential state for migration and restore it after 23 /// migration completes. 24 /// 25 /// On top of extracting data from synchronization wrappers during save 26 /// and restoring it during load, it's also possible to use `ToMigrationState` 27 /// to convert runtime representations to migration-safe formats. 28 /// 29 /// # Examples 30 /// 31 /// ``` 32 /// use bql::BqlCell; 33 /// use migration::{InvalidError, ToMigrationState, VMState}; 34 /// # use migration::VMStateField; 35 /// 36 /// # #[derive(Debug, PartialEq, Eq)] 37 /// struct DeviceState { 38 /// counter: BqlCell<u32>, 39 /// enabled: bool, 40 /// } 41 /// 42 /// # #[derive(Debug)] 43 /// #[derive(Default)] 44 /// struct DeviceMigrationState { 45 /// counter: u32, 46 /// enabled: bool, 47 /// } 48 /// 49 /// # unsafe impl VMState for DeviceMigrationState { 50 /// # const BASE: VMStateField = ::common::Zeroable::ZERO; 51 /// # } 52 /// impl ToMigrationState for DeviceState { 53 /// type Migrated = DeviceMigrationState; 54 /// 55 /// fn snapshot_migration_state( 56 /// &self, 57 /// target: &mut Self::Migrated, 58 /// ) -> Result<(), InvalidError> { 59 /// target.counter = self.counter.get(); 60 /// target.enabled = self.enabled; 61 /// Ok(()) 62 /// } 63 /// 64 /// fn restore_migrated_state_mut( 65 /// &mut self, 66 /// source: Self::Migrated, 67 /// _version_id: u8, 68 /// ) -> Result<(), InvalidError> { 69 /// self.counter.set(source.counter); 70 /// self.enabled = source.enabled; 71 /// Ok(()) 72 /// } 73 /// } 74 /// # bql::start_test(); 75 /// # let dev = DeviceState { counter: 10.into(), enabled: true }; 76 /// # let mig = dev.to_migration_state().unwrap(); 77 /// # assert!(matches!(*mig, DeviceMigrationState { counter: 10, enabled: true })); 78 /// # let mut dev2 = DeviceState { counter: 42.into(), enabled: false }; 79 /// # dev2.restore_migrated_state_mut(*mig, 1).unwrap(); 80 /// # assert_eq!(dev2, dev); 81 /// ``` 82 /// 83 /// More commonly, the trait is derived through the 84 /// [`derive(ToMigrationState)`](qemu_macros::ToMigrationState) procedural 85 /// macro. 86 pub trait ToMigrationState { 87 /// The type used to represent the migrated state. 88 type Migrated: Default + VMState; 89 90 /// Capture the current state into a migration-safe format, failing 91 /// if the state cannot be migrated. 92 fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), InvalidError>; 93 94 /// Restores state from a migrated representation, failing if the 95 /// state cannot be restored. 96 fn restore_migrated_state_mut( 97 &mut self, 98 source: Self::Migrated, 99 version_id: u8, 100 ) -> Result<(), InvalidError>; 101 102 /// Convenience method to combine allocation and state capture 103 /// into a single operation. 104 fn to_migration_state(&self) -> Result<Box<Self::Migrated>, InvalidError> { 105 let mut migrated = Box::<Self::Migrated>::default(); 106 self.snapshot_migration_state(&mut migrated)?; 107 Ok(migrated) 108 } 109 } 110 111 // Implementations for primitive types. Do not use a blanket implementation 112 // for all Copy types, because [T; N] is Copy if T is Copy; that would conflict 113 // with the below implementation for arrays. 114 macro_rules! impl_for_primitive { 115 ($($t:ty),*) => { 116 $( 117 impl ToMigrationState for $t { 118 type Migrated = Self; 119 120 fn snapshot_migration_state( 121 &self, 122 target: &mut Self::Migrated, 123 ) -> Result<(), InvalidError> { 124 *target = *self; 125 Ok(()) 126 } 127 128 fn restore_migrated_state_mut( 129 &mut self, 130 source: Self::Migrated, 131 _version_id: u8, 132 ) -> Result<(), InvalidError> { 133 *self = source; 134 Ok(()) 135 } 136 } 137 )* 138 }; 139 } 140 141 impl_for_primitive!(u8, u16, u32, u64, i8, i16, i32, i64, bool); 142 143 impl<T: ToMigrationState, const N: usize> ToMigrationState for [T; N] 144 where 145 [T::Migrated; N]: Default, 146 { 147 type Migrated = [T::Migrated; N]; 148 149 fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), InvalidError> { 150 for (item, target_item) in self.iter().zip(target.iter_mut()) { 151 item.snapshot_migration_state(target_item)?; 152 } 153 Ok(()) 154 } 155 156 fn restore_migrated_state_mut( 157 &mut self, 158 source: Self::Migrated, 159 version_id: u8, 160 ) -> Result<(), InvalidError> { 161 for (item, source_item) in self.iter_mut().zip(source) { 162 item.restore_migrated_state_mut(source_item, version_id)?; 163 } 164 Ok(()) 165 } 166 } 167 168 impl<T: ToMigrationState> ToMigrationState for Mutex<T> { 169 type Migrated = T::Migrated; 170 171 fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), InvalidError> { 172 self.lock().unwrap().snapshot_migration_state(target) 173 } 174 175 fn restore_migrated_state_mut( 176 &mut self, 177 source: Self::Migrated, 178 version_id: u8, 179 ) -> Result<(), InvalidError> { 180 self.get_mut() 181 .unwrap() 182 .restore_migrated_state_mut(source, version_id) 183 } 184 } 185 186 impl<T: ToMigrationState> ToMigrationState for BqlRefCell<T> { 187 type Migrated = T::Migrated; 188 189 fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), InvalidError> { 190 self.borrow().snapshot_migration_state(target) 191 } 192 193 fn restore_migrated_state_mut( 194 &mut self, 195 source: Self::Migrated, 196 version_id: u8, 197 ) -> Result<(), InvalidError> { 198 self.get_mut() 199 .restore_migrated_state_mut(source, version_id) 200 } 201 } 202 203 /// Extension trait for types that support migration state restoration 204 /// through interior mutability. 205 /// 206 /// This trait extends [`ToMigrationState`] for types that can restore 207 /// their state without requiring mutable access. While user structs 208 /// will generally use `ToMigrationState`, the device will have multiple 209 /// references and therefore the device struct has to employ an interior 210 /// mutability wrapper like [`Mutex`] or [`BqlRefCell`]. 211 /// 212 /// Anything that implements this trait can in turn be used within 213 /// [`Migratable<T>`], which makes no assumptions on how to achieve mutable 214 /// access to the runtime state. 215 /// 216 /// # Examples 217 /// 218 /// ``` 219 /// use std::sync::Mutex; 220 /// 221 /// use migration::ToMigrationStateShared; 222 /// 223 /// let device_state = Mutex::new(42); 224 /// // Can restore without &mut access 225 /// device_state.restore_migrated_state(100, 1).unwrap(); 226 /// assert_eq!(*device_state.lock().unwrap(), 100); 227 /// ``` 228 pub trait ToMigrationStateShared: ToMigrationState { 229 /// Restores state from a migrated representation to an interior-mutable 230 /// object. Similar to `restore_migrated_state_mut`, but requires a 231 /// shared reference; therefore it can be used to restore a device's 232 /// state even though devices have multiple references to them. 233 fn restore_migrated_state( 234 &self, 235 source: Self::Migrated, 236 version_id: u8, 237 ) -> Result<(), InvalidError>; 238 } 239 240 impl<T: ToMigrationStateShared, const N: usize> ToMigrationStateShared for [T; N] 241 where 242 [T::Migrated; N]: Default, 243 { 244 fn restore_migrated_state( 245 &self, 246 source: Self::Migrated, 247 version_id: u8, 248 ) -> Result<(), InvalidError> { 249 for (item, source_item) in self.iter().zip(source) { 250 item.restore_migrated_state(source_item, version_id)?; 251 } 252 Ok(()) 253 } 254 } 255 256 // Arc requires the contained object to be interior-mutable 257 impl<T: ToMigrationStateShared> ToMigrationState for Arc<T> { 258 type Migrated = T::Migrated; 259 260 fn snapshot_migration_state(&self, target: &mut Self::Migrated) -> Result<(), InvalidError> { 261 (**self).snapshot_migration_state(target) 262 } 263 264 fn restore_migrated_state_mut( 265 &mut self, 266 source: Self::Migrated, 267 version_id: u8, 268 ) -> Result<(), InvalidError> { 269 (**self).restore_migrated_state(source, version_id) 270 } 271 } 272 273 impl<T: ToMigrationStateShared> ToMigrationStateShared for Arc<T> { 274 fn restore_migrated_state( 275 &self, 276 source: Self::Migrated, 277 version_id: u8, 278 ) -> Result<(), InvalidError> { 279 (**self).restore_migrated_state(source, version_id) 280 } 281 } 282 283 // Interior-mutable types. Note how they only require ToMigrationState for 284 // the inner type! 285 286 impl<T: ToMigrationState> ToMigrationStateShared for Mutex<T> { 287 fn restore_migrated_state( 288 &self, 289 source: Self::Migrated, 290 version_id: u8, 291 ) -> Result<(), InvalidError> { 292 self.lock() 293 .unwrap() 294 .restore_migrated_state_mut(source, version_id) 295 } 296 } 297 298 impl<T: ToMigrationState> ToMigrationStateShared for BqlRefCell<T> { 299 fn restore_migrated_state( 300 &self, 301 source: Self::Migrated, 302 version_id: u8, 303 ) -> Result<(), InvalidError> { 304 self.borrow_mut() 305 .restore_migrated_state_mut(source, version_id) 306 } 307 } 308 309 /// A wrapper that enables QEMU migration for types with shared state. 310 /// 311 /// `Migratable<T>` provides a bridge between Rust types that use interior 312 /// mutability (like `Mutex<T>`) and QEMU's C-based migration infrastructure. 313 /// It manages the lifecycle of migration state and provides automatic 314 /// conversion between runtime and migration representations. 315 /// 316 /// ``` 317 /// # use std::sync::Mutex; 318 /// # use migration::{Migratable, ToMigrationState, VMState, VMStateField}; 319 /// 320 /// #[derive(ToMigrationState)] 321 /// pub struct DeviceRegs { 322 /// status: u32, 323 /// } 324 /// # unsafe impl VMState for DeviceRegsMigration { 325 /// # const BASE: VMStateField = ::common::Zeroable::ZERO; 326 /// # } 327 /// 328 /// pub struct SomeDevice { 329 /// // ... 330 /// registers: Migratable<Mutex<DeviceRegs>>, 331 /// } 332 /// ``` 333 #[repr(C)] 334 pub struct Migratable<T: ToMigrationStateShared> { 335 /// Pointer to migration state, valid only during migration operations. 336 /// C vmstate does not support NULL pointers, so no `Option<Box<>>`. 337 migration_state: BqlCell<*mut T::Migrated>, 338 339 /// The runtime state that can be accessed during normal operation 340 runtime_state: T, 341 } 342 343 impl<T: ToMigrationStateShared> std::ops::Deref for Migratable<T> { 344 type Target = T; 345 346 fn deref(&self) -> &Self::Target { 347 &self.runtime_state 348 } 349 } 350 351 impl<T: ToMigrationStateShared> std::ops::DerefMut for Migratable<T> { 352 fn deref_mut(&mut self) -> &mut Self::Target { 353 &mut self.runtime_state 354 } 355 } 356 357 impl<T: ToMigrationStateShared> Migratable<T> { 358 /// Creates a new `Migratable` wrapper around the given runtime state. 359 /// 360 /// # Returns 361 /// A new `Migratable` instance ready for use and migration 362 pub fn new(runtime_state: T) -> Self { 363 Self { 364 migration_state: BqlCell::new(ptr::null_mut()), 365 runtime_state, 366 } 367 } 368 369 fn pre_save(&self) -> Result<(), InvalidError> { 370 let state = self.runtime_state.to_migration_state()?; 371 self.migration_state.set(Box::into_raw(state)); 372 Ok(()) 373 } 374 375 fn post_save(&self) -> Result<(), InvalidError> { 376 let state = unsafe { Box::from_raw(self.migration_state.replace(ptr::null_mut())) }; 377 drop(state); 378 Ok(()) 379 } 380 381 fn pre_load(&self) -> Result<(), InvalidError> { 382 self.migration_state 383 .set(Box::into_raw(Box::<T::Migrated>::default())); 384 Ok(()) 385 } 386 387 fn post_load(&self, version_id: u8) -> Result<(), InvalidError> { 388 let state = unsafe { Box::from_raw(self.migration_state.replace(ptr::null_mut())) }; 389 self.runtime_state 390 .restore_migrated_state(*state, version_id) 391 } 392 } 393 394 impl<T: ToMigrationStateShared + fmt::Debug> fmt::Debug for Migratable<T> 395 where 396 T::Migrated: fmt::Debug, 397 { 398 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 399 let mut struct_f = f.debug_struct("Migratable"); 400 struct_f.field("runtime_state", &self.runtime_state); 401 402 let state = NonNull::new(self.migration_state.get()).map(|x| unsafe { x.as_ref() }); 403 struct_f.field("migration_state", &state); 404 struct_f.finish() 405 } 406 } 407 408 impl<T: ToMigrationStateShared + Default> Default for Migratable<T> { 409 fn default() -> Self { 410 Self::new(T::default()) 411 } 412 } 413 414 impl<T: 'static + ToMigrationStateShared> Migratable<T> { 415 const FIELD: bindings::VMStateField = vmstate_of!(Self, migration_state); 416 417 const FIELDS: &[bindings::VMStateField] = vmstate_fields_ref! { 418 Migratable::<T>::FIELD 419 }; 420 421 const VMSD: &'static bindings::VMStateDescription = VMStateDescriptionBuilder::<Self>::new() 422 .version_id(1) 423 .minimum_version_id(1) 424 .pre_save(&Self::pre_save) 425 .pre_load(&Self::pre_load) 426 .post_save(&Self::post_save) 427 .post_load(&Self::post_load) 428 .fields(Self::FIELDS) 429 .build() 430 .as_ref(); 431 } 432 433 unsafe impl<T: 'static + ToMigrationStateShared> VMState for Migratable<T> { 434 const BASE: bindings::VMStateField = { 435 bindings::VMStateField { 436 vmsd: addr_of!(*Self::VMSD), 437 size: size_of::<Self>(), 438 flags: bindings::VMStateFlags::VMS_STRUCT, 439 ..Zeroable::ZERO 440 } 441 }; 442 } 443