summary refs log tree commit diff stats
path: root/rust/qemu-api
diff options
context:
space:
mode:
Diffstat (limited to 'rust/qemu-api')
-rw-r--r--rust/qemu-api/Cargo.toml1
-rw-r--r--rust/qemu-api/meson.build12
-rw-r--r--rust/qemu-api/src/bindings.rs21
-rw-r--r--rust/qemu-api/src/cell.rs4
-rw-r--r--rust/qemu-api/src/lib.rs1
-rw-r--r--rust/qemu-api/src/prelude.rs2
-rw-r--r--rust/qemu-api/src/qdev.rs3
-rw-r--r--rust/qemu-api/src/qom.rs2
-rw-r--r--rust/qemu-api/src/vmstate.rs709
-rw-r--r--rust/qemu-api/tests/tests.rs2
-rw-r--r--rust/qemu-api/tests/vmstate_tests.rs4
-rw-r--r--rust/qemu-api/wrapper.h1
12 files changed, 15 insertions, 747 deletions
diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml
index fbfb894421..7276e67aa9 100644
--- a/rust/qemu-api/Cargo.toml
+++ b/rust/qemu-api/Cargo.toml
@@ -15,6 +15,7 @@ rust-version.workspace = true
 
 [dependencies]
 common = { path = "../common" }
+migration = { path = "../migration" }
 util = { path = "../util" }
 qemu_api_macros = { path = "../qemu-api-macros" }
 
diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build
index 7734f656a2..a6b5772d19 100644
--- a/rust/qemu-api/meson.build
+++ b/rust/qemu-api/meson.build
@@ -11,8 +11,6 @@ c_enums = [
   'GpioPolarity',
   'MachineInitPhase',
   'MemoryDeviceInfoKind',
-  'MigrationPolicy',
-  'MigrationPriority',
   'QEMUChrEvent',
   'ResetType',
   'device_endian',
@@ -23,12 +21,13 @@ foreach enum : c_enums
 endforeach
 c_bitfields = [
   'ClockEvent',
-  'VMStateFlags',
 ]
 foreach enum : c_bitfields
   _qemu_api_bindgen_args += ['--bitfield-enum', enum]
 endforeach
 
+_qemu_api_bindgen_args += ['--blocklist-type', 'VMStateDescription']
+
 _qemu_api_bindgen_args += ['--blocklist-type', 'Error']
 # TODO: Remove this comment when the clang/libclang mismatch issue is solved.
 #
@@ -60,15 +59,14 @@ _qemu_api_rs = static_library(
       'src/qdev.rs',
       'src/qom.rs',
       'src/sysbus.rs',
-      'src/vmstate.rs',
     ],
     {'.' : _qemu_api_bindings_inc_rs},
   ),
   override_options: ['rust_std=2021', 'build.rust_std=2021'],
   rust_abi: 'rust',
   rust_args: _qemu_api_cfg,
-  dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, qemu_api_macros, util_rs,
-                 qom, hwcore, chardev, migration],
+  dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, migration_rs, qemu_api_macros,
+                 util_rs, qom, hwcore, chardev],
 )
 
 qemu_api_rs = declare_dependency(link_with: [_qemu_api_rs],
@@ -90,7 +88,7 @@ test('rust-qemu-api-integration',
         override_options: ['rust_std=2021', 'build.rust_std=2021'],
         rust_args: ['--test'],
         install: false,
-        dependencies: [common_rs, util_rs, qemu_api_rs]),
+        dependencies: [common_rs, util_rs, migration_rs, qemu_api_rs]),
     args: [
         '--test', '--test-threads', '1',
         '--format', 'pretty',
diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs
index aedf42b652..ce00a6e0e4 100644
--- a/rust/qemu-api/src/bindings.rs
+++ b/rust/qemu-api/src/bindings.rs
@@ -21,6 +21,7 @@
 //! `bindgen`-generated declarations.
 
 use common::Zeroable;
+use migration::bindings::VMStateDescription;
 use util::bindings::Error;
 
 #[cfg(MESON)]
@@ -51,28 +52,8 @@ unsafe impl Sync for Property {}
 unsafe impl Send for TypeInfo {}
 unsafe impl Sync for TypeInfo {}
 
-unsafe impl Send for VMStateDescription {}
-unsafe impl Sync for VMStateDescription {}
-
-unsafe impl Send for VMStateField {}
-unsafe impl Sync for VMStateField {}
-
-unsafe impl Send for VMStateInfo {}
-unsafe impl Sync for VMStateInfo {}
-
-// bindgen does not derive Default here
-#[allow(clippy::derivable_impls)]
-impl Default for crate::bindings::VMStateFlags {
-    fn default() -> Self {
-        Self(0)
-    }
-}
-
 unsafe impl Zeroable for crate::bindings::Property__bindgen_ty_1 {}
 unsafe impl Zeroable for crate::bindings::Property {}
-unsafe impl Zeroable for crate::bindings::VMStateFlags {}
-unsafe impl Zeroable for crate::bindings::VMStateField {}
-unsafe impl Zeroable for crate::bindings::VMStateDescription {}
 unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_1 {}
 unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_2 {}
 unsafe impl Zeroable for crate::bindings::MemoryRegionOps {}
diff --git a/rust/qemu-api/src/cell.rs b/rust/qemu-api/src/cell.rs
index d13848df20..b80a0fd80b 100644
--- a/rust/qemu-api/src/cell.rs
+++ b/rust/qemu-api/src/cell.rs
@@ -152,7 +152,9 @@ use std::{
     ptr::NonNull,
 };
 
-use crate::{bindings, impl_vmstate_transparent};
+use migration::impl_vmstate_transparent;
+
+use crate::bindings;
 
 /// An internal function that is used by doctests.
 pub fn bql_start_test() {
diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs
index 54b252fb2c..55386f6697 100644
--- a/rust/qemu-api/src/lib.rs
+++ b/rust/qemu-api/src/lib.rs
@@ -20,7 +20,6 @@ pub mod memory;
 pub mod qdev;
 pub mod qom;
 pub mod sysbus;
-pub mod vmstate;
 
 // Allow proc-macros to refer to `::qemu_api` inside the `qemu_api` crate (this
 // crate).
diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs
index 3d771481e4..c10c171158 100644
--- a/rust/qemu-api/src/prelude.rs
+++ b/rust/qemu-api/src/prelude.rs
@@ -21,5 +21,3 @@ pub use crate::qom::ObjectType;
 pub use crate::qom_isa;
 
 pub use crate::sysbus::SysBusDeviceMethods;
-
-pub use crate::vmstate::VMState;
diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs
index d87479ce13..c81ae7cf45 100644
--- a/rust/qemu-api/src/qdev.rs
+++ b/rust/qemu-api/src/qdev.rs
@@ -11,17 +11,16 @@ use std::{
 
 pub use bindings::{ClockEvent, DeviceClass, Property, ResetType};
 use common::{callbacks::FnCall, Opaque};
+use migration::{impl_vmstate_c_struct, VMStateDescription};
 use util::{Error, Result};
 
 use crate::{
     bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, ResettableClass},
     cell::bql_locked,
     chardev::Chardev,
-    impl_vmstate_c_struct,
     irq::InterruptSource,
     prelude::*,
     qom::{ObjectClass, ObjectImpl, Owned, ParentInit},
-    vmstate::VMStateDescription,
 };
 
 /// A safe wrapper around [`bindings::Clock`].
diff --git a/rust/qemu-api/src/qom.rs b/rust/qemu-api/src/qom.rs
index 49b4f03ccf..7f2f7797e4 100644
--- a/rust/qemu-api/src/qom.rs
+++ b/rust/qemu-api/src/qom.rs
@@ -103,6 +103,7 @@ use std::{
 
 pub use bindings::ObjectClass;
 use common::Opaque;
+use migration::impl_vmstate_pointer;
 
 use crate::{
     bindings::{
@@ -110,7 +111,6 @@ use crate::{
         object_get_typename, object_new, object_ref, object_unref, TypeInfo,
     },
     cell::bql_locked,
-    impl_vmstate_pointer,
 };
 
 /// A safe wrapper around [`bindings::Object`].
diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs
deleted file mode 100644
index 37e47cc4c6..0000000000
--- a/rust/qemu-api/src/vmstate.rs
+++ /dev/null
@@ -1,709 +0,0 @@
-// Copyright 2024, Linaro Limited
-// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! Helper macros to declare migration state for device models.
-//!
-//! This module includes four families of macros:
-//!
-//! * [`vmstate_unused!`](crate::vmstate_unused) and
-//!   [`vmstate_of!`](crate::vmstate_of), which are used to express the
-//!   migration format for a struct.  This is based on the [`VMState`] trait,
-//!   which is defined by all migratable types.
-//!
-//! * [`impl_vmstate_forward`](crate::impl_vmstate_forward),
-//!   [`impl_vmstate_bitsized`](crate::impl_vmstate_bitsized), and
-//!   [`impl_vmstate_struct`](crate::impl_vmstate_struct), which help with the
-//!   definition of the [`VMState`] trait (respectively for transparent structs,
-//!   nested structs and `bilge`-defined types)
-//!
-//! * helper macros to declare a device model state struct, in particular
-//!   [`vmstate_subsections`](crate::vmstate_subsections) and
-//!   [`vmstate_fields`](crate::vmstate_fields).
-//!
-//! * direct equivalents to the C macros declared in
-//!   `include/migration/vmstate.h`. These are not type-safe and only provide
-//!   functionality that is missing from `vmstate_of!`.
-
-pub use std::convert::Infallible;
-use std::{
-    error::Error,
-    ffi::{c_int, c_void, CStr},
-    fmt, io,
-    marker::PhantomData,
-    mem,
-    ptr::{addr_of, NonNull},
-};
-
-use common::{
-    callbacks::FnCall,
-    errno::{into_neg_errno, Errno},
-    Zeroable,
-};
-
-use crate::bindings::{self, VMStateFlags};
-pub use crate::bindings::{MigrationPriority, VMStateField};
-
-/// This macro is used to call a function with a generic argument bound
-/// to the type of a field.  The function must take a
-/// [`PhantomData`]`<T>` argument; `T` is the type of
-/// field `$field` in the `$typ` type.
-///
-/// # Examples
-///
-/// ```
-/// # use qemu_api::call_func_with_field;
-/// # use core::marker::PhantomData;
-/// const fn size_of_field<T>(_: PhantomData<T>) -> usize {
-///     std::mem::size_of::<T>()
-/// }
-///
-/// struct Foo {
-///     x: u16,
-/// };
-/// // calls size_of_field::<u16>()
-/// assert_eq!(call_func_with_field!(size_of_field, Foo, x), 2);
-/// ```
-#[macro_export]
-macro_rules! call_func_with_field {
-    // Based on the answer by user steffahn (Frank Steffahn) at
-    // https://users.rust-lang.org/t/inferring-type-of-field/122857
-    // and used under MIT license
-    ($func:expr, $typ:ty, $($field:tt).+) => {
-        $func(loop {
-            #![allow(unreachable_code)]
-            const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> { ::core::marker::PhantomData }
-            // Unreachable code is exempt from checks on uninitialized values.
-            // Use that trick to infer the type of this PhantomData.
-            break ::core::marker::PhantomData;
-            break phantom__(&{ let value__: $typ; value__.$($field).+ });
-        })
-    };
-}
-
-/// A trait for types that can be included in a device's migration stream.  It
-/// provides the base contents of a `VMStateField` (minus the name and offset).
-///
-/// # Safety
-///
-/// The contents of this trait go straight into structs that are parsed by C
-/// code and used to introspect into other structs.  Generally, you don't need
-/// to implement it except via macros that do it for you, such as
-/// `impl_vmstate_bitsized!`.
-pub unsafe trait VMState {
-    /// The base contents of a `VMStateField` (minus the name and offset) for
-    /// the type that is implementing the trait.
-    const BASE: VMStateField;
-
-    /// A flag that is added to another field's `VMStateField` to specify the
-    /// length's type in a variable-sized array.  If this is not a supported
-    /// type for the length (i.e. if it is not `u8`, `u16`, `u32`), using it
-    /// in a call to [`vmstate_of!`](crate::vmstate_of) will cause a
-    /// compile-time error.
-    const VARRAY_FLAG: VMStateFlags = {
-        panic!("invalid type for variable-sized array");
-    };
-}
-
-/// Internal utility function to retrieve a type's `VMStateField`;
-/// used by [`vmstate_of!`](crate::vmstate_of).
-pub const fn vmstate_base<T: VMState>(_: PhantomData<T>) -> VMStateField {
-    T::BASE
-}
-
-/// Internal utility function to retrieve a type's `VMStateFlags` when it
-/// is used as the element count of a `VMSTATE_VARRAY`; used by
-/// [`vmstate_of!`](crate::vmstate_of).
-pub const fn vmstate_varray_flag<T: VMState>(_: PhantomData<T>) -> VMStateFlags {
-    T::VARRAY_FLAG
-}
-
-/// Return the `VMStateField` for a field of a struct.  The field must be
-/// visible in the current scope.
-///
-/// Only a limited set of types is supported out of the box:
-/// * scalar types (integer and `bool`)
-/// * the C struct `QEMUTimer`
-/// * a transparent wrapper for any of the above (`Cell`, `UnsafeCell`,
-///   [`BqlCell`](crate::cell::BqlCell),
-///   [`BqlRefCell`](crate::cell::BqlRefCell)),
-/// * a raw pointer to any of the above
-/// * a `NonNull` pointer, a `Box` or an [`Owned`](crate::qom::Owned) for any of
-///   the above
-/// * an array of any of the above
-///
-/// In order to support other types, the trait `VMState` must be implemented
-/// for them.  The macros [`impl_vmstate_forward`](crate::impl_vmstate_forward),
-/// [`impl_vmstate_bitsized`](crate::impl_vmstate_bitsized), and
-/// [`impl_vmstate_struct`](crate::impl_vmstate_struct) help with this.
-#[macro_export]
-macro_rules! vmstate_of {
-    ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:expr)?])? $(, $test_fn:expr)? $(,)?) => {
-        $crate::bindings::VMStateField {
-            name: ::core::concat!(::core::stringify!($field_name), "\0")
-                .as_bytes()
-                .as_ptr() as *const ::std::os::raw::c_char,
-            offset: ::std::mem::offset_of!($struct_name, $field_name),
-            $(num_offset: ::std::mem::offset_of!($struct_name, $num),)?
-            $(field_exists: $crate::vmstate_exist_fn!($struct_name, $test_fn),)?
-            // The calls to `call_func_with_field!` are the magic that
-            // computes most of the VMStateField from the type of the field.
-            ..$crate::call_func_with_field!(
-                $crate::vmstate::vmstate_base,
-                $struct_name,
-                $field_name
-            )$(.with_varray_flag($crate::call_func_with_field!(
-                    $crate::vmstate::vmstate_varray_flag,
-                    $struct_name,
-                    $num))
-               $(.with_varray_multiply($factor))?)?
-        }
-    };
-}
-
-impl VMStateFlags {
-    const VMS_VARRAY_FLAGS: VMStateFlags = VMStateFlags(
-        VMStateFlags::VMS_VARRAY_INT32.0
-            | VMStateFlags::VMS_VARRAY_UINT8.0
-            | VMStateFlags::VMS_VARRAY_UINT16.0
-            | VMStateFlags::VMS_VARRAY_UINT32.0,
-    );
-}
-
-// Add a couple builder-style methods to VMStateField, allowing
-// easy derivation of VMStateField constants from other types.
-impl VMStateField {
-    #[must_use]
-    pub const fn with_version_id(mut self, version_id: i32) -> Self {
-        assert!(version_id >= 0);
-        self.version_id = version_id;
-        self
-    }
-
-    #[must_use]
-    pub const fn with_array_flag(mut self, num: usize) -> Self {
-        assert!(num <= 0x7FFF_FFFFusize);
-        assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) == 0);
-        assert!((self.flags.0 & VMStateFlags::VMS_VARRAY_FLAGS.0) == 0);
-        if (self.flags.0 & VMStateFlags::VMS_POINTER.0) != 0 {
-            self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_POINTER.0);
-            self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0);
-            // VMS_ARRAY_OF_POINTER flag stores the size of pointer.
-            // FIXME: *const, *mut, NonNull and Box<> have the same size as usize.
-            //        Resize if more smart pointers are supported.
-            self.size = std::mem::size_of::<usize>();
-        }
-        self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_SINGLE.0);
-        self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY.0);
-        self.num = num as i32;
-        self
-    }
-
-    #[must_use]
-    pub const fn with_pointer_flag(mut self) -> Self {
-        assert!((self.flags.0 & VMStateFlags::VMS_POINTER.0) == 0);
-        self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_POINTER.0);
-        self
-    }
-
-    #[must_use]
-    pub const fn with_varray_flag_unchecked(mut self, flag: VMStateFlags) -> VMStateField {
-        self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_ARRAY.0);
-        self.flags = VMStateFlags(self.flags.0 | flag.0);
-        self.num = 0; // varray uses num_offset instead of num.
-        self
-    }
-
-    #[must_use]
-    #[allow(unused_mut)]
-    pub const fn with_varray_flag(mut self, flag: VMStateFlags) -> VMStateField {
-        assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) != 0);
-        self.with_varray_flag_unchecked(flag)
-    }
-
-    #[must_use]
-    pub const fn with_varray_multiply(mut self, num: u32) -> VMStateField {
-        assert!(num <= 0x7FFF_FFFFu32);
-        self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0);
-        self.num = num as i32;
-        self
-    }
-}
-
-/// This macro can be used (by just passing it a type) to forward the `VMState`
-/// trait to the first field of a tuple.  This is a workaround for lack of
-/// support of nested [`offset_of`](core::mem::offset_of) until Rust 1.82.0.
-///
-/// # Examples
-///
-/// ```
-/// # use qemu_api::impl_vmstate_forward;
-/// pub struct Fifo([u8; 16]);
-/// impl_vmstate_forward!(Fifo);
-/// ```
-#[macro_export]
-macro_rules! impl_vmstate_forward {
-    // This is similar to impl_vmstate_transparent below, but it
-    // uses the same trick as vmstate_of! to obtain the type of
-    // the first field of the tuple
-    ($tuple:ty) => {
-        unsafe impl $crate::vmstate::VMState for $tuple {
-            const BASE: $crate::bindings::VMStateField =
-                $crate::call_func_with_field!($crate::vmstate::vmstate_base, $tuple, 0);
-        }
-    };
-}
-
-// Transparent wrappers: just use the internal type
-
-#[macro_export]
-macro_rules! impl_vmstate_transparent {
-    ($type:ty where $base:tt: VMState $($where:tt)*) => {
-        unsafe impl<$base> $crate::vmstate::VMState for $type where $base: $crate::vmstate::VMState $($where)* {
-            const BASE: $crate::vmstate::VMStateField = $crate::vmstate::VMStateField {
-                size: mem::size_of::<$type>(),
-                ..<$base as $crate::vmstate::VMState>::BASE
-            };
-            const VARRAY_FLAG: $crate::bindings::VMStateFlags = <$base as $crate::vmstate::VMState>::VARRAY_FLAG;
-        }
-    };
-}
-
-impl_vmstate_transparent!(std::cell::Cell<T> where T: VMState);
-impl_vmstate_transparent!(std::cell::UnsafeCell<T> where T: VMState);
-impl_vmstate_transparent!(std::pin::Pin<T> where T: VMState);
-impl_vmstate_transparent!(::common::Opaque<T> where T: VMState);
-
-#[macro_export]
-macro_rules! impl_vmstate_bitsized {
-    ($type:ty) => {
-        unsafe impl $crate::vmstate::VMState for $type {
-            const BASE: $crate::bindings::VMStateField =
-                                        <<<$type as ::bilge::prelude::Bitsized>::ArbitraryInt
-                                          as ::bilge::prelude::Number>::UnderlyingType
-                                         as $crate::vmstate::VMState>::BASE;
-            const VARRAY_FLAG: $crate::bindings::VMStateFlags =
-                                        <<<$type as ::bilge::prelude::Bitsized>::ArbitraryInt
-                                          as ::bilge::prelude::Number>::UnderlyingType
-                                         as $crate::vmstate::VMState>::VARRAY_FLAG;
-        }
-    };
-}
-
-// Scalar types using predefined VMStateInfos
-
-macro_rules! impl_vmstate_scalar {
-    ($info:ident, $type:ty$(, $varray_flag:ident)?) => {
-        unsafe impl VMState for $type {
-            const BASE: VMStateField = VMStateField {
-                info: addr_of!(bindings::$info),
-                size: mem::size_of::<$type>(),
-                flags: VMStateFlags::VMS_SINGLE,
-                ..Zeroable::ZERO
-            };
-            $(const VARRAY_FLAG: VMStateFlags = VMStateFlags::$varray_flag;)?
-        }
-    };
-}
-
-impl_vmstate_scalar!(vmstate_info_bool, bool);
-impl_vmstate_scalar!(vmstate_info_int8, i8);
-impl_vmstate_scalar!(vmstate_info_int16, i16);
-impl_vmstate_scalar!(vmstate_info_int32, i32);
-impl_vmstate_scalar!(vmstate_info_int64, i64);
-impl_vmstate_scalar!(vmstate_info_uint8, u8, VMS_VARRAY_UINT8);
-impl_vmstate_scalar!(vmstate_info_uint16, u16, VMS_VARRAY_UINT16);
-impl_vmstate_scalar!(vmstate_info_uint32, u32, VMS_VARRAY_UINT32);
-impl_vmstate_scalar!(vmstate_info_uint64, u64);
-impl_vmstate_scalar!(vmstate_info_timer, util::timer::Timer);
-
-#[macro_export]
-macro_rules! impl_vmstate_c_struct {
-    ($type:ty, $vmsd:expr) => {
-        unsafe impl VMState for $type {
-            const BASE: $crate::bindings::VMStateField = $crate::bindings::VMStateField {
-                vmsd: ::std::ptr::addr_of!($vmsd),
-                size: ::std::mem::size_of::<$type>(),
-                flags: $crate::bindings::VMStateFlags::VMS_STRUCT,
-                ..common::zeroable::Zeroable::ZERO
-            };
-        }
-    };
-}
-
-// Pointer types using the underlying type's VMState plus VMS_POINTER
-// Note that references are not supported, though references to cells
-// could be allowed.
-
-#[macro_export]
-macro_rules! impl_vmstate_pointer {
-    ($type:ty where $base:tt: VMState $($where:tt)*) => {
-        unsafe impl<$base> $crate::vmstate::VMState for $type where $base: $crate::vmstate::VMState $($where)* {
-            const BASE: $crate::vmstate::VMStateField = <$base as $crate::vmstate::VMState>::BASE.with_pointer_flag();
-        }
-    };
-}
-
-impl_vmstate_pointer!(*const T where T: VMState);
-impl_vmstate_pointer!(*mut T where T: VMState);
-impl_vmstate_pointer!(NonNull<T> where T: VMState);
-
-// Unlike C pointers, Box is always non-null therefore there is no need
-// to specify VMS_ALLOC.
-impl_vmstate_pointer!(Box<T> where T: VMState);
-
-// Arrays using the underlying type's VMState plus
-// VMS_ARRAY/VMS_ARRAY_OF_POINTER
-
-unsafe impl<T: VMState, const N: usize> VMState for [T; N] {
-    const BASE: VMStateField = <T as VMState>::BASE.with_array_flag(N);
-}
-
-#[doc(alias = "VMSTATE_UNUSED")]
-#[macro_export]
-macro_rules! vmstate_unused {
-    ($size:expr) => {{
-        $crate::bindings::VMStateField {
-            name: c"unused".as_ptr(),
-            size: $size,
-            info: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate_info_unused_buffer) },
-            flags: $crate::bindings::VMStateFlags::VMS_BUFFER,
-            ..::common::Zeroable::ZERO
-        }
-    }};
-}
-
-pub extern "C" fn rust_vms_test_field_exists<T, F: for<'a> FnCall<(&'a T, u8), bool>>(
-    opaque: *mut c_void,
-    version_id: c_int,
-) -> bool {
-    // SAFETY: the function is used in T's implementation of VMState
-    let owner: &T = unsafe { &*(opaque.cast::<T>()) };
-    let version: u8 = version_id.try_into().unwrap();
-    F::call((owner, version))
-}
-
-pub type VMSFieldExistCb = unsafe extern "C" fn(
-    opaque: *mut std::os::raw::c_void,
-    version_id: std::os::raw::c_int,
-) -> bool;
-
-#[macro_export]
-macro_rules! vmstate_exist_fn {
-    ($struct_name:ty, $test_fn:expr) => {{
-        const fn test_cb_builder__<T, F: for<'a> ::common::callbacks::FnCall<(&'a T, u8), bool>>(
-            _phantom: ::core::marker::PhantomData<F>,
-        ) -> $crate::vmstate::VMSFieldExistCb {
-            const { assert!(F::IS_SOME) };
-            $crate::vmstate::rust_vms_test_field_exists::<T, F>
-        }
-
-        const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> {
-            ::core::marker::PhantomData
-        }
-        Some(test_cb_builder__::<$struct_name, _>(phantom__(&$test_fn)))
-    }};
-}
-
-/// Helper macro to declare a list of
-/// ([`VMStateField`](`crate::bindings::VMStateField`)) into a static and return
-/// a pointer to the array of values it created.
-#[macro_export]
-macro_rules! vmstate_fields {
-    ($($field:expr),*$(,)*) => {{
-        static _FIELDS: &[$crate::bindings::VMStateField] = &[
-            $($field),*,
-            $crate::bindings::VMStateField {
-                flags: $crate::bindings::VMStateFlags::VMS_END,
-                ..::common::zeroable::Zeroable::ZERO
-            }
-        ];
-        _FIELDS.as_ptr()
-    }}
-}
-
-#[doc(alias = "VMSTATE_VALIDATE")]
-#[macro_export]
-macro_rules! vmstate_validate {
-    ($struct_name:ty, $test_name:expr, $test_fn:expr $(,)?) => {
-        $crate::bindings::VMStateField {
-            name: ::std::ffi::CStr::as_ptr($test_name),
-            field_exists: $crate::vmstate_exist_fn!($struct_name, $test_fn),
-            flags: $crate::bindings::VMStateFlags(
-                $crate::bindings::VMStateFlags::VMS_MUST_EXIST.0
-                    | $crate::bindings::VMStateFlags::VMS_ARRAY.0,
-            ),
-            num: 0, // 0 elements: no data, only run test_fn callback
-            ..::common::zeroable::Zeroable::ZERO
-        }
-    };
-}
-
-/// Helper macro to allow using a struct in [`vmstate_of!`]
-///
-/// # Safety
-///
-/// The [`VMStateDescription`] constant `$vmsd` must be an accurate
-/// description of the struct.
-#[macro_export]
-macro_rules! impl_vmstate_struct {
-    ($type:ty, $vmsd:expr) => {
-        unsafe impl $crate::vmstate::VMState for $type {
-            const BASE: $crate::bindings::VMStateField = {
-                static VMSD: &$crate::bindings::VMStateDescription = $vmsd.as_ref();
-
-                $crate::bindings::VMStateField {
-                    vmsd: ::core::ptr::addr_of!(*VMSD),
-                    size: ::core::mem::size_of::<$type>(),
-                    flags: $crate::bindings::VMStateFlags::VMS_STRUCT,
-                    ..common::Zeroable::ZERO
-                }
-            };
-        }
-    };
-}
-
-/// A transparent wrapper type for the `subsections` field of
-/// [`VMStateDescription`].
-///
-/// This is necessary to be able to declare subsection descriptions as statics,
-/// because the only way to implement `Sync` for a foreign type (and `*const`
-/// pointers are foreign types in Rust) is to create a wrapper struct and
-/// `unsafe impl Sync` for it.
-///
-/// This struct is used in the
-/// [`vm_state_subsections`](crate::vmstate_subsections) macro implementation.
-#[repr(transparent)]
-pub struct VMStateSubsectionsWrapper(pub &'static [*const crate::bindings::VMStateDescription]);
-
-unsafe impl Sync for VMStateSubsectionsWrapper {}
-
-/// Helper macro to declare a list of subsections ([`VMStateDescription`])
-/// into a static and return a pointer to the array of pointers it created.
-#[macro_export]
-macro_rules! vmstate_subsections {
-    ($($subsection:expr),*$(,)*) => {{
-        static _SUBSECTIONS: $crate::vmstate::VMStateSubsectionsWrapper = $crate::vmstate::VMStateSubsectionsWrapper(&[
-            $({
-                static _SUBSECTION: $crate::bindings::VMStateDescription = $subsection.get();
-                ::core::ptr::addr_of!(_SUBSECTION)
-            }),*,
-            ::core::ptr::null()
-        ]);
-        &_SUBSECTIONS
-    }}
-}
-
-pub struct VMStateDescription<T>(bindings::VMStateDescription, PhantomData<fn(&T)>);
-
-// SAFETY: When a *const T is passed to the callbacks, the call itself
-// is done in a thread-safe manner.  The invocation is okay as long as
-// T itself is `Sync`.
-unsafe impl<T: Sync> Sync for VMStateDescription<T> {}
-
-#[derive(Clone)]
-pub struct VMStateDescriptionBuilder<T>(bindings::VMStateDescription, PhantomData<fn(&T)>);
-
-#[derive(Debug)]
-pub struct InvalidError;
-
-impl Error for InvalidError {}
-
-impl std::fmt::Display for InvalidError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "invalid migration data")
-    }
-}
-
-impl From<InvalidError> for Errno {
-    fn from(_value: InvalidError) -> Errno {
-        io::ErrorKind::InvalidInput.into()
-    }
-}
-
-unsafe extern "C" fn vmstate_no_version_cb<
-    T,
-    F: for<'a> FnCall<(&'a T,), Result<(), impl Into<Errno>>>,
->(
-    opaque: *mut c_void,
-) -> c_int {
-    // SAFETY: the function is used in T's implementation of VMState
-    let result = F::call((unsafe { &*(opaque.cast::<T>()) },));
-    into_neg_errno(result)
-}
-
-unsafe extern "C" fn vmstate_post_load_cb<
-    T,
-    F: for<'a> FnCall<(&'a T, u8), Result<(), impl Into<Errno>>>,
->(
-    opaque: *mut c_void,
-    version_id: c_int,
-) -> c_int {
-    // SAFETY: the function is used in T's implementation of VMState
-    let owner: &T = unsafe { &*(opaque.cast::<T>()) };
-    let version: u8 = version_id.try_into().unwrap();
-    let result = F::call((owner, version));
-    into_neg_errno(result)
-}
-
-unsafe extern "C" fn vmstate_needed_cb<T, F: for<'a> FnCall<(&'a T,), bool>>(
-    opaque: *mut c_void,
-) -> bool {
-    // SAFETY: the function is used in T's implementation of VMState
-    F::call((unsafe { &*(opaque.cast::<T>()) },))
-}
-
-unsafe extern "C" fn vmstate_dev_unplug_pending_cb<T, F: for<'a> FnCall<(&'a T,), bool>>(
-    opaque: *mut c_void,
-) -> bool {
-    // SAFETY: the function is used in T's implementation of VMState
-    F::call((unsafe { &*(opaque.cast::<T>()) },))
-}
-
-impl<T> VMStateDescriptionBuilder<T> {
-    #[must_use]
-    pub const fn name(mut self, name_str: &CStr) -> Self {
-        self.0.name = ::std::ffi::CStr::as_ptr(name_str);
-        self
-    }
-
-    #[must_use]
-    pub const fn unmigratable(mut self) -> Self {
-        self.0.unmigratable = true;
-        self
-    }
-
-    #[must_use]
-    pub const fn early_setup(mut self) -> Self {
-        self.0.early_setup = true;
-        self
-    }
-
-    #[must_use]
-    pub const fn version_id(mut self, version: u8) -> Self {
-        self.0.version_id = version as c_int;
-        self
-    }
-
-    #[must_use]
-    pub const fn minimum_version_id(mut self, min_version: u8) -> Self {
-        self.0.minimum_version_id = min_version as c_int;
-        self
-    }
-
-    #[must_use]
-    pub const fn priority(mut self, priority: MigrationPriority) -> Self {
-        self.0.priority = priority;
-        self
-    }
-
-    #[must_use]
-    pub const fn pre_load<F: for<'a> FnCall<(&'a T,), Result<(), impl Into<Errno>>>>(
-        mut self,
-        _f: &F,
-    ) -> Self {
-        self.0.pre_load = if F::IS_SOME {
-            Some(vmstate_no_version_cb::<T, F>)
-        } else {
-            None
-        };
-        self
-    }
-
-    #[must_use]
-    pub const fn post_load<F: for<'a> FnCall<(&'a T, u8), Result<(), impl Into<Errno>>>>(
-        mut self,
-        _f: &F,
-    ) -> Self {
-        self.0.post_load = if F::IS_SOME {
-            Some(vmstate_post_load_cb::<T, F>)
-        } else {
-            None
-        };
-        self
-    }
-
-    #[must_use]
-    pub const fn pre_save<F: for<'a> FnCall<(&'a T,), Result<(), impl Into<Errno>>>>(
-        mut self,
-        _f: &F,
-    ) -> Self {
-        self.0.pre_save = if F::IS_SOME {
-            Some(vmstate_no_version_cb::<T, F>)
-        } else {
-            None
-        };
-        self
-    }
-
-    #[must_use]
-    pub const fn post_save<F: for<'a> FnCall<(&'a T,), Result<(), impl Into<Errno>>>>(
-        mut self,
-        _f: &F,
-    ) -> Self {
-        self.0.post_save = if F::IS_SOME {
-            Some(vmstate_no_version_cb::<T, F>)
-        } else {
-            None
-        };
-        self
-    }
-
-    #[must_use]
-    pub const fn needed<F: for<'a> FnCall<(&'a T,), bool>>(mut self, _f: &F) -> Self {
-        self.0.needed = if F::IS_SOME {
-            Some(vmstate_needed_cb::<T, F>)
-        } else {
-            None
-        };
-        self
-    }
-
-    #[must_use]
-    pub const fn unplug_pending<F: for<'a> FnCall<(&'a T,), bool>>(mut self, _f: &F) -> Self {
-        self.0.dev_unplug_pending = if F::IS_SOME {
-            Some(vmstate_dev_unplug_pending_cb::<T, F>)
-        } else {
-            None
-        };
-        self
-    }
-
-    #[must_use]
-    pub const fn fields(mut self, fields: *const VMStateField) -> Self {
-        self.0.fields = fields;
-        self
-    }
-
-    #[must_use]
-    pub const fn subsections(mut self, subs: &'static VMStateSubsectionsWrapper) -> Self {
-        self.0.subsections = subs.0.as_ptr();
-        self
-    }
-
-    #[must_use]
-    pub const fn build(self) -> VMStateDescription<T> {
-        VMStateDescription::<T>(self.0, PhantomData)
-    }
-
-    #[must_use]
-    pub const fn new() -> Self {
-        Self(bindings::VMStateDescription::ZERO, PhantomData)
-    }
-}
-
-impl<T> Default for VMStateDescriptionBuilder<T> {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
-impl<T> VMStateDescription<T> {
-    pub const fn get(&self) -> bindings::VMStateDescription {
-        self.0
-    }
-
-    pub const fn as_ref(&self) -> &bindings::VMStateDescription {
-        &self.0
-    }
-}
diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs
index 70ef4a80d5..92e3534d3c 100644
--- a/rust/qemu-api/tests/tests.rs
+++ b/rust/qemu-api/tests/tests.rs
@@ -4,13 +4,13 @@
 
 use std::{ffi::CStr, ptr::addr_of};
 
+use migration::{VMStateDescription, VMStateDescriptionBuilder};
 use qemu_api::{
     cell::{self, BqlCell},
     prelude::*,
     qdev::{DeviceImpl, DeviceState, ResettablePhasesImpl},
     qom::{ObjectImpl, ParentField},
     sysbus::SysBusDevice,
-    vmstate::{VMStateDescription, VMStateDescriptionBuilder},
 };
 use util::bindings::{module_call_init, module_init_type};
 
diff --git a/rust/qemu-api/tests/vmstate_tests.rs b/rust/qemu-api/tests/vmstate_tests.rs
index d9e5bcc498..47fc15149b 100644
--- a/rust/qemu-api/tests/vmstate_tests.rs
+++ b/rust/qemu-api/tests/vmstate_tests.rs
@@ -10,16 +10,16 @@ use std::{
 };
 
 use common::Opaque;
-use qemu_api::{
+use migration::{
     bindings::{
         vmstate_info_bool, vmstate_info_int32, vmstate_info_int64, vmstate_info_int8,
         vmstate_info_uint64, vmstate_info_uint8, vmstate_info_unused_buffer, VMStateFlags,
     },
-    cell::BqlCell,
     impl_vmstate_forward, impl_vmstate_struct,
     vmstate::{VMStateDescription, VMStateDescriptionBuilder, VMStateField},
     vmstate_fields, vmstate_of, vmstate_unused, vmstate_validate,
 };
+use qemu_api::cell::BqlCell;
 
 const FOO_ARRAY_MAX: usize = 3;
 
diff --git a/rust/qemu-api/wrapper.h b/rust/qemu-api/wrapper.h
index cc7112406b..b99df9f568 100644
--- a/rust/qemu-api/wrapper.h
+++ b/rust/qemu-api/wrapper.h
@@ -58,7 +58,6 @@ typedef enum memory_order {
 #include "hw/qdev-properties.h"
 #include "hw/qdev-properties-system.h"
 #include "hw/irq.h"
-#include "migration/vmstate.h"
 #include "chardev/char-serial.h"
 #include "exec/memattrs.h"
 #include "system/address-spaces.h"