diff options
Diffstat (limited to 'rust/qemu-api')
| -rw-r--r-- | rust/qemu-api/.gitignore | 2 | ||||
| -rw-r--r-- | rust/qemu-api/Cargo.toml | 28 | ||||
| -rw-r--r-- | rust/qemu-api/README.md | 19 | ||||
| l--------- | rust/qemu-api/build.rs | 1 | ||||
| -rw-r--r-- | rust/qemu-api/meson.build | 75 | ||||
| -rw-r--r-- | rust/qemu-api/src/bindings.rs | 33 | ||||
| -rw-r--r-- | rust/qemu-api/src/lib.rs | 18 | ||||
| -rw-r--r-- | rust/qemu-api/src/prelude.rs | 5 | ||||
| -rw-r--r-- | rust/qemu-api/tests/vmstate_tests.rs | 541 | ||||
| -rw-r--r-- | rust/qemu-api/wrapper.h | 53 |
10 files changed, 0 insertions, 775 deletions
diff --git a/rust/qemu-api/.gitignore b/rust/qemu-api/.gitignore deleted file mode 100644 index df6c2163e0..0000000000 --- a/rust/qemu-api/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# Ignore generated bindings file overrides. -/src/bindings.inc.rs diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml deleted file mode 100644 index 9abb88aa1f..0000000000 --- a/rust/qemu-api/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "qemu_api" -version = "0.1.0" -authors = ["Manos Pitsidianakis <manos.pitsidianakis@linaro.org>"] -description = "Rust bindings for QEMU" -readme = "README.md" -resolver = "2" -publish = false - -edition.workspace = true -homepage.workspace = true -license.workspace = true -repository.workspace = true -rust-version.workspace = true - -[dependencies] -common = { path = "../common" } -chardev = { path = "../chardev" } -hwcore = { path = "../hw/core" } -migration = { path = "../migration" } -util = { path = "../util" } -bql = { path = "../bql" } -qemu_macros = { path = "../qemu-macros" } -qom = { path = "../qom" } -system = { path = "../system" } - -[lints] -workspace = true diff --git a/rust/qemu-api/README.md b/rust/qemu-api/README.md deleted file mode 100644 index ed1b7ab263..0000000000 --- a/rust/qemu-api/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# QEMU bindings and API wrappers - -This library exports helper Rust types, Rust macros and C FFI bindings for internal QEMU APIs. - -The C bindings can be generated with `bindgen`, using this build target: - -```console -$ make bindings.inc.rs -``` - -## Generate Rust documentation - -Common Cargo tasks can be performed from the QEMU build directory - -```console -$ make clippy -$ make rustfmt -$ make rustdoc -``` diff --git a/rust/qemu-api/build.rs b/rust/qemu-api/build.rs deleted file mode 120000 index 71a3167885..0000000000 --- a/rust/qemu-api/build.rs +++ /dev/null @@ -1 +0,0 @@ -../util/build.rs \ No newline at end of file diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build deleted file mode 100644 index fe81f16d99..0000000000 --- a/rust/qemu-api/meson.build +++ /dev/null @@ -1,75 +0,0 @@ -_qemu_api_cfg = run_command(rustc_args, - '--config-headers', config_host_h, '--features', files('Cargo.toml'), - capture: true, check: true).stdout().strip().splitlines() - -c_enums = [ - 'MemoryDeviceInfoKind', -] -_qemu_api_bindgen_args = [] -foreach enum : c_enums - _qemu_api_bindgen_args += ['--rustified-enum', enum] -endforeach - -blocked_type = [ - 'Chardev', - 'Error', - 'MemTxAttrs', - 'MemoryRegion', - 'ObjectClass', - 'VMStateDescription', - 'device_endian', -] -foreach type: blocked_type - _qemu_api_bindgen_args += ['--blocklist-type', type] -endforeach - -# TODO: Remove this comment when the clang/libclang mismatch issue is solved. -# -# Rust bindings generation with `bindgen` might fail in some cases where the -# detected `libclang` does not match the expected `clang` version/target. In -# this case you must pass the path to `clang` and `libclang` to your build -# command invocation using the environment variables CLANG_PATH and -# LIBCLANG_PATH -_qemu_api_bindings_inc_rs = rust.bindgen( - input: 'wrapper.h', - dependencies: common_ss.all_dependencies(), - output: 'bindings.inc.rs', - include_directories: bindings_incdir, - bindgen_version: ['>=0.60.0'], - args: bindgen_args_common + _qemu_api_bindgen_args, - ) - -_qemu_api_rs = static_library( - 'qemu_api', - structured_sources( - [ - 'src/lib.rs', - 'src/bindings.rs', - 'src/prelude.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, bql_rs, chardev_rs, common_rs, foreign_rs, hwcore_rs, libc_rs, migration_rs, qemu_macros, - qom_rs, system_rs, util_rs, hwcore], -) - -qemu_api_rs = declare_dependency(link_with: [_qemu_api_rs], - dependencies: [qemu_macros, qom, hwcore, chardev, migration]) - -test('rust-qemu-api-integration', - executable( - 'rust-qemu-api-integration', - files('tests/vmstate_tests.rs'), - override_options: ['rust_std=2021', 'build.rust_std=2021'], - rust_args: ['--test'], - install: false, - dependencies: [bql_rs, common_rs, util_rs, migration_rs, qom_rs, qemu_api_rs]), - args: [ - '--test', '--test-threads', '1', - '--format', 'pretty', - ], - protocol: 'rust', - suite: ['unit', 'rust']) diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs deleted file mode 100644 index 9c863e9b5b..0000000000 --- a/rust/qemu-api/src/bindings.rs +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -#![allow( - dead_code, - improper_ctypes_definitions, - improper_ctypes, - non_camel_case_types, - non_snake_case, - non_upper_case_globals, - unnecessary_transmutes, - unsafe_op_in_unsafe_fn, - clippy::pedantic, - clippy::restriction, - clippy::style, - clippy::missing_const_for_fn, - clippy::ptr_offset_with_cast, - clippy::useless_transmute, - clippy::missing_safety_doc, - clippy::too_many_arguments -)] - -//! `bindgen`-generated declarations. - -use chardev::bindings::Chardev; -use migration::bindings::VMStateDescription; -use qom::bindings::ObjectClass; -use system::bindings::{device_endian, MemTxAttrs, MemoryRegion}; -use util::bindings::Error; - -#[cfg(MESON)] -include!("bindings.inc.rs"); - -#[cfg(not(MESON))] -include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs deleted file mode 100644 index 21b886035f..0000000000 --- a/rust/qemu-api/src/lib.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2024, Linaro Limited -// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> -// SPDX-License-Identifier: GPL-2.0-or-later - -#![cfg_attr(not(MESON), doc = include_str!("../README.md"))] -#![deny(clippy::missing_const_for_fn)] - -#[rustfmt::skip] -pub mod bindings; - -// preserve one-item-per-"use" syntax, it is clearer -// for prelude-like modules -#[rustfmt::skip] -pub mod prelude; - -// Allow proc-macros to refer to `::qemu_api` inside the `qemu_api` crate (this -// crate). -extern crate self as qemu_api; diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs deleted file mode 100644 index 8db56f9f81..0000000000 --- a/rust/qemu-api/src/prelude.rs +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2024 Red Hat, Inc. -// Author(s): Paolo Bonzini <pbonzini@redhat.com> -// SPDX-License-Identifier: GPL-2.0-or-later - -//! Commonly used traits and types for QEMU. diff --git a/rust/qemu-api/tests/vmstate_tests.rs b/rust/qemu-api/tests/vmstate_tests.rs deleted file mode 100644 index fa9bbd6a12..0000000000 --- a/rust/qemu-api/tests/vmstate_tests.rs +++ /dev/null @@ -1,541 +0,0 @@ -// Copyright (C) 2025 Intel Corporation. -// Author(s): Zhao Liu <zhao1.liu@intel.com> -// SPDX-License-Identifier: GPL-2.0-or-later - -use std::{ - ffi::{c_void, CStr}, - mem::size_of, - ptr::NonNull, - slice, -}; - -use bql::BqlCell; -use common::Opaque; -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, - }, - impl_vmstate_forward, impl_vmstate_struct, - vmstate::{VMStateDescription, VMStateDescriptionBuilder, VMStateField}, - vmstate_fields, vmstate_of, vmstate_unused, vmstate_validate, -}; - -const FOO_ARRAY_MAX: usize = 3; - -// =========================== Test VMSTATE_FOOA =========================== -// Test the use cases of the vmstate macro, corresponding to the following C -// macro variants: -// * VMSTATE_FOOA: -// - VMSTATE_U16 -// - VMSTATE_UNUSED -// - VMSTATE_VARRAY_UINT16_UNSAFE -// - VMSTATE_VARRAY_MULTIPLY -#[repr(C)] -#[derive(Default)] -struct FooA { - arr: [u8; FOO_ARRAY_MAX], - num: u16, - arr_mul: [i8; FOO_ARRAY_MAX], - num_mul: u32, - elem: i8, -} - -static VMSTATE_FOOA: VMStateDescription<FooA> = VMStateDescriptionBuilder::<FooA>::new() - .name(c"foo_a") - .version_id(1) - .minimum_version_id(1) - .fields(vmstate_fields! { - vmstate_of!(FooA, elem), - vmstate_unused!(size_of::<i64>()), - vmstate_of!(FooA, arr[0 .. num]).with_version_id(0), - vmstate_of!(FooA, arr_mul[0 .. num_mul * 16]), - }) - .build(); - -impl_vmstate_struct!(FooA, VMSTATE_FOOA); - -#[test] -fn test_vmstate_uint16() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOA.as_ref().fields, 5) }; - - // 1st VMStateField ("elem") in VMSTATE_FOOA (corresponding to VMSTATE_UINT16) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[0].name) }.to_bytes_with_nul(), - b"elem\0" - ); - assert_eq!(foo_fields[0].offset, 16); - assert_eq!(foo_fields[0].num_offset, 0); - assert_eq!(foo_fields[0].info, unsafe { &vmstate_info_int8 }); - assert_eq!(foo_fields[0].version_id, 0); - assert_eq!(foo_fields[0].size, 1); - assert_eq!(foo_fields[0].num, 0); - assert_eq!(foo_fields[0].flags, VMStateFlags::VMS_SINGLE); - assert!(foo_fields[0].vmsd.is_null()); - assert!(foo_fields[0].field_exists.is_none()); -} - -#[test] -fn test_vmstate_unused() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOA.as_ref().fields, 5) }; - - // 2nd VMStateField ("unused") in VMSTATE_FOOA (corresponding to VMSTATE_UNUSED) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[1].name) }.to_bytes_with_nul(), - b"unused\0" - ); - assert_eq!(foo_fields[1].offset, 0); - assert_eq!(foo_fields[1].num_offset, 0); - assert_eq!(foo_fields[1].info, unsafe { &vmstate_info_unused_buffer }); - assert_eq!(foo_fields[1].version_id, 0); - assert_eq!(foo_fields[1].size, 8); - assert_eq!(foo_fields[1].num, 0); - assert_eq!(foo_fields[1].flags, VMStateFlags::VMS_BUFFER); - assert!(foo_fields[1].vmsd.is_null()); - assert!(foo_fields[1].field_exists.is_none()); -} - -#[test] -fn test_vmstate_varray_uint16_unsafe() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOA.as_ref().fields, 5) }; - - // 3rd VMStateField ("arr") in VMSTATE_FOOA (corresponding to - // VMSTATE_VARRAY_UINT16_UNSAFE) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[2].name) }.to_bytes_with_nul(), - b"arr\0" - ); - assert_eq!(foo_fields[2].offset, 0); - assert_eq!(foo_fields[2].num_offset, 4); - assert_eq!(foo_fields[2].info, unsafe { &vmstate_info_uint8 }); - assert_eq!(foo_fields[2].version_id, 0); - assert_eq!(foo_fields[2].size, 1); - assert_eq!(foo_fields[2].num, 0); - assert_eq!(foo_fields[2].flags, VMStateFlags::VMS_VARRAY_UINT16); - assert!(foo_fields[2].vmsd.is_null()); - assert!(foo_fields[2].field_exists.is_none()); -} - -#[test] -fn test_vmstate_varray_multiply() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOA.as_ref().fields, 5) }; - - // 4th VMStateField ("arr_mul") in VMSTATE_FOOA (corresponding to - // VMSTATE_VARRAY_MULTIPLY) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[3].name) }.to_bytes_with_nul(), - b"arr_mul\0" - ); - assert_eq!(foo_fields[3].offset, 6); - assert_eq!(foo_fields[3].num_offset, 12); - assert_eq!(foo_fields[3].info, unsafe { &vmstate_info_int8 }); - assert_eq!(foo_fields[3].version_id, 0); - assert_eq!(foo_fields[3].size, 1); - assert_eq!(foo_fields[3].num, 16); - assert_eq!( - foo_fields[3].flags.0, - VMStateFlags::VMS_VARRAY_UINT32.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0 - ); - assert!(foo_fields[3].vmsd.is_null()); - assert!(foo_fields[3].field_exists.is_none()); - - // The last VMStateField in VMSTATE_FOOA. - assert_eq!(foo_fields[4].flags, VMStateFlags::VMS_END); -} - -// =========================== Test VMSTATE_FOOB =========================== -// Test the use cases of the vmstate macro, corresponding to the following C -// macro variants: -// * VMSTATE_FOOB: -// - VMSTATE_BOOL_V -// - VMSTATE_U64 -// - VMSTATE_STRUCT_VARRAY_UINT8 -// - (no C version) MULTIPLY variant of VMSTATE_STRUCT_VARRAY_UINT32 -// - VMSTATE_ARRAY -// - VMSTATE_STRUCT_VARRAY_UINT8 with BqlCell wrapper & test_fn -#[repr(C)] -#[derive(Default)] -struct FooB { - arr_a: [FooA; FOO_ARRAY_MAX], - num_a: u8, - arr_a_mul: [FooA; FOO_ARRAY_MAX], - num_a_mul: u32, - wrap: BqlCell<u64>, - val: bool, - // FIXME: Use Timer array. Now we can't since it's hard to link savevm.c to test. - arr_i64: [i64; FOO_ARRAY_MAX], - arr_a_wrap: [FooA; FOO_ARRAY_MAX], - num_a_wrap: BqlCell<u32>, -} - -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_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() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOB.as_ref().fields, 7) }; - - // 1st VMStateField ("val") in VMSTATE_FOOB (corresponding to VMSTATE_BOOL_V) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[0].name) }.to_bytes_with_nul(), - b"val\0" - ); - assert_eq!(foo_fields[0].offset, 136); - assert_eq!(foo_fields[0].num_offset, 0); - assert_eq!(foo_fields[0].info, unsafe { &vmstate_info_bool }); - assert_eq!(foo_fields[0].version_id, 2); - assert_eq!(foo_fields[0].size, 1); - assert_eq!(foo_fields[0].num, 0); - assert_eq!(foo_fields[0].flags, VMStateFlags::VMS_SINGLE); - assert!(foo_fields[0].vmsd.is_null()); - assert!(foo_fields[0].field_exists.is_none()); -} - -#[test] -fn test_vmstate_uint64() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOB.as_ref().fields, 7) }; - - // 2nd VMStateField ("wrap") in VMSTATE_FOOB (corresponding to VMSTATE_U64) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[1].name) }.to_bytes_with_nul(), - b"wrap\0" - ); - assert_eq!(foo_fields[1].offset, 128); - assert_eq!(foo_fields[1].num_offset, 0); - assert_eq!(foo_fields[1].info, unsafe { &vmstate_info_uint64 }); - assert_eq!(foo_fields[1].version_id, 0); - assert_eq!(foo_fields[1].size, 8); - assert_eq!(foo_fields[1].num, 0); - assert_eq!(foo_fields[1].flags, VMStateFlags::VMS_SINGLE); - assert!(foo_fields[1].vmsd.is_null()); - assert!(foo_fields[1].field_exists.is_none()); -} - -#[test] -fn test_vmstate_struct_varray_uint8() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOB.as_ref().fields, 7) }; - - // 3rd VMStateField ("arr_a") in VMSTATE_FOOB (corresponding to - // VMSTATE_STRUCT_VARRAY_UINT8) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[2].name) }.to_bytes_with_nul(), - b"arr_a\0" - ); - assert_eq!(foo_fields[2].offset, 0); - assert_eq!(foo_fields[2].num_offset, 60); - assert!(foo_fields[2].info.is_null()); // VMSTATE_STRUCT_VARRAY_UINT8 doesn't set info field. - assert_eq!(foo_fields[2].version_id, 1); - assert_eq!(foo_fields[2].size, 20); - assert_eq!(foo_fields[2].num, 0); - assert_eq!( - foo_fields[2].flags.0, - VMStateFlags::VMS_STRUCT.0 | VMStateFlags::VMS_VARRAY_UINT8.0 - ); - assert_eq!(foo_fields[2].vmsd, VMSTATE_FOOA.as_ref()); - assert!(foo_fields[2].field_exists.is_none()); -} - -#[test] -fn test_vmstate_struct_varray_uint32_multiply() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOB.as_ref().fields, 7) }; - - // 4th VMStateField ("arr_a_mul") in VMSTATE_FOOB (corresponding to - // (no C version) MULTIPLY variant of VMSTATE_STRUCT_VARRAY_UINT32) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[3].name) }.to_bytes_with_nul(), - b"arr_a_mul\0" - ); - assert_eq!(foo_fields[3].offset, 64); - assert_eq!(foo_fields[3].num_offset, 124); - assert!(foo_fields[3].info.is_null()); // VMSTATE_STRUCT_VARRAY_UINT8 doesn't set info field. - assert_eq!(foo_fields[3].version_id, 2); - assert_eq!(foo_fields[3].size, 20); - assert_eq!(foo_fields[3].num, 32); - assert_eq!( - foo_fields[3].flags.0, - VMStateFlags::VMS_STRUCT.0 - | VMStateFlags::VMS_VARRAY_UINT32.0 - | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0 - ); - assert_eq!(foo_fields[3].vmsd, VMSTATE_FOOA.as_ref()); - assert!(foo_fields[3].field_exists.is_none()); -} - -#[test] -fn test_vmstate_macro_array() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOB.as_ref().fields, 7) }; - - // 5th VMStateField ("arr_i64") in VMSTATE_FOOB (corresponding to - // VMSTATE_ARRAY) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[4].name) }.to_bytes_with_nul(), - b"arr_i64\0" - ); - assert_eq!(foo_fields[4].offset, 144); - assert_eq!(foo_fields[4].num_offset, 0); - assert_eq!(foo_fields[4].info, unsafe { &vmstate_info_int64 }); - assert_eq!(foo_fields[4].version_id, 0); - assert_eq!(foo_fields[4].size, 8); - assert_eq!(foo_fields[4].num, FOO_ARRAY_MAX as i32); - assert_eq!(foo_fields[4].flags, VMStateFlags::VMS_ARRAY); - assert!(foo_fields[4].vmsd.is_null()); - assert!(foo_fields[4].field_exists.is_none()); -} - -#[test] -fn test_vmstate_struct_varray_uint8_wrapper() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOB.as_ref().fields, 7) }; - let mut foo_b: FooB = Default::default(); - let foo_b_p = std::ptr::addr_of_mut!(foo_b).cast::<c_void>(); - - // 6th VMStateField ("arr_a_wrap") in VMSTATE_FOOB (corresponding to - // VMSTATE_STRUCT_VARRAY_UINT8). Other fields are checked in - // test_vmstate_struct_varray_uint8. - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[5].name) }.to_bytes_with_nul(), - b"arr_a_wrap\0" - ); - assert_eq!(foo_fields[5].num_offset, 228); - assert!(unsafe { foo_fields[5].field_exists.unwrap()(foo_b_p, 0) }); - - // The last VMStateField in VMSTATE_FOOB. - assert_eq!(foo_fields[6].flags, VMStateFlags::VMS_END); -} - -// =========================== Test VMSTATE_FOOC =========================== -// Test the use cases of the vmstate macro, corresponding to the following C -// macro variants: -// * VMSTATE_FOOC: -// - VMSTATE_POINTER -// - VMSTATE_ARRAY_OF_POINTER -struct FooCWrapper([Opaque<*mut u8>; FOO_ARRAY_MAX]); // Though Opaque<> array is almost impossible. - -impl_vmstate_forward!(FooCWrapper); - -#[repr(C)] -struct FooC { - ptr: *const i32, - ptr_a: NonNull<FooA>, - arr_ptr: [Box<u8>; FOO_ARRAY_MAX], - arr_ptr_wrap: FooCWrapper, -} - -unsafe impl Sync for FooC {} - -static VMSTATE_FOOC: VMStateDescription<FooC> = VMStateDescriptionBuilder::<FooC>::new() - .name(c"foo_c") - .version_id(3) - .minimum_version_id(1) - .fields(vmstate_fields! { - vmstate_of!(FooC, ptr).with_version_id(2), - vmstate_of!(FooC, ptr_a), - vmstate_of!(FooC, arr_ptr), - vmstate_of!(FooC, arr_ptr_wrap), - }) - .build(); - -const PTR_SIZE: usize = size_of::<*mut ()>(); - -#[test] -fn test_vmstate_pointer() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOC.as_ref().fields, 6) }; - - // 1st VMStateField ("ptr") in VMSTATE_FOOC (corresponding to VMSTATE_POINTER) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[0].name) }.to_bytes_with_nul(), - b"ptr\0" - ); - assert_eq!(foo_fields[0].offset, 0); - assert_eq!(foo_fields[0].num_offset, 0); - assert_eq!(foo_fields[0].info, unsafe { &vmstate_info_int32 }); - assert_eq!(foo_fields[0].version_id, 2); - assert_eq!(foo_fields[0].size, 4); - assert_eq!(foo_fields[0].num, 0); - assert_eq!( - foo_fields[0].flags.0, - VMStateFlags::VMS_SINGLE.0 | VMStateFlags::VMS_POINTER.0 - ); - assert!(foo_fields[0].vmsd.is_null()); - 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] = - unsafe { slice::from_raw_parts(VMSTATE_FOOC.as_ref().fields, 6) }; - - // 3rd VMStateField ("arr_ptr") in VMSTATE_FOOC (corresponding to - // VMSTATE_ARRAY_OF_POINTER) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[2].name) }.to_bytes_with_nul(), - b"arr_ptr\0" - ); - assert_eq!(foo_fields[2].offset, 2 * PTR_SIZE); - assert_eq!(foo_fields[2].num_offset, 0); - assert_eq!(foo_fields[2].info, unsafe { &vmstate_info_uint8 }); - assert_eq!(foo_fields[2].version_id, 0); - assert_eq!(foo_fields[2].size, PTR_SIZE); - assert_eq!(foo_fields[2].num, FOO_ARRAY_MAX as i32); - assert_eq!( - foo_fields[2].flags.0, - VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0 - ); - assert!(foo_fields[2].vmsd.is_null()); - assert!(foo_fields[2].field_exists.is_none()); -} - -#[test] -fn test_vmstate_macro_array_of_pointer_wrapped() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOC.as_ref().fields, 6) }; - - // 4th VMStateField ("arr_ptr_wrap") in VMSTATE_FOOC (corresponding to - // VMSTATE_ARRAY_OF_POINTER) - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[3].name) }.to_bytes_with_nul(), - b"arr_ptr_wrap\0" - ); - assert_eq!(foo_fields[3].offset, (FOO_ARRAY_MAX + 2) * PTR_SIZE); - assert_eq!(foo_fields[3].num_offset, 0); - assert_eq!(foo_fields[3].info, unsafe { &vmstate_info_uint8 }); - assert_eq!(foo_fields[3].version_id, 0); - assert_eq!(foo_fields[3].size, PTR_SIZE); - assert_eq!(foo_fields[3].num, FOO_ARRAY_MAX as i32); - assert_eq!( - foo_fields[3].flags.0, - VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0 - ); - assert!(foo_fields[3].vmsd.is_null()); - assert!(foo_fields[3].field_exists.is_none()); - - // The last VMStateField in VMSTATE_FOOC. - assert_eq!(foo_fields[4].flags, VMStateFlags::VMS_END); -} - -// =========================== Test VMSTATE_FOOD =========================== -// Test the use cases of the vmstate macro, corresponding to the following C -// macro variants: -// * VMSTATE_FOOD: -// - VMSTATE_VALIDATE - -// Add more member fields when vmstate_of support "test" parameter. -struct FooD; - -impl FooD { - fn validate_food_0(&self, _version_id: u8) -> bool { - true - } - - fn validate_food_1(_state: &FooD, _version_id: u8) -> bool { - false - } -} - -fn validate_food_2(_state: &FooD, _version_id: u8) -> bool { - true -} - -static VMSTATE_FOOD: VMStateDescription<FooD> = VMStateDescriptionBuilder::<FooD>::new() - .name(c"foo_d") - .version_id(3) - .minimum_version_id(1) - .fields(vmstate_fields! { - vmstate_validate!(FooD, c"foo_d_0", FooD::validate_food_0), - vmstate_validate!(FooD, c"foo_d_1", FooD::validate_food_1), - vmstate_validate!(FooD, c"foo_d_2", validate_food_2), - }) - .build(); - -#[test] -fn test_vmstate_validate() { - let foo_fields: &[VMStateField] = - unsafe { slice::from_raw_parts(VMSTATE_FOOD.as_ref().fields, 4) }; - let mut foo_d = FooD; - let foo_d_p = std::ptr::addr_of_mut!(foo_d).cast::<c_void>(); - - // 1st VMStateField in VMSTATE_FOOD - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[0].name) }.to_bytes_with_nul(), - b"foo_d_0\0" - ); - assert_eq!(foo_fields[0].offset, 0); - assert_eq!(foo_fields[0].num_offset, 0); - assert!(foo_fields[0].info.is_null()); - assert_eq!(foo_fields[0].version_id, 0); - assert_eq!(foo_fields[0].size, 0); - assert_eq!(foo_fields[0].num, 0); - assert_eq!( - foo_fields[0].flags.0, - VMStateFlags::VMS_ARRAY.0 | VMStateFlags::VMS_MUST_EXIST.0 - ); - assert!(foo_fields[0].vmsd.is_null()); - assert!(unsafe { foo_fields[0].field_exists.unwrap()(foo_d_p, 0) }); - - // 2nd VMStateField in VMSTATE_FOOD - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[1].name) }.to_bytes_with_nul(), - b"foo_d_1\0" - ); - assert!(!unsafe { foo_fields[1].field_exists.unwrap()(foo_d_p, 1) }); - - // 3rd VMStateField in VMSTATE_FOOD - assert_eq!( - unsafe { CStr::from_ptr(foo_fields[2].name) }.to_bytes_with_nul(), - b"foo_d_2\0" - ); - assert!(unsafe { foo_fields[2].field_exists.unwrap()(foo_d_p, 2) }); - - // The last VMStateField in VMSTATE_FOOD. - assert_eq!(foo_fields[3].flags, VMStateFlags::VMS_END); -} diff --git a/rust/qemu-api/wrapper.h b/rust/qemu-api/wrapper.h deleted file mode 100644 index 7c9c20b14f..0000000000 --- a/rust/qemu-api/wrapper.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2024 Linaro Ltd. - * - * Authors: Manos Pitsidianakis <manos.pitsidianakis@linaro.org> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - -/* - * This header file is meant to be used as input to the `bindgen` application - * in order to generate C FFI compatible Rust bindings. - */ - -#ifndef __CLANG_STDATOMIC_H -#define __CLANG_STDATOMIC_H -/* - * Fix potential missing stdatomic.h error in case bindgen does not insert the - * correct libclang header paths on its own. We do not use stdatomic.h symbols - * in QEMU code, so it's fine to declare dummy types instead. - */ -typedef enum memory_order { - memory_order_relaxed, - memory_order_consume, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst, -} memory_order; -#endif /* __CLANG_STDATOMIC_H */ - -#include "qemu/osdep.h" -#include "qemu-io.h" -#include "exec/memattrs.h" -#include "hw/char/pl011.h" |