rust: vmstate: use const_refs_to_static

The VMStateDescriptionBuilder already needs const_refs_static, so
use it to remove the need for vmstate_clock! and vmstate_struct!,
as well as to simplify the implementation for scalars.

If the consts in the VMState trait can reference to static
VMStateDescription, scalars do not need the info_enum_to_ref!
indirection and structs can implement the VMState trait themselves.

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Link: https://lore.kernel.org/r/20250908105005.2119297-9-pbonzini@redhat.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2025-09-08 12:49:40 +02:00
parent 7da9ee9207
commit dcdee1e718
6 changed files with 113 additions and 217 deletions

View file

@ -15,9 +15,9 @@ use qemu_api::{
vmstate_info_uint64, vmstate_info_uint8, vmstate_info_unused_buffer, VMStateFlags,
},
cell::{BqlCell, Opaque},
impl_vmstate_forward,
impl_vmstate_forward, impl_vmstate_struct,
vmstate::{VMStateDescription, VMStateDescriptionBuilder, VMStateField},
vmstate_fields, vmstate_of, vmstate_struct, vmstate_unused, vmstate_validate,
vmstate_fields, vmstate_of, vmstate_unused, vmstate_validate,
};
const FOO_ARRAY_MAX: usize = 3;
@ -52,6 +52,8 @@ static VMSTATE_FOOA: VMStateDescription<FooA> = VMStateDescriptionBuilder::<FooA
})
.build();
impl_vmstate_struct!(FooA, VMSTATE_FOOA);
#[test]
fn test_vmstate_uint16() {
let foo_fields: &[VMStateField] =
@ -173,20 +175,19 @@ fn validate_foob(_state: &FooB, _version_id: u8) -> bool {
true
}
static VMSTATE_FOOB: VMStateDescription<FooB> =
VMStateDescriptionBuilder::<FooB>::new()
.name(c"foo_b")
.version_id(2)
.minimum_version_id(1)
.fields(vmstate_fields! {
vmstate_of!(FooB, val).with_version_id(2),
vmstate_of!(FooB, wrap),
vmstate_struct!(FooB, arr_a[0 .. num_a], &VMSTATE_FOOA, FooA).with_version_id(1),
vmstate_struct!(FooB, arr_a_mul[0 .. num_a_mul * 32], &VMSTATE_FOOA, FooA).with_version_id(2),
vmstate_of!(FooB, arr_i64),
vmstate_struct!(FooB, arr_a_wrap[0 .. num_a_wrap], &VMSTATE_FOOA, FooA, validate_foob),
})
.build();
static VMSTATE_FOOB: VMStateDescription<FooB> = VMStateDescriptionBuilder::<FooB>::new()
.name(c"foo_b")
.version_id(2)
.minimum_version_id(1)
.fields(vmstate_fields! {
vmstate_of!(FooB, val).with_version_id(2),
vmstate_of!(FooB, wrap),
vmstate_of!(FooB, arr_a[0 .. num_a]).with_version_id(1),
vmstate_of!(FooB, arr_a_mul[0 .. num_a_mul * 32]).with_version_id(2),
vmstate_of!(FooB, arr_i64),
vmstate_of!(FooB, arr_a_wrap[0 .. num_a_wrap], validate_foob),
})
.build();
#[test]
fn test_vmstate_bool_v() {
@ -351,9 +352,7 @@ static VMSTATE_FOOC: VMStateDescription<FooC> = VMStateDescriptionBuilder::<FooC
.minimum_version_id(1)
.fields(vmstate_fields! {
vmstate_of!(FooC, ptr).with_version_id(2),
// FIXME: Currently vmstate_struct doesn't support the pointer to structure.
// VMSTATE_STRUCT_POINTER: vmstate_struct!(FooC, ptr_a, VMSTATE_FOOA, NonNull<FooA>)
vmstate_unused!(size_of::<NonNull<FooA>>()),
vmstate_of!(FooC, ptr_a),
vmstate_of!(FooC, arr_ptr),
vmstate_of!(FooC, arr_ptr_wrap),
})
@ -385,6 +384,31 @@ fn test_vmstate_pointer() {
assert!(foo_fields[0].field_exists.is_none());
}
#[test]
fn test_vmstate_struct_pointer() {
let foo_fields: &[VMStateField] =
unsafe { slice::from_raw_parts(VMSTATE_FOOC.as_ref().fields, 6) };
// 2st VMStateField ("ptr_a") in VMSTATE_FOOC (corresponding to
// VMSTATE_STRUCT_POINTER)
assert_eq!(
unsafe { CStr::from_ptr(foo_fields[1].name) }.to_bytes_with_nul(),
b"ptr_a\0"
);
assert_eq!(foo_fields[1].offset, PTR_SIZE);
assert_eq!(foo_fields[1].num_offset, 0);
assert_eq!(foo_fields[1].vmsd, VMSTATE_FOOA.as_ref());
assert_eq!(foo_fields[1].version_id, 0);
assert_eq!(foo_fields[1].size, size_of::<FooA>());
assert_eq!(foo_fields[1].num, 0);
assert_eq!(
foo_fields[1].flags.0,
VMStateFlags::VMS_STRUCT.0 | VMStateFlags::VMS_POINTER.0
);
assert!(foo_fields[1].info.is_null());
assert!(foo_fields[1].field_exists.is_none());
}
#[test]
fn test_vmstate_macro_array_of_pointer() {
let foo_fields: &[VMStateField] =
@ -444,8 +468,7 @@ fn test_vmstate_macro_array_of_pointer_wrapped() {
// * VMSTATE_FOOD:
// - VMSTATE_VALIDATE
// Add more member fields when vmstate_of/vmstate_struct support "test"
// parameter.
// Add more member fields when vmstate_of support "test" parameter.
struct FooD;
impl FooD {