On 11/3/25 16:49, Zhao Liu wrote:
did you miss something like the following?


diff --git a/rust/qemu-macros/src/migration_state.rs 
b/rust/qemu-macros/src/migration_state.rs
index 5edf0efe687f..2064bb73a6f0 100644
--- a/rust/qemu-macros/src/migration_state.rs
+++ b/rust/qemu-macros/src/migration_state.rs
@@ -236,6 +236,16 @@ pub struct #name {
          }
      }

+    fn generate_vmstate_impl(&self) -> TokenStream {
+        let name = self.migration_state_name();
+
+        quote! {
+            unsafe impl ::migration::VMState for #name {
+                const BASE: ::migration::VMStateField = 
::common::Zeroable::ZERO;

It seems the generated migration_state_struct needs a complete VMSD:
collect all its fields and build a VMSD.

And then apply impl_vmstate_struct! to this  migration_state_struct.

If we zero the BASE, then `vmstate_of!(Self, migration_state)` seems
can't migrate its fields.

The VMStateDescription for the inner struct is indeed missing, but you need to write it yourself and apply impl_vmstate_struct, because the derive macro cannot know the checks or version_ids for each field, or the subsections.

The VMStateDescription for Migratable<> however is automatic (of course), and the outer VMStateDescription for the device is simple---it consists only of the parent class if applicable, and the Migratable<>, similar to VMSTATE_PL011.

For HPET, you'll have to move the subsections from VMSTATE_HPET to the inner VMState.

Paolo


Reply via email to