1*19985021SZhao Liu // Copyright (C) 2025 Intel Corporation. 2*19985021SZhao Liu // Author(s): Zhao Liu <zhai1.liu@intel.com> 3*19985021SZhao Liu // SPDX-License-Identifier: GPL-2.0-or-later 4*19985021SZhao Liu 5*19985021SZhao Liu use std::{ffi::CStr, mem::size_of, slice}; 6*19985021SZhao Liu 7*19985021SZhao Liu use qemu_api::{ 8*19985021SZhao Liu bindings::{vmstate_info_int8, vmstate_info_uint8, vmstate_info_unused_buffer, VMStateFlags}, 9*19985021SZhao Liu c_str, 10*19985021SZhao Liu vmstate::{VMStateDescription, VMStateField}, 11*19985021SZhao Liu vmstate_fields, vmstate_of, vmstate_unused, 12*19985021SZhao Liu zeroable::Zeroable, 13*19985021SZhao Liu }; 14*19985021SZhao Liu 15*19985021SZhao Liu const FOO_ARRAY_MAX: usize = 3; 16*19985021SZhao Liu 17*19985021SZhao Liu // =========================== Test VMSTATE_FOOA =========================== 18*19985021SZhao Liu // Test the use cases of the vmstate macro, corresponding to the following C 19*19985021SZhao Liu // macro variants: 20*19985021SZhao Liu // * VMSTATE_FOOA: 21*19985021SZhao Liu // - VMSTATE_U16 22*19985021SZhao Liu // - VMSTATE_UNUSED 23*19985021SZhao Liu // - VMSTATE_VARRAY_UINT16_UNSAFE 24*19985021SZhao Liu // - VMSTATE_VARRAY_MULTIPLY 25*19985021SZhao Liu #[repr(C)] 26*19985021SZhao Liu #[derive(qemu_api_macros::offsets)] 27*19985021SZhao Liu struct FooA { 28*19985021SZhao Liu arr: [u8; FOO_ARRAY_MAX], 29*19985021SZhao Liu num: u16, 30*19985021SZhao Liu arr_mul: [i8; FOO_ARRAY_MAX], 31*19985021SZhao Liu num_mul: u32, 32*19985021SZhao Liu elem: i8, 33*19985021SZhao Liu } 34*19985021SZhao Liu 35*19985021SZhao Liu static VMSTATE_FOOA: VMStateDescription = VMStateDescription { 36*19985021SZhao Liu name: c_str!("foo_a").as_ptr(), 37*19985021SZhao Liu version_id: 1, 38*19985021SZhao Liu minimum_version_id: 1, 39*19985021SZhao Liu fields: vmstate_fields! { 40*19985021SZhao Liu vmstate_of!(FooA, elem), 41*19985021SZhao Liu vmstate_unused!(size_of::<i64>()), 42*19985021SZhao Liu vmstate_of!(FooA, arr[0 .. num]).with_version_id(0), 43*19985021SZhao Liu vmstate_of!(FooA, arr_mul[0 .. num_mul * 16]), 44*19985021SZhao Liu }, 45*19985021SZhao Liu ..Zeroable::ZERO 46*19985021SZhao Liu }; 47*19985021SZhao Liu 48*19985021SZhao Liu #[test] 49*19985021SZhao Liu fn test_vmstate_uint16() { 50*19985021SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOA.fields, 5) }; 51*19985021SZhao Liu 52*19985021SZhao Liu // 1st VMStateField ("elem") in VMSTATE_FOOA (corresponding to VMSTATE_UINT16) 53*19985021SZhao Liu assert_eq!( 54*19985021SZhao Liu unsafe { CStr::from_ptr(foo_fields[0].name) }.to_bytes_with_nul(), 55*19985021SZhao Liu b"elem\0" 56*19985021SZhao Liu ); 57*19985021SZhao Liu assert_eq!(foo_fields[0].offset, 16); 58*19985021SZhao Liu assert_eq!(foo_fields[0].num_offset, 0); 59*19985021SZhao Liu assert_eq!(foo_fields[0].info, unsafe { &vmstate_info_int8 }); 60*19985021SZhao Liu assert_eq!(foo_fields[0].version_id, 0); 61*19985021SZhao Liu assert_eq!(foo_fields[0].size, 1); 62*19985021SZhao Liu assert_eq!(foo_fields[0].num, 0); 63*19985021SZhao Liu assert_eq!(foo_fields[0].flags, VMStateFlags::VMS_SINGLE); 64*19985021SZhao Liu assert!(foo_fields[0].vmsd.is_null()); 65*19985021SZhao Liu assert!(foo_fields[0].field_exists.is_none()); 66*19985021SZhao Liu } 67*19985021SZhao Liu 68*19985021SZhao Liu #[test] 69*19985021SZhao Liu fn test_vmstate_unused() { 70*19985021SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOA.fields, 5) }; 71*19985021SZhao Liu 72*19985021SZhao Liu // 2nd VMStateField ("unused") in VMSTATE_FOOA (corresponding to VMSTATE_UNUSED) 73*19985021SZhao Liu assert_eq!( 74*19985021SZhao Liu unsafe { CStr::from_ptr(foo_fields[1].name) }.to_bytes_with_nul(), 75*19985021SZhao Liu b"unused\0" 76*19985021SZhao Liu ); 77*19985021SZhao Liu assert_eq!(foo_fields[1].offset, 0); 78*19985021SZhao Liu assert_eq!(foo_fields[1].num_offset, 0); 79*19985021SZhao Liu assert_eq!(foo_fields[1].info, unsafe { &vmstate_info_unused_buffer }); 80*19985021SZhao Liu assert_eq!(foo_fields[1].version_id, 0); 81*19985021SZhao Liu assert_eq!(foo_fields[1].size, 8); 82*19985021SZhao Liu assert_eq!(foo_fields[1].num, 0); 83*19985021SZhao Liu assert_eq!(foo_fields[1].flags, VMStateFlags::VMS_BUFFER); 84*19985021SZhao Liu assert!(foo_fields[1].vmsd.is_null()); 85*19985021SZhao Liu assert!(foo_fields[1].field_exists.is_none()); 86*19985021SZhao Liu } 87*19985021SZhao Liu 88*19985021SZhao Liu #[test] 89*19985021SZhao Liu fn test_vmstate_varray_uint16_unsafe() { 90*19985021SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOA.fields, 5) }; 91*19985021SZhao Liu 92*19985021SZhao Liu // 3rd VMStateField ("arr") in VMSTATE_FOOA (corresponding to 93*19985021SZhao Liu // VMSTATE_VARRAY_UINT16_UNSAFE) 94*19985021SZhao Liu assert_eq!( 95*19985021SZhao Liu unsafe { CStr::from_ptr(foo_fields[2].name) }.to_bytes_with_nul(), 96*19985021SZhao Liu b"arr\0" 97*19985021SZhao Liu ); 98*19985021SZhao Liu assert_eq!(foo_fields[2].offset, 0); 99*19985021SZhao Liu assert_eq!(foo_fields[2].num_offset, 4); 100*19985021SZhao Liu assert_eq!(foo_fields[2].info, unsafe { &vmstate_info_uint8 }); 101*19985021SZhao Liu assert_eq!(foo_fields[2].version_id, 0); 102*19985021SZhao Liu assert_eq!(foo_fields[2].size, 1); 103*19985021SZhao Liu assert_eq!(foo_fields[2].num, 0); 104*19985021SZhao Liu assert_eq!(foo_fields[2].flags, VMStateFlags::VMS_VARRAY_UINT16); 105*19985021SZhao Liu assert!(foo_fields[2].vmsd.is_null()); 106*19985021SZhao Liu assert!(foo_fields[2].field_exists.is_none()); 107*19985021SZhao Liu } 108*19985021SZhao Liu 109*19985021SZhao Liu #[test] 110*19985021SZhao Liu fn test_vmstate_varray_multiply() { 111*19985021SZhao Liu let foo_fields: &[VMStateField] = unsafe { slice::from_raw_parts(VMSTATE_FOOA.fields, 5) }; 112*19985021SZhao Liu 113*19985021SZhao Liu // 4th VMStateField ("arr_mul") in VMSTATE_FOOA (corresponding to 114*19985021SZhao Liu // VMSTATE_VARRAY_MULTIPLY) 115*19985021SZhao Liu assert_eq!( 116*19985021SZhao Liu unsafe { CStr::from_ptr(foo_fields[3].name) }.to_bytes_with_nul(), 117*19985021SZhao Liu b"arr_mul\0" 118*19985021SZhao Liu ); 119*19985021SZhao Liu assert_eq!(foo_fields[3].offset, 6); 120*19985021SZhao Liu assert_eq!(foo_fields[3].num_offset, 12); 121*19985021SZhao Liu assert_eq!(foo_fields[3].info, unsafe { &vmstate_info_int8 }); 122*19985021SZhao Liu assert_eq!(foo_fields[3].version_id, 0); 123*19985021SZhao Liu assert_eq!(foo_fields[3].size, 1); 124*19985021SZhao Liu assert_eq!(foo_fields[3].num, 16); 125*19985021SZhao Liu assert_eq!( 126*19985021SZhao Liu foo_fields[3].flags.0, 127*19985021SZhao Liu VMStateFlags::VMS_VARRAY_UINT32.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0 128*19985021SZhao Liu ); 129*19985021SZhao Liu assert!(foo_fields[3].vmsd.is_null()); 130*19985021SZhao Liu assert!(foo_fields[3].field_exists.is_none()); 131*19985021SZhao Liu 132*19985021SZhao Liu // The last VMStateField in VMSTATE_FOOA. 133*19985021SZhao Liu assert_eq!(foo_fields[4].flags, VMStateFlags::VMS_END); 134*19985021SZhao Liu } 135