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
