From cde3c425d16f6d0c8e6f47940ef5152b9021f3f2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 18 Oct 2024 16:30:56 +0200 Subject: rust: build integration test for the qemu_api crate Adjust the integration test to compile with a subset of QEMU object files, and make it actually create an object of the class it defines. Follow the Rust filesystem conventions, where tests go in tests/ if they use the library in the same way any other code would. Reviewed-by: Junjie Mao Reviewed-by: Kevin Wolf Signed-off-by: Paolo Bonzini --- rust/qemu-api/tests/tests.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 rust/qemu-api/tests/tests.rs (limited to 'rust/qemu-api/tests/tests.rs') diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs new file mode 100644 index 0000000..aa1e056 --- /dev/null +++ b/rust/qemu-api/tests/tests.rs @@ -0,0 +1,78 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis +// SPDX-License-Identifier: GPL-2.0-or-later + +use core::ffi::CStr; + +use qemu_api::{ + bindings::*, + declare_properties, define_property, + definitions::{Class, ObjectImpl}, + device_class_init, vm_state_description, +}; + +#[test] +fn test_device_decl_macros() { + // Test that macros can compile. + vm_state_description! { + VMSTATE, + name: c"name", + unmigratable: true, + } + + #[repr(C)] + #[derive(qemu_api_macros::Object)] + pub struct DummyState { + pub _parent: DeviceState, + pub migrate_clock: bool, + } + + #[repr(C)] + pub struct DummyClass { + pub _parent: DeviceClass, + } + + declare_properties! { + DUMMY_PROPERTIES, + define_property!( + c"migrate-clk", + DummyState, + migrate_clock, + unsafe { &qdev_prop_bool }, + bool + ), + } + + device_class_init! { + dummy_class_init, + props => DUMMY_PROPERTIES, + realize_fn => None, + legacy_reset_fn => None, + vmsd => VMSTATE, + } + + impl ObjectImpl for DummyState { + type Class = DummyClass; + const TYPE_INFO: qemu_api::bindings::TypeInfo = qemu_api::type_info! { Self }; + const TYPE_NAME: &'static CStr = c"dummy"; + const PARENT_TYPE_NAME: Option<&'static CStr> = Some(TYPE_DEVICE); + const ABSTRACT: bool = false; + const INSTANCE_INIT: Option = None; + const INSTANCE_POST_INIT: Option = None; + const INSTANCE_FINALIZE: Option = None; + } + + impl Class for DummyClass { + const CLASS_INIT: Option< + unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut core::ffi::c_void), + > = Some(dummy_class_init); + const CLASS_BASE_INIT: Option< + unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut core::ffi::c_void), + > = None; + } + + unsafe { + module_call_init(module_init_type::MODULE_INIT_QOM); + object_unref(object_new(DummyState::TYPE_NAME.as_ptr()) as *mut _); + } +} -- cgit v1.1 From 0a65e4124ad9c6dab594d738cac31fd32d19402c Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Fri, 25 Oct 2024 07:55:50 +0200 Subject: rust: add definitions for vmstate Add a new qemu_api module, `vmstate`. Declare a bunch of Rust macros declared that are equivalent in spirit to the C macros in include/migration/vmstate.h. For example the Rust of equivalent of the C macro: VMSTATE_UINT32(field_name, struct_name) is: vmstate_uint32!(field_name, StructName) This breathtaking development will allow us to reach feature parity between the Rust and C pl011 implementations. Extracted from a patch by Manos Pitsidianakis (https://lore.kernel.org/qemu-devel/20241024-rust-round-2-v1-4-051e7a25b978@linaro.org/). Signed-off-by: Manos Pitsidianakis Signed-off-by: Paolo Bonzini --- rust/qemu-api/tests/tests.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'rust/qemu-api/tests/tests.rs') diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index aa1e056..37c4dd4 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -8,17 +8,18 @@ use qemu_api::{ bindings::*, declare_properties, define_property, definitions::{Class, ObjectImpl}, - device_class_init, vm_state_description, + device_class_init, + zeroable::Zeroable, }; #[test] fn test_device_decl_macros() { // Test that macros can compile. - vm_state_description! { - VMSTATE, - name: c"name", + pub static VMSTATE: VMStateDescription = VMStateDescription { + name: c"name".as_ptr(), unmigratable: true, - } + ..Zeroable::ZERO + }; #[repr(C)] #[derive(qemu_api_macros::Object)] -- cgit v1.1 From 9f7d4520d679364f7ca95b7ddb899ff084e7d7c6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 24 Oct 2024 13:53:59 +0200 Subject: rust: use std::os::raw instead of core::ffi core::ffi::c_* types were introduced in Rust 1.64.0. Use the older types in std::os::raw, which are now aliases of the types in core::ffi. There is no need to compile QEMU as no_std, so this is acceptable as long as we support a version of Debian with Rust 1.63.0. Reviewed-by: Zhao Liu Signed-off-by: Paolo Bonzini --- rust/qemu-api/tests/tests.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'rust/qemu-api/tests/tests.rs') diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 37c4dd4..c7089f0 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -2,7 +2,7 @@ // Author(s): Manos Pitsidianakis // SPDX-License-Identifier: GPL-2.0-or-later -use core::ffi::CStr; +use std::{ffi::CStr, os::raw::c_void}; use qemu_api::{ bindings::*, @@ -64,11 +64,10 @@ fn test_device_decl_macros() { } impl Class for DummyClass { - const CLASS_INIT: Option< - unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut core::ffi::c_void), - > = Some(dummy_class_init); + const CLASS_INIT: Option = + Some(dummy_class_init); const CLASS_BASE_INIT: Option< - unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut core::ffi::c_void), + unsafe extern "C" fn(klass: *mut ObjectClass, data: *mut c_void), > = None; } -- cgit v1.1 From 718e255f0a97cf43939ae2e90ba4673ae9a8bd2f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 25 Oct 2024 08:23:53 +0200 Subject: rust: introduce a c_str macro This allows CStr constants to be defined easily on Rust 1.63.0, while checking that there are no embedded NULs. c"" literals were only stabilized in Rust 1.77.0. Reviewed-by: Zhao Liu Signed-off-by: Paolo Bonzini --- rust/qemu-api/tests/tests.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'rust/qemu-api/tests/tests.rs') diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index c7089f0..381ac84 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -6,7 +6,7 @@ use std::{ffi::CStr, os::raw::c_void}; use qemu_api::{ bindings::*, - declare_properties, define_property, + c_str, declare_properties, define_property, definitions::{Class, ObjectImpl}, device_class_init, zeroable::Zeroable, @@ -16,7 +16,7 @@ use qemu_api::{ fn test_device_decl_macros() { // Test that macros can compile. pub static VMSTATE: VMStateDescription = VMStateDescription { - name: c"name".as_ptr(), + name: c_str!("name").as_ptr(), unmigratable: true, ..Zeroable::ZERO }; @@ -36,7 +36,7 @@ fn test_device_decl_macros() { declare_properties! { DUMMY_PROPERTIES, define_property!( - c"migrate-clk", + c_str!("migrate-clk"), DummyState, migrate_clock, unsafe { &qdev_prop_bool }, @@ -55,7 +55,7 @@ fn test_device_decl_macros() { impl ObjectImpl for DummyState { type Class = DummyClass; const TYPE_INFO: qemu_api::bindings::TypeInfo = qemu_api::type_info! { Self }; - const TYPE_NAME: &'static CStr = c"dummy"; + const TYPE_NAME: &'static CStr = c_str!("dummy"); const PARENT_TYPE_NAME: Option<&'static CStr> = Some(TYPE_DEVICE); const ABSTRACT: bool = false; const INSTANCE_INIT: Option = None; -- cgit v1.1 From f3518400882022ddcbe1148abf2165917a7b4640 Mon Sep 17 00:00:00 2001 From: Junjie Mao Date: Thu, 24 Oct 2024 12:25:15 +0200 Subject: rust: introduce alternative implementation of offset_of! offset_of! was stabilized in Rust 1.77.0. Use an alternative implemenation that was found on the Rust forums, and whose author agreed to license as MIT for use in QEMU. The alternative allows only one level of field access, but apart from this can be used just by replacing core::mem::offset_of! with qemu_api::offset_of!. The actual implementation of offset_of! is done in a declarative macro, but for simplicity and to avoid introducing an extra level of indentation, the trigger is a procedural macro #[derive(offsets)]. The procedural macro is perhaps a bit overengineered, but it helps introducing some idioms that will be useful in the future as well. Signed-off-by: Junjie Mao Co-developed-by: Paolo Bonzini Signed-off-by: Paolo Bonzini --- rust/qemu-api/tests/tests.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'rust/qemu-api/tests/tests.rs') diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 381ac84..7442f69 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -21,6 +21,7 @@ fn test_device_decl_macros() { ..Zeroable::ZERO }; + #[derive(qemu_api_macros::offsets)] #[repr(C)] #[derive(qemu_api_macros::Object)] pub struct DummyState { -- cgit v1.1 From ce4a144cf817d401592918faa86f4903d3c78c3e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 25 Oct 2024 09:20:16 +0200 Subject: rust: do not use --generate-cstr --generate-cstr is a good idea and generally the right thing to do, but it is not available in Debian 12 and Ubuntu 22.04. Work around the absence. Signed-off-by: Paolo Bonzini --- rust/qemu-api/tests/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'rust/qemu-api/tests/tests.rs') diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 7442f69..43a4827 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -8,7 +8,7 @@ use qemu_api::{ bindings::*, c_str, declare_properties, define_property, definitions::{Class, ObjectImpl}, - device_class_init, + device_class, device_class_init, zeroable::Zeroable, }; @@ -57,7 +57,7 @@ fn test_device_decl_macros() { type Class = DummyClass; const TYPE_INFO: qemu_api::bindings::TypeInfo = qemu_api::type_info! { Self }; const TYPE_NAME: &'static CStr = c_str!("dummy"); - const PARENT_TYPE_NAME: Option<&'static CStr> = Some(TYPE_DEVICE); + const PARENT_TYPE_NAME: Option<&'static CStr> = Some(device_class::TYPE_DEVICE); const ABSTRACT: bool = false; const INSTANCE_INIT: Option = None; const INSTANCE_POST_INIT: Option = None; -- cgit v1.1