From nobody Fri Dec 19 22:01:34 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1744641017; cv=none; d=zohomail.com; s=zohoarc; b=DQekF5rmqUXwjcdadFF+fUGjtDwQLQAlbz8VdSimuXXOouCfh/pXPIehLBhazFy9Mc3pQiJIjj7ajv+25JX6B9HCiMQGqmQ703iADlmwsNeFg4zV7vM9NppSqIiY3Pm0K81C+DABtSvfL1NFdqx46sK0FcwWtcHGqEM9vuUq3FM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1744641017; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=R19Q/sUKIbLjIR/jOx1RqlZgkK+/1y0ry0LkGWIffx4=; b=depGirR+L8BLf0UdvPRWYl/TrlyjmTkQVFDzIGWbOGJhoBqNFJxDhxeR2Sc2GK49L+9KMIkGLqOPp0Cj38ek16vOtR9itXHnxFcpe/H5vftEOMXdh2LKkIAspisEd80IvT6Y85ntTuqxfnmufB4h15Xn6bPT2ZTwHISzsVv+gHc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=@intel.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17446410178031017.3478402632186; Mon, 14 Apr 2025 07:30:17 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1u4KoG-0003H4-AF; Mon, 14 Apr 2025 10:29:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u4Ko5-0003Ci-HJ; Mon, 14 Apr 2025 10:29:07 -0400 Received: from mgamail.intel.com ([192.198.163.7]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u4Ko3-00064t-DK; Mon, 14 Apr 2025 10:29:05 -0400 Received: from fmviesa005.fm.intel.com ([10.60.135.145]) by fmvoesa101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Apr 2025 07:28:59 -0700 Received: from liuzhao-optiplex-7080.sh.intel.com ([10.239.160.39]) by fmviesa005.fm.intel.com with ESMTP; 14 Apr 2025 07:28:57 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1744640943; x=1776176943; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=GzS64O2hk/JA+khEXR5sy4DpnE89caJbyZrlyQSwIBE=; b=mQx+NFvTKov2dpzzkIT5POz2j8945OsZuE9XJOkHMyWjW31drlu+wyJZ 0gAXgRtJkHnHILIHy0jUhfTH96k8JXY2qfj6CemDqPf1YGVQlQQdfjMKw YHp3lnOAdi8e3G5rCcpuvQ2VUJqvR8oxStPznyVm//YgM6oeZG1oct7fG tBLx1P7ZPgW3Yhgl/pSsyAeYh1b1yeGs/RImDjEiC7V8nT/A3qXnxFf8W XTvSPLlMXZ5QTfZVDs8+QsLgC8A5Vy3Lt3uBptpnHYEhfjFdpOZ8LAS2J TFSk3cqkZR4hM6a3McQRNFxr3P0gM7Q4PjMEdUZSGyTZN/0BzogxZ1Jgk w==; X-CSE-ConnectionGUID: NgAkI0i2ReiS6qEfwLGURg== X-CSE-MsgGUID: uhXGdTWqQ+yAh2CbZwh3rA== X-IronPort-AV: E=McAfee;i="6700,10204,11403"; a="71501829" X-IronPort-AV: E=Sophos;i="6.15,212,1739865600"; d="scan'208";a="71501829" X-CSE-ConnectionGUID: 87EZugvOS1WCk/nYiSK/og== X-CSE-MsgGUID: 2QJh8lE3S8i4NdHnc/zYlQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.15,212,1739865600"; d="scan'208";a="134606054" From: Zhao Liu To: Paolo Bonzini Cc: qemu-devel@nongnu.org, qemu-rust@nongnu.org, Dapeng Mi , Zhao Liu Subject: [PATCH 1/9] rust/vmstate: Support field_exists check in vmstate_struct macro Date: Mon, 14 Apr 2025 22:49:35 +0800 Message-Id: <20250414144943.1112885-2-zhao1.liu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250414144943.1112885-1-zhao1.liu@intel.com> References: <20250414144943.1112885-1-zhao1.liu@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=192.198.163.7; envelope-from=zhao1.liu@intel.com; helo=mgamail.intel.com X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @intel.com) X-ZM-MESSAGEID: 1744641020170019100 Content-Type: text/plain; charset="utf-8" Unfortunately, at present it's not possible to have a const "with_exist_check" method to append test_fn after vmstate_struct (due to error on "constant functions cannot evaluate destructors" for `F`). Before the vmstate builder, the only way to support "test_fn" is to extend vmstate_struct macro to add the such new optional member (and fortunately, Rust can still parse the current expansion!). Abstract the previous callback implementation of vmstate_validate into a separate macro, and moves it before vmstate_struct for vmstate_struct to call. Note that there's no need to add any extra flag for a new test_fn added in the VMStateField. Signed-off-by: Zhao Liu --- rust/qemu-api/src/vmstate.rs | 67 +++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs index 1b2b12eadd6e..7d9f3a2ca6f2 100644 --- a/rust/qemu-api/src/vmstate.rs +++ b/rust/qemu-api/src/vmstate.rs @@ -435,6 +435,38 @@ macro_rules! vmstate_unused { }}; } =20 +pub extern "C" fn rust_vms_test_field_exists FnCall<(&'a T, = u8), bool>>( + opaque: *mut c_void, + version_id: c_int, +) -> bool { + // SAFETY: the opaque was passed as a reference to `T`. + let owner: &T =3D unsafe { &*(opaque.cast::()) }; + let version: u8 =3D version_id.try_into().unwrap(); + F::call((owner, version)) +} + +pub type VMSFieldExistCb =3D unsafe extern "C" fn( + opaque: *mut std::os::raw::c_void, + version_id: std::os::raw::c_int, +) -> bool; + +#[macro_export] +macro_rules! vmstate_exist_fn { + ($struct_name:ty, $test_fn:expr) =3D> {{ + const fn test_cb_builder__ $crate::callbacks::FnCall= <(&'a T, u8), bool>>( + _phantom: ::core::marker::PhantomData, + ) -> $crate::vmstate::VMSFieldExistCb { + let _: () =3D F::ASSERT_IS_SOME; + $crate::vmstate::rust_vms_test_field_exists:: + } + + const fn phantom__(_: &T) -> ::core::marker::PhantomData { + ::core::marker::PhantomData + } + Some(test_cb_builder__::<$struct_name, _>(phantom__(&$test_fn))) + }}; +} + // FIXME: including the `vmsd` field in a `const` is not possible without // the const_refs_static feature (stabilized in Rust 1.83.0). Without it, // it is not possible to use VMS_STRUCT in a transparent manner using @@ -445,7 +477,7 @@ macro_rules! vmstate_unused { #[doc(alias =3D "VMSTATE_STRUCT")] #[macro_export] macro_rules! vmstate_struct { - ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:exp= r)?])?, $vmsd:expr, $type:ty $(,)?) =3D> { + ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:exp= r)?])?, $vmsd:expr, $type:ty $(, $test_fn:expr)? $(,)?) =3D> { $crate::bindings::VMStateField { name: ::core::concat!(::core::stringify!($field_name), "\0") .as_bytes() @@ -458,6 +490,7 @@ macro_rules! vmstate_struct { size: ::core::mem::size_of::<$type>(), flags: $crate::bindings::VMStateFlags::VMS_STRUCT, vmsd: $vmsd, + $(field_exists: $crate::vmstate_exist_fn!($struct_name, $test_= fn),)? ..$crate::zeroable::Zeroable::ZERO } $(.with_varray_flag_unchecked( $crate::call_func_with_field!( @@ -514,43 +547,13 @@ macro_rules! vmstate_fields { }} } =20 -pub extern "C" fn rust_vms_test_field_exists FnCall<(&'a T, = u8), bool>>( - opaque: *mut c_void, - version_id: c_int, -) -> bool { - let owner: &T =3D unsafe { &*(opaque.cast::()) }; - let version: u8 =3D version_id.try_into().unwrap(); - // SAFETY: the opaque was passed as a reference to `T`. - F::call((owner, version)) -} - -pub type VMSFieldExistCb =3D unsafe extern "C" fn( - opaque: *mut std::os::raw::c_void, - version_id: std::os::raw::c_int, -) -> bool; - #[doc(alias =3D "VMSTATE_VALIDATE")] #[macro_export] macro_rules! vmstate_validate { ($struct_name:ty, $test_name:expr, $test_fn:expr $(,)?) =3D> { $crate::bindings::VMStateField { name: ::std::ffi::CStr::as_ptr($test_name), - field_exists: { - const fn test_cb_builder__< - T, - F: for<'a> $crate::callbacks::FnCall<(&'a T, u8), bool= >, - >( - _phantom: ::core::marker::PhantomData, - ) -> $crate::vmstate::VMSFieldExistCb { - let _: () =3D F::ASSERT_IS_SOME; - $crate::vmstate::rust_vms_test_field_exists:: - } - - const fn phantom__(_: &T) -> ::core::marker::PhantomDat= a { - ::core::marker::PhantomData - } - Some(test_cb_builder__::<$struct_name, _>(phantom__(&$test= _fn))) - }, + field_exists: $crate::vmstate_exist_fn!($struct_name, $test_fn= ), flags: $crate::bindings::VMStateFlags( $crate::bindings::VMStateFlags::VMS_MUST_EXIST.0 | $crate::bindings::VMStateFlags::VMS_ARRAY.0, --=20 2.34.1