From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217226; cv=none; d=zohomail.com; s=zohoarc; b=f9w2fPzkDkirp+FzVyqTqdQ+LXzlI5DIkkeRFxhtJZpeMnzSbRlJle47WIn7R7QpoWlXF7TpvQ6f+lqg/LcDnmZoFKUwBH65qPhFibCd55VoqyiwCmFvoYcU6iTxVsXQ88+YjkCgvudI1evWS05EBJvvTEsbmvmyzHxbq4ggrJs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217226; h=Content-Type: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=Gpr5BEiJG98iqlxJYetB1UMIinIuIwew365BsOdINxM=; b=jVcG34NWGbzLi2L0bjM90+mU5H6bnDX88+jwyz4cWLoGsHKIVt2pMCcxgQUxzJmCpKX1Mt3h1zysS39dMKiuj0MU2ZbSBiUO9ZiiYVz16eVmwGn71BjBQnJS0EqcX0wAYGgAyzKeRKvdiQNwQflnHpdtjipgboI7/Lnw9RF9J8Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217226183901.1345035961799; Tue, 26 Aug 2025 07:07:06 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJ4-00064u-Uy; Tue, 26 Aug 2025 10:05:50 -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 1uquIW-0005us-G5 for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:18 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquIM-0006n9-UA for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:15 -0400 Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-56-AFI72CCXPVyTSklwcSoavQ-1; Tue, 26 Aug 2025 10:05:01 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C867E1956095; Tue, 26 Aug 2025 14:04:59 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7EAA81800280; Tue, 26 Aug 2025 14:04:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217104; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Gpr5BEiJG98iqlxJYetB1UMIinIuIwew365BsOdINxM=; b=g8vkHSSDWfmkrOVUHPTXdtsEmsdyjkHTbxSXlIV6oIpmX6qOp5K7xK3axEQ5omUG722OlK F39MGu7cv08Q/+O/mBo1fX8FU6m092gU+/JMr3G0MKbrYpipN1hKqjg+zCZRsx+vFX6wJw eoKp1QJ3D/hgW6bfOlpu8yAjFhVZGfk= X-MC-Unique: AFI72CCXPVyTSklwcSoavQ-1 X-Mimecast-MFC-AGG-ID: AFI72CCXPVyTSklwcSoavQ_1756217100 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 01/18] rust: remove unused global qemu "allocator" Date: Tue, 26 Aug 2025 18:04:29 +0400 Message-ID: <20250826140449.4190022-2-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 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=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-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 @redhat.com) X-ZM-MESSAGEID: 1756217227229116600 From: Marc-Andr=C3=A9 Lureau The global allocator has always been disabled. There is no clear reason Rust and C should use the same allocator. Allocations made from Rust must be freed by Rust, and same for C, otherwise we head into troubles. Signed-off-by: Marc-Andr=C3=A9 Lureau --- meson.build | 4 -- rust/Cargo.toml | 2 +- rust/qemu-api/Cargo.toml | 1 - rust/qemu-api/meson.build | 1 - rust/qemu-api/src/lib.rs | 135 -------------------------------------- 5 files changed, 1 insertion(+), 142 deletions(-) diff --git a/meson.build b/meson.build index 50c774a195..ebbe9f8785 100644 --- a/meson.build +++ b/meson.build @@ -1090,9 +1090,6 @@ glib =3D declare_dependency(dependencies: [glib_pc, g= module], # TODO: remove this check and the corresponding workaround (qtree) when # the minimum supported glib is >=3D 2.75.3 glib_has_gslice =3D glib.version().version_compare('<2.75.3') -# Check whether glib has the aligned_alloc family of functions. -# -glib_has_aligned_alloc =3D glib.version().version_compare('>=3D2.72.0') =20 # override glib dep to include the above refinements meson.override_dependency('glib-2.0', glib) @@ -2706,7 +2703,6 @@ config_host_data.set('CONFIG_GETLOADAVG', cc.has_func= tion('getloadavg')) config_host_data.set('HAVE_COPY_FILE_RANGE', cc.has_function('copy_file_ra= nge')) config_host_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs')) config_host_data.set('HAVE_GLIB_WITH_SLICE_ALLOCATOR', glib_has_gslice) -config_host_data.set('HAVE_GLIB_WITH_ALIGNED_ALLOC', glib_has_aligned_allo= c) config_host_data.set('HAVE_OPENPTY', cc.has_function('openpty', dependenci= es: util)) config_host_data.set('HAVE_STRCHRNUL', cc.has_function('strchrnul', prefix= : osdep_prefix)) config_host_data.set('HAVE_SYSTEM_FUNCTION', cc.has_function('system', pre= fix: '#include ')) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 0868e1b426..1a24859cd7 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -17,7 +17,7 @@ rust-version =3D "1.77.0" =20 [workspace.lints.rust] unexpected_cfgs =3D { level =3D "deny", check-cfg =3D [ - 'cfg(MESON)', 'cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)', + 'cfg(MESON)', ] } =20 # Occasionally, we may need to silence warnings and clippy lints that diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index db7000dee4..603327945f 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -21,7 +21,6 @@ foreign =3D "~0.3.1" =20 [features] default =3D ["debug_cell"] -allocator =3D [] debug_cell =3D [] =20 [lints] diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index a090297c45..062009f161 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -2,7 +2,6 @@ _qemu_api_cfg =3D run_command(rustc_args, '--config-headers', config_host_h, '--features', files('Cargo.toml'), capture: true, check: true).stdout().strip().splitlines() =20 -# _qemu_api_cfg +=3D ['--cfg', 'feature=3D"allocator"'] if get_option('debug_mutex') _qemu_api_cfg +=3D ['--cfg', 'feature=3D"debug_cell"'] endif diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 86dcd8ef17..0f9231f398 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -32,139 +32,4 @@ pub mod vmstate; pub mod zeroable; =20 -use std::{ - alloc::{GlobalAlloc, Layout}, - ffi::c_void, -}; - pub use error::{Error, Result}; - -#[cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)] -extern "C" { - fn g_aligned_alloc0( - n_blocks: bindings::gsize, - n_block_bytes: bindings::gsize, - alignment: bindings::gsize, - ) -> bindings::gpointer; - fn g_aligned_free(mem: bindings::gpointer); -} - -#[cfg(not(HAVE_GLIB_WITH_ALIGNED_ALLOC))] -extern "C" { - fn qemu_memalign(alignment: usize, size: usize) -> *mut c_void; - fn qemu_vfree(ptr: *mut c_void); -} - -extern "C" { - fn g_malloc0(n_bytes: bindings::gsize) -> bindings::gpointer; - fn g_free(mem: bindings::gpointer); -} - -/// An allocator that uses the same allocator as QEMU in C. -/// -/// It is enabled by default with the `allocator` feature. -/// -/// To set it up manually as a global allocator in your crate: -/// -/// ```ignore -/// use qemu_api::QemuAllocator; -/// -/// #[global_allocator] -/// static GLOBAL: QemuAllocator =3D QemuAllocator::new(); -/// ``` -#[derive(Clone, Copy, Debug)] -#[repr(C)] -pub struct QemuAllocator { - _unused: [u8; 0], -} - -#[cfg_attr(all(feature =3D "allocator", not(test)), global_allocator)] -pub static GLOBAL: QemuAllocator =3D QemuAllocator::new(); - -impl QemuAllocator { - // From the glibc documentation, on GNU systems, malloc guarantees 16-= byte - // alignment on 64-bit systems and 8-byte alignment on 32-bit systems.= See - // https://www.gnu.org/software/libc/manual/html_node/Malloc-Examples.= html. - // This alignment guarantee also applies to Windows and Android. On Da= rwin - // and OpenBSD, the alignment is 16 bytes on both 64-bit and 32-bit sy= stems. - #[cfg(all( - target_pointer_width =3D "32", - not(any(target_os =3D "macos", target_os =3D "openbsd")) - ))] - pub const DEFAULT_ALIGNMENT_BYTES: Option =3D Some(8); - #[cfg(all( - target_pointer_width =3D "64", - not(any(target_os =3D "macos", target_os =3D "openbsd")) - ))] - pub const DEFAULT_ALIGNMENT_BYTES: Option =3D Some(16); - #[cfg(all( - any(target_pointer_width =3D "32", target_pointer_width =3D "64"), - any(target_os =3D "macos", target_os =3D "openbsd") - ))] - pub const DEFAULT_ALIGNMENT_BYTES: Option =3D Some(16); - #[cfg(not(any(target_pointer_width =3D "32", target_pointer_width =3D = "64")))] - pub const DEFAULT_ALIGNMENT_BYTES: Option =3D None; - - pub const fn new() -> Self { - Self { _unused: [] } - } -} - -impl Default for QemuAllocator { - fn default() -> Self { - Self::new() - } -} - -// Sanity check. -const _: [(); 8] =3D [(); ::core::mem::size_of::<*mut c_void>()]; - -unsafe impl GlobalAlloc for QemuAllocator { - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - if matches!(Self::DEFAULT_ALIGNMENT_BYTES, Some(default) if defaul= t.checked_rem(layout.align()) =3D=3D Some(0)) - { - // SAFETY: g_malloc0() is safe to call. - unsafe { g_malloc0(layout.size().try_into().unwrap()).cast::() } - } else { - #[cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)] - { - // SAFETY: g_aligned_alloc0() is safe to call. - unsafe { - g_aligned_alloc0( - layout.size().try_into().unwrap(), - 1, - layout.align().try_into().unwrap(), - ) - .cast::() - } - } - #[cfg(not(HAVE_GLIB_WITH_ALIGNED_ALLOC))] - { - // SAFETY: qemu_memalign() is safe to call. - unsafe { qemu_memalign(layout.align(), layout.size()).cast= ::() } - } - } - } - - unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - if matches!(Self::DEFAULT_ALIGNMENT_BYTES, Some(default) if defaul= t.checked_rem(layout.align()) =3D=3D Some(0)) - { - // SAFETY: `ptr` must have been allocated by Self::alloc thus = a valid - // glib-allocated pointer, so `g_free`ing is safe. - unsafe { g_free(ptr.cast::<_>()) } - } else { - #[cfg(HAVE_GLIB_WITH_ALIGNED_ALLOC)] - { - // SAFETY: `ptr` must have been allocated by Self::alloc t= hus a valid aligned - // glib-allocated pointer, so `g_aligned_free`ing is safe. - unsafe { g_aligned_free(ptr.cast::<_>()) } - } - #[cfg(not(HAVE_GLIB_WITH_ALIGNED_ALLOC))] - { - // SAFETY: `ptr` must have been allocated by Self::alloc t= hus a valid aligned - // glib-allocated pointer, so `qemu_vfree`ing is safe. - unsafe { qemu_vfree(ptr.cast::<_>()) } - } - } - } -} --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217456; cv=none; d=zohomail.com; s=zohoarc; b=hSzGSaulXDT52jx58MhCXs4ONbrgxHMPbECqKmfEk8i4lRBosMInOGO5h870ABmpFsiCSLYeDOJOD2UJnox/dhf47Sx7EmGul4tX4jIfgPY+Wxbgn1d/NiTARqWT68gkaAgbnQXyRIO4k+jBaVyjXnbFA+WwPX/PuFLX+NWOT4s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217456; h=Content-Type: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=NtaV6wg0F8dIzupPcWRwESTWV4rf4xI3WwEEX8M7G6c=; b=eLMqGWx7xG0pMezJ0K4K8i4wF4OeJuhhxFZ4sBmkR6+HHwZa0ng3ayqjOj0i6jAsOhq34uY3xAHBVhgWy7iIxgDpyMvYsiPn7KKOqdfytEIvLILDX0JQXXEZ7HkyS2BxigBh6i3CuWgUqp3GEj7k2E3ZcNQdVIHLiUMBxxguFJk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217456849738.8010658091549; Tue, 26 Aug 2025 07:10:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJ1-00062O-1g; Tue, 26 Aug 2025 10:05:48 -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 1uquIc-0005wB-0t for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:24 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquIS-0006nw-Oc for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:21 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-509-n_kXrA29NgGUdTzvP7Eerw-1; Tue, 26 Aug 2025 10:05:05 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B5AD019560A2; Tue, 26 Aug 2025 14:05:04 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 89FA11955F24; Tue, 26 Aug 2025 14:05:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217109; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NtaV6wg0F8dIzupPcWRwESTWV4rf4xI3WwEEX8M7G6c=; b=bb0G1KYluEYCMRcJIV7YpCnvJEx/MJYHZBROWpzKuxggaLsEdInDOhjlBQNv+Ke1mWC5rH qR2GayH2hHExYFfcExzxIOiiBtnq2nGBV+pXdNZ2ChMBpv63paQzkBpMNL4YygZITnNWVo 7YnqtPSORKHhABvVkhlbvcaPJEgyeNM= X-MC-Unique: n_kXrA29NgGUdTzvP7Eerw-1 X-Mimecast-MFC-AGG-ID: n_kXrA29NgGUdTzvP7Eerw_1756217104 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 02/18] rust: add workspace authors Date: Tue, 26 Aug 2025 18:04:30 +0400 Message-ID: <20250826140449.4190022-3-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, T_SPF_TEMPERROR=0.01 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1756217459225124100 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau --- rust/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 1a24859cd7..5881bd034b 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -14,6 +14,7 @@ homepage =3D "https://www.qemu.org" license =3D "GPL-2.0-or-later" repository =3D "https://gitlab.com/qemu-project/qemu/" rust-version =3D "1.77.0" +authors =3D ["The QEMU Project Developers "] =20 [workspace.lints.rust] unexpected_cfgs =3D { level =3D "deny", check-cfg =3D [ --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217554; cv=none; d=zohomail.com; s=zohoarc; b=QbNRTiuSdvTfGhdJ4NHD1cMzIIpGinQtFVR+DdRXCVC3Gr8q5Qruu5HaOxmc5rQGc/OpSLEE6pelrXpmAGNnnbBGdsrh/pv598xyzbGOZdLc3wEnJJ1cDNOTierV7k9fkhFC+uq6rKZoVyo6V9FaT7W+SEkut9bk2dD5sgp2peE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217554; h=Content-Type: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=vmOSFLL9CGRJNy6tw0oQcxAYnd8paMS0iNpyDkrFQjw=; b=l4L9ZL/M9+nq3Y4ygW1yXOnVVPtvkT5/55QTryubLyG2UJHobAIdmB1KwZvBGcM268mfNdDChqDdr2b6b+VMln9jFHFMnDLb3LyBsKmIzV2Kw+G/74qtSmhpoQMnSWZPm2JSMR88dJOSVZG4Z/Wml4aIc0Ao45AZnJqBIdwOy+M= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217554272297.52947558953633; Tue, 26 Aug 2025 07:12:34 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJ5-00065K-Ce; Tue, 26 Aug 2025 10:05:51 -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 1uquIn-000603-BL for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:35 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquId-000700-Af for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:33 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-587-vBZrPnGAO42dIJ5ZhTg24g-1; Tue, 26 Aug 2025 10:05:13 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D6DBF19560B3; Tue, 26 Aug 2025 14:05:10 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DDFA21800280; Tue, 26 Aug 2025 14:05:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217117; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vmOSFLL9CGRJNy6tw0oQcxAYnd8paMS0iNpyDkrFQjw=; b=cl8JK0zVBTV29f7XdW2pg26bmSyZ1VNvWjVA45udjI2Px2auJzdpLuvX7eiMIaSOmBYuqS E/kF+HE/qagHPY80YLhpMnJ5B5Tzl3Jhsf4rnEEsVP+2qIKWUWAcTJaPWlRf4z3UFHKfTQ 4JHH+euOXtWgBawoQnfNNXz5FabMMMI= X-MC-Unique: vBZrPnGAO42dIJ5ZhTg24g-1 X-Mimecast-MFC-AGG-ID: vBZrPnGAO42dIJ5ZhTg24g_1756217111 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 03/18] rust: split Rust-only "common" crate Date: Tue, 26 Aug 2025 18:04:31 +0400 Message-ID: <20250826140449.4190022-4-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 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=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-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 @redhat.com) X-ZM-MESSAGEID: 1756217557992116600 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau --- MAINTAINERS | 1 + rust/Cargo.lock | 7 + rust/Cargo.toml | 1 + rust/common/Cargo.toml | 16 ++ rust/common/meson.build | 32 +++ rust/{qemu-api =3D> common}/src/assertions.rs | 16 +- rust/{qemu-api =3D> common}/src/bitops.rs | 1 - rust/{qemu-api =3D> common}/src/callbacks.rs | 12 +- rust/common/src/lib.rs | 17 ++ rust/common/src/opaque.rs | 240 ++++++++++++++++++++ rust/{qemu-api =3D> common}/src/uninit.rs | 2 +- rust/common/src/zeroable.rs | 18 ++ rust/hw/char/pl011/Cargo.toml | 1 + rust/hw/char/pl011/meson.build | 1 + rust/hw/char/pl011/src/device.rs | 4 +- rust/hw/timer/hpet/Cargo.toml | 1 + rust/hw/timer/hpet/meson.build | 1 + rust/hw/timer/hpet/src/device.rs | 3 +- rust/hw/timer/hpet/src/fw_cfg.rs | 3 +- rust/meson.build | 1 + rust/qemu-api-macros/src/lib.rs | 14 +- rust/qemu-api-macros/src/tests.rs | 2 +- rust/qemu-api/Cargo.toml | 1 + rust/qemu-api/meson.build | 9 +- rust/qemu-api/src/bindings.rs | 21 ++ rust/qemu-api/src/cell.rs | 237 +------------------ rust/qemu-api/src/chardev.rs | 5 +- rust/qemu-api/src/errno.rs | 3 +- rust/qemu-api/src/error.rs | 3 +- rust/qemu-api/src/irq.rs | 3 +- rust/qemu-api/src/lib.rs | 5 - rust/qemu-api/src/memory.rs | 5 +- rust/qemu-api/src/prelude.rs | 4 +- rust/qemu-api/src/qdev.rs | 10 +- rust/qemu-api/src/qom.rs | 3 +- rust/qemu-api/src/sysbus.rs | 3 +- rust/qemu-api/src/timer.rs | 8 +- rust/qemu-api/src/vmstate.rs | 24 +- rust/qemu-api/src/zeroable.rs | 37 --- rust/qemu-api/tests/tests.rs | 2 +- rust/qemu-api/tests/vmstate_tests.rs | 4 +- 41 files changed, 429 insertions(+), 352 deletions(-) create mode 100644 rust/common/Cargo.toml create mode 100644 rust/common/meson.build rename rust/{qemu-api =3D> common}/src/assertions.rs (92%) rename rust/{qemu-api =3D> common}/src/bitops.rs (98%) rename rust/{qemu-api =3D> common}/src/callbacks.rs (97%) create mode 100644 rust/common/src/lib.rs create mode 100644 rust/common/src/opaque.rs rename rust/{qemu-api =3D> common}/src/uninit.rs (98%) create mode 100644 rust/common/src/zeroable.rs delete mode 100644 rust/qemu-api/src/zeroable.rs diff --git a/MAINTAINERS b/MAINTAINERS index a07086ed76..80c0f80657 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3510,6 +3510,7 @@ F: include/hw/registerfields.h Rust M: Manos Pitsidianakis S: Maintained +F: rust/common/ F: rust/qemu-api F: rust/qemu-api-macros F: rust/rustfmt.toml diff --git a/rust/Cargo.lock b/rust/Cargo.lock index b785c718f3..ac105bd499 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -44,6 +44,10 @@ dependencies =3D [ "qemu_api_macros", ] =20 +[[package]] +name =3D "common" +version =3D "0.1.0" + [[package]] name =3D "either" version =3D "1.12.0" @@ -63,6 +67,7 @@ dependencies =3D [ name =3D "hpet" version =3D "0.1.0" dependencies =3D [ + "common", "qemu_api", "qemu_api_macros", ] @@ -89,6 +94,7 @@ dependencies =3D [ "bilge", "bilge-impl", "bits", + "common", "qemu_api", "qemu_api_macros", ] @@ -130,6 +136,7 @@ name =3D "qemu_api" version =3D "0.1.0" dependencies =3D [ "anyhow", + "common", "foreign", "libc", "qemu_api_macros", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 5881bd034b..bb27db7931 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -2,6 +2,7 @@ resolver =3D "2" members =3D [ "bits", + "common", "qemu-api-macros", "qemu-api", "hw/char/pl011", diff --git a/rust/common/Cargo.toml b/rust/common/Cargo.toml new file mode 100644 index 0000000000..d7e5580339 --- /dev/null +++ b/rust/common/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name =3D "common" +version =3D "0.1.0" +description =3D "Rust common code for QEMU" +resolver =3D "2" +publish =3D false + +authors.workspace =3D true +edition.workspace =3D true +homepage.workspace =3D true +license.workspace =3D true +repository.workspace =3D true +rust-version.workspace =3D true + +[lints] +workspace =3D true diff --git a/rust/common/meson.build b/rust/common/meson.build new file mode 100644 index 0000000000..d644a4f012 --- /dev/null +++ b/rust/common/meson.build @@ -0,0 +1,32 @@ +_common_cfg =3D run_command(rustc_args, + '--config-headers', config_host_h, '--features', files('Cargo.toml'), + capture: true, check: true).stdout().strip().splitlines() + +_common_rs =3D static_library( + 'common', + structured_sources( + [ + 'src/lib.rs', + 'src/assertions.rs', + 'src/bitops.rs', + 'src/callbacks.rs', + 'src/opaque.rs', + 'src/uninit.rs', + 'src/zeroable.rs', + ], + ), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_abi: 'rust', + rust_args: _common_cfg, +) + +common_rs =3D declare_dependency(link_with: [_common_rs]) +# +# Doctests are essentially integration tests, so they need the same depend= encies. +# Note that running them requires the object files for C code, so place th= em +# in a separate suite that is run by the "build" CI jobs rather than "chec= k". +rust.doctest('rust-common-doctests', + _common_rs, + protocol: 'rust', + dependencies: common_rs, + suite: ['doc', 'rust']) diff --git a/rust/qemu-api/src/assertions.rs b/rust/common/src/assertions.rs similarity index 92% rename from rust/qemu-api/src/assertions.rs rename to rust/common/src/assertions.rs index a2d38c877d..32a3ad0be6 100644 --- a/rust/qemu-api/src/assertions.rs +++ b/rust/common/src/assertions.rs @@ -8,7 +8,7 @@ //! types match the expectations of C code. //! //! Documentation is hidden because it only exposes macros, which -//! are exported directly from `qemu_api`. +//! are exported directly from `common`. =20 // Based on https://stackoverflow.com/questions/64251852/x/70978292#709782= 92 // (stackoverflow answers are released under MIT license). @@ -27,7 +27,7 @@ impl EqType for T { /// # Examples /// /// ``` -/// # use qemu_api::assert_same_type; +/// # use common::assert_same_type; /// # use std::ops::Deref; /// assert_same_type!(u32, u32); /// assert_same_type!( as Deref>::Target, u32); @@ -36,7 +36,7 @@ impl EqType for T { /// Different types will cause a compile failure /// /// ```compile_fail -/// # use qemu_api::assert_same_type; +/// # use common::assert_same_type; /// assert_same_type!(&Box, &u32); /// ``` #[macro_export] @@ -61,7 +61,7 @@ fn types_must_be_equal(_: T) /// # Examples /// /// ``` -/// # use qemu_api::assert_field_type; +/// # use common::assert_field_type; /// pub struct A { /// field1: u32, /// } @@ -72,7 +72,7 @@ fn types_must_be_equal(_: T) /// Different types will cause a compile failure /// /// ```compile_fail -/// # use qemu_api::assert_field_type; +/// # use common::assert_field_type; /// # pub struct A { field1: u32 } /// assert_field_type!(A, field1, i32); /// ``` @@ -107,7 +107,7 @@ fn types_must_be_equal(_: &T) /// # Examples /// /// ``` -/// # use qemu_api::assert_match; +/// # use common::assert_match; /// // JoinHandle does not implement `Eq`, therefore the result /// // does not either. /// let result: Result, u32> =3D Err(42); @@ -136,12 +136,12 @@ macro_rules! assert_match { /// # Examples /// /// ``` -/// # use qemu_api::static_assert; +/// # use common::static_assert; /// static_assert!("abc".len() =3D=3D 3); /// ``` /// /// ```compile_fail -/// # use qemu_api::static_assert; +/// # use common::static_assert; /// static_assert!("abc".len() =3D=3D 2); // does not compile /// ``` #[macro_export] diff --git a/rust/qemu-api/src/bitops.rs b/rust/common/src/bitops.rs similarity index 98% rename from rust/qemu-api/src/bitops.rs rename to rust/common/src/bitops.rs index b1e3a530ab..06c78c3b8a 100644 --- a/rust/qemu-api/src/bitops.rs +++ b/rust/common/src/bitops.rs @@ -3,7 +3,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later =20 //! This module provides bit operation extensions to integer types. -//! It is usually included via the `qemu_api` prelude. =20 use std::ops::{ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitX= orAssign, Div, DivAssign, diff --git a/rust/qemu-api/src/callbacks.rs b/rust/common/src/callbacks.rs similarity index 97% rename from rust/qemu-api/src/callbacks.rs rename to rust/common/src/callbacks.rs index 9642a16eb8..676508a4b2 100644 --- a/rust/qemu-api/src/callbacks.rs +++ b/rust/common/src/callbacks.rs @@ -55,7 +55,7 @@ /// # Examples /// /// ``` -/// # use qemu_api::callbacks::FnCall; +/// # use common::callbacks::FnCall; /// fn call_it FnCall<(&'a str,), String>>(_f: &F, s: &str) -> = String { /// F::call((s,)) /// } @@ -71,7 +71,7 @@ /// Attempting to pass a non-zero-sized closure causes a compile-time fail= ure: /// /// ```compile_fail -/// # use qemu_api::callbacks::FnCall; +/// # use common::callbacks::FnCall; /// # fn call_it<'a, F: FnCall<(&'a str,), String>>(_f: &F, s: &'a str) ->= String { /// # F::call((s,)) /// # } @@ -82,7 +82,7 @@ /// `()` can be used to indicate "no function": /// /// ``` -/// # use qemu_api::callbacks::FnCall; +/// # use common::callbacks::FnCall; /// fn optional FnCall<(&'a str,), String>>(_f: &F, s: &str) ->= Option { /// if F::IS_SOME { /// Some(F::call((s,))) @@ -97,7 +97,7 @@ /// Invoking `F::call` will then be a run-time error. /// /// ```should_panic -/// # use qemu_api::callbacks::FnCall; +/// # use common::callbacks::FnCall; /// # fn call_it FnCall<(&'a str,), String>>(_f: &F, s: &str) -= > String { /// # F::call((s,)) /// # } @@ -125,7 +125,7 @@ pub unsafe trait FnCall: 'static + Sync= + Sized { /// # Examples /// /// ```compile_fail - /// # use qemu_api::callbacks::FnCall; + /// # use common::callbacks::FnCall; /// fn call_it FnCall<(&'a str,), String>>(_f: &F, s: &str)= -> String { /// let _: () =3D F::ASSERT_IS_SOME; /// F::call((s,)) @@ -145,7 +145,7 @@ pub unsafe trait FnCall: 'static + Sync= + Sized { /// You can use `IS_SOME` to catch this at compile time: /// /// ```compile_fail - /// # use qemu_api::callbacks::FnCall; + /// # use common::callbacks::FnCall; /// fn call_it FnCall<(&'a str,), String>>(_f: &F, s: &str)= -> String { /// const { assert!(F::IS_SOME) } /// F::call((s,)) diff --git a/rust/common/src/lib.rs b/rust/common/src/lib.rs new file mode 100644 index 0000000000..a956ebbd0b --- /dev/null +++ b/rust/common/src/lib.rs @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pub mod assertions; + +pub mod bitops; + +pub mod callbacks; +pub use callbacks::FnCall; + +pub mod opaque; +pub use opaque::{Opaque, Wrapper}; + +pub mod uninit; +pub use uninit::MaybeUninitField; + +pub mod zeroable; +pub use zeroable::Zeroable; diff --git a/rust/common/src/opaque.rs b/rust/common/src/opaque.rs new file mode 100644 index 0000000000..f96b91e25a --- /dev/null +++ b/rust/common/src/opaque.rs @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: MIT + +//! ## Opaque wrappers +//! +//! The cell types from the previous section are useful at the boundaries +//! of code that requires interior mutability. When writing glue code that +//! interacts directly with C structs, however, it is useful to operate +//! at a lower level. +//! +//! C functions often violate Rust's fundamental assumptions about memory +//! safety by modifying memory even if it is shared. Furthermore, C struc= ts +//! often start their life uninitialized and may be populated lazily. +//! +//! For this reason, this module provides the [`Opaque`] type to opt out +//! of Rust's usual guarantees about the wrapped type. Access to the wrapp= ed +//! value is always through raw pointers, obtained via methods like +//! [`as_mut_ptr()`](Opaque::as_mut_ptr) and [`as_ptr()`](Opaque::as_ptr).= These +//! pointers can then be passed to C functions or dereferenced; both actio= ns +//! require `unsafe` blocks, making it clear where safety guarantees must = be +//! manually verified. For example +//! +//! ```ignore +//! unsafe { +//! let state =3D Opaque::::uninit(); +//! qemu_struct_init(state.as_mut_ptr()); +//! } +//! ``` +//! +//! [`Opaque`] will usually be wrapped one level further, so that +//! bridge methods can be added to the wrapper: +//! +//! ```ignore +//! pub struct MyStruct(Opaque); +//! +//! impl MyStruct { +//! fn new() -> Pin> { +//! let result =3D Box::pin(unsafe { Opaque::uninit() }); +//! unsafe { qemu_struct_init(result.as_mut_ptr()) }; +//! result +//! } +//! } +//! ``` +//! +//! This pattern of wrapping bindgen-generated types in [`Opaque`] prov= ides +//! several advantages: +//! +//! * The choice of traits to be implemented is not limited by the +//! bindgen-generated code. For example, [`Drop`] can be added without +//! disabling [`Copy`] on the underlying bindgen type +//! +//! * [`Send`] and [`Sync`] implementations can be controlled by the wrapp= er +//! type rather than being automatically derived from the C struct's lay= out +//! +//! * Methods can be implemented in a separate crate from the bindgen-gene= rated +//! bindings +//! +//! * [`Debug`](std::fmt::Debug) and [`Display`](std::fmt::Display) +//! implementations can be customized to be more readable than the raw C +//! struct representation +//! +//! The [`Opaque`] type does not include BQL validation; it is possible= to +//! assert in the code that the right lock is taken, to use it together +//! with a custom lock guard type, or to let C code take the lock, as +//! appropriate. It is also possible to use it with non-thread-safe +//! types, since by default (unlike [`BqlCell`] and [`BqlRefCell`] +//! it is neither `Sync` nor `Send`. +//! +//! While [`Opaque`] is necessary for C interop, it should be used spar= ingly +//! and only at FFI boundaries. For QEMU-specific types that need interior +//! mutability, prefer [`BqlCell`] or [`BqlRefCell`]. +//! +//! [`BqlCell`]: ../../qemu_api/cell/struct.BqlCell.html +//! [`BqlRefCell`]: ../../qemu_api/cell/struct.BqlRefCell.html +use std::{cell::UnsafeCell, fmt, marker::PhantomPinned, mem::MaybeUninit, = ptr::NonNull}; + +/// Stores an opaque value that is shared with C code. +/// +/// Often, C structs can changed when calling a C function even if they are +/// behind a shared Rust reference, or they can be initialized lazily and = have +/// invalid bit patterns (e.g. `3` for a [`bool`]). This goes against Rus= t's +/// strict aliasing rules, which normally prevent mutation through shared +/// references. +/// +/// Wrapping the struct with `Opaque` ensures that the Rust compiler do= es not +/// assume the usual constraints that Rust structs require, and allows usi= ng +/// shared references on the Rust side. +/// +/// `Opaque` is `#[repr(transparent)]`, so that it matches the memory l= ayout +/// of `T`. +#[repr(transparent)] +pub struct Opaque { + value: UnsafeCell>, + // PhantomPinned also allows multiple references to the `Opaque`, i= .e. + // one `&mut Opaque` can coexist with a `&mut T` or any number of `= &T`; + // see https://docs.rs/pinned-aliasable/latest/pinned_aliasable/. + _pin: PhantomPinned, +} + +impl Opaque { + /// Creates a new shared reference from a C pointer + /// + /// # Safety + /// + /// The pointer must be valid, though it need not point to a valid val= ue. + pub unsafe fn from_raw<'a>(ptr: *mut T) -> &'a Self { + let ptr =3D NonNull::new(ptr).unwrap().cast::(); + // SAFETY: Self is a transparent wrapper over T + unsafe { ptr.as_ref() } + } + + /// Creates a new opaque object with uninitialized contents. + /// + /// # Safety + /// + /// Ultimately the pointer to the returned value will be dereferenced + /// in another `unsafe` block, for example when passing it to a C func= tion, + /// but the functions containing the dereference are usually safe. The + /// value returned from `uninit()` must be initialized and pinned befo= re + /// calling them. + #[allow(clippy::missing_const_for_fn)] + pub unsafe fn uninit() -> Self { + Self { + value: UnsafeCell::new(MaybeUninit::uninit()), + _pin: PhantomPinned, + } + } + + /// Creates a new opaque object with zeroed contents. + /// + /// # Safety + /// + /// Ultimately the pointer to the returned value will be dereferenced + /// in another `unsafe` block, for example when passing it to a C func= tion, + /// but the functions containing the dereference are usually safe. The + /// value returned from `uninit()` must be pinned (and possibly initia= lized) + /// before calling them. + #[allow(clippy::missing_const_for_fn)] + pub unsafe fn zeroed() -> Self { + Self { + value: UnsafeCell::new(MaybeUninit::zeroed()), + _pin: PhantomPinned, + } + } + + /// Returns a raw mutable pointer to the opaque data. + pub const fn as_mut_ptr(&self) -> *mut T { + UnsafeCell::get(&self.value).cast() + } + + /// Returns a raw pointer to the opaque data. + pub const fn as_ptr(&self) -> *const T { + self.as_mut_ptr().cast_const() + } + + /// Returns a raw pointer to the opaque data that can be passed to a + /// C function as `void *`. + pub const fn as_void_ptr(&self) -> *mut std::ffi::c_void { + UnsafeCell::get(&self.value).cast() + } + + /// Converts a raw pointer to the wrapped type. + pub const fn raw_get(slot: *mut Self) -> *mut T { + // Compare with Linux's raw_get method, which goes through an Unsa= feCell + // because it takes a *const Self instead. + slot.cast() + } +} + +impl fmt::Debug for Opaque { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut name: String =3D "Opaque<".to_string(); + name +=3D std::any::type_name::(); + name +=3D ">"; + f.debug_tuple(&name).field(&self.as_ptr()).finish() + } +} + +impl Opaque { + /// Creates a new opaque object with default contents. + /// + /// # Safety + /// + /// Ultimately the pointer to the returned value will be dereferenced + /// in another `unsafe` block, for example when passing it to a C func= tion, + /// but the functions containing the dereference are usually safe. The + /// value returned from `uninit()` must be pinned before calling them. + pub unsafe fn new() -> Self { + Self { + value: UnsafeCell::new(MaybeUninit::new(T::default())), + _pin: PhantomPinned, + } + } +} + +/// Annotates [`Self`] as a transparent wrapper for another type. +/// +/// Usually defined via the [`qemu_api_macros::Wrapper`] derive macro. +/// +/// # Examples +/// +/// ``` +/// # use std::mem::ManuallyDrop; +/// # use common::opaque::Wrapper; +/// #[repr(transparent)] +/// pub struct Example { +/// inner: ManuallyDrop, +/// } +/// +/// unsafe impl Wrapper for Example { +/// type Wrapped =3D String; +/// } +/// ``` +/// +/// # Safety +/// +/// `Self` must be a `#[repr(transparent)]` wrapper for the `Wrapped` type, +/// whether directly or indirectly. +/// +/// # Methods +/// +/// By convention, types that implement Wrapper also implement the followi= ng +/// methods: +/// +/// ```ignore +/// pub const unsafe fn from_raw<'a>(value: *mut Self::Wrapped) -> &'a Sel= f; +/// pub const unsafe fn as_mut_ptr(&self) -> *mut Self::Wrapped; +/// pub const unsafe fn as_ptr(&self) -> *const Self::Wrapped; +/// pub const unsafe fn raw_get(slot: *mut Self) -> *const Self::Wrapped; +/// ``` +/// +/// They are not defined here to allow them to be `const`. +/// +/// [`qemu_api_macros::Wrapper`]: ../../qemu_api_macros/derive.Wrapper.html +pub unsafe trait Wrapper { + type Wrapped; +} + +unsafe impl Wrapper for Opaque { + type Wrapped =3D T; +} diff --git a/rust/qemu-api/src/uninit.rs b/rust/common/src/uninit.rs similarity index 98% rename from rust/qemu-api/src/uninit.rs rename to rust/common/src/uninit.rs index 04123b4ae9..1a1adfbb0d 100644 --- a/rust/qemu-api/src/uninit.rs +++ b/rust/common/src/uninit.rs @@ -63,7 +63,7 @@ fn deref_mut(&mut self) -> &mut MaybeUninit { /// } /// /// # use std::mem::MaybeUninit; -/// # use qemu_api::{assert_match, uninit_field_mut}; +/// # use common::{assert_match, uninit_field_mut}; /// /// let mut s: MaybeUninit =3D MaybeUninit::zeroed(); /// uninit_field_mut!(s, x).write(5); diff --git a/rust/common/src/zeroable.rs b/rust/common/src/zeroable.rs new file mode 100644 index 0000000000..fd056deb1f --- /dev/null +++ b/rust/common/src/zeroable.rs @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +//! Defines a trait for structs that can be safely initialized with zero b= ytes. + +/// Encapsulates the requirement that +/// `MaybeUninit::::zeroed().assume_init()` does not cause undefined +/// behavior. +/// +/// # Safety +/// +/// Do not add this trait to a type unless all-zeroes is a valid value for= the +/// type. In particular, raw pointers can be zero, but references and +/// `NonNull` cannot. +pub unsafe trait Zeroable: Default { + /// Return a value of Self whose memory representation consists of all + /// zeroes, with the possible exclusion of padding bytes. + const ZERO: Self =3D unsafe { ::core::mem::MaybeUninit::::zeroed= ().assume_init() }; +} diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml index 88ef110507..6d15f107df 100644 --- a/rust/hw/char/pl011/Cargo.toml +++ b/rust/hw/char/pl011/Cargo.toml @@ -16,6 +16,7 @@ rust-version.workspace =3D true bilge =3D { version =3D "0.2.0" } bilge-impl =3D { version =3D "0.2.0" } bits =3D { path =3D "../../../bits" } +common =3D { path =3D "../../../common" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build index 2a1be329ab..67bd295c3d 100644 --- a/rust/hw/char/pl011/meson.build +++ b/rust/hw/char/pl011/meson.build @@ -7,6 +7,7 @@ _libpl011_rs =3D static_library( bilge_rs, bilge_impl_rs, bits_rs, + common_rs, qemu_api, qemu_api_macros, ], diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index ceb71dd99b..0c27c42c31 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -8,6 +8,7 @@ ptr::NonNull, }; =20 +use common::{static_assert, uninit_field_mut, Zeroable}; use qemu_api::{ bindings::{qdev_prop_bool, qdev_prop_chr}, chardev::{CharBackend, Chardev, Event}, @@ -19,12 +20,9 @@ prelude::*, qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType= , ResettablePhasesImpl}, qom::{ObjectImpl, Owned, ParentField, ParentInit}, - static_assert, sysbus::{SysBusDevice, SysBusDeviceImpl}, - uninit_field_mut, vmstate::VMStateDescription, vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct, vmstate_sub= sections, vmstate_unused, - zeroable::Zeroable, }; =20 use crate::registers::{self, Interrupt, RegisterOffset}; diff --git a/rust/hw/timer/hpet/Cargo.toml b/rust/hw/timer/hpet/Cargo.toml index ac5df23c1d..ba7354f07e 100644 --- a/rust/hw/timer/hpet/Cargo.toml +++ b/rust/hw/timer/hpet/Cargo.toml @@ -11,6 +11,7 @@ repository.workspace =3D true rust-version.workspace =3D true =20 [dependencies] +common =3D { path =3D "../../../common" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/timer/hpet/meson.build b/rust/hw/timer/hpet/meson.build index c2d7c0532c..05f8bd240a 100644 --- a/rust/hw/timer/hpet/meson.build +++ b/rust/hw/timer/hpet/meson.build @@ -4,6 +4,7 @@ _libhpet_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', dependencies: [ + common_rs, qemu_api, qemu_api_macros, ], diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index acf7251029..f3c324f243 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -10,6 +10,7 @@ slice::from_ref, }; =20 +use common::{bitops::IntegerExt, uninit_field_mut, Zeroable}; use qemu_api::{ bindings::{ address_space_memory, address_space_stl_le, qdev_prop_bit, qdev_pr= op_bool, @@ -26,10 +27,8 @@ qom_isa, sysbus::{SysBusDevice, SysBusDeviceImpl}, timer::{Timer, CLOCK_VIRTUAL, NANOSECONDS_PER_SECOND}, - uninit_field_mut, vmstate::VMStateDescription, vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmsta= te_validate, - zeroable::Zeroable, }; =20 use crate::fw_cfg::HPETFwConfig; diff --git a/rust/hw/timer/hpet/src/fw_cfg.rs b/rust/hw/timer/hpet/src/fw_c= fg.rs index 619d662ee1..0605225fbb 100644 --- a/rust/hw/timer/hpet/src/fw_cfg.rs +++ b/rust/hw/timer/hpet/src/fw_cfg.rs @@ -4,7 +4,8 @@ =20 use std::ptr::addr_of_mut; =20 -use qemu_api::{cell::bql_locked, zeroable::Zeroable}; +use common::Zeroable; +use qemu_api::cell::bql_locked; =20 /// Each `HPETState` represents a Event Timer Block. The v1 spec supports /// up to 8 blocks. QEMU only uses 1 block (in PC machine). diff --git a/rust/meson.build b/rust/meson.build index 331f11b7e7..402f8d6600 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -22,6 +22,7 @@ qemuutil_rs =3D qemuutil.partial_dependency(link_args: tr= ue, links: true) =20 genrs =3D [] =20 +subdir('common') subdir('qemu-api-macros') subdir('bits') subdir('qemu-api') diff --git a/rust/qemu-api-macros/src/lib.rs b/rust/qemu-api-macros/src/lib= .rs index b525d89c09..850e3b1596 100644 --- a/rust/qemu-api-macros/src/lib.rs +++ b/rust/qemu-api-macros/src/lib.rs @@ -88,7 +88,7 @@ fn derive_object_or_error(input: DeriveInput) -> Result::ParentType>); =20 ::qemu_api::module_init! { @@ -118,20 +118,20 @@ fn derive_opaque_or_error(input: DeriveInput) -> Resu= lt::Wrapped; + unsafe impl ::common::opaque::Wrapper for #name { + type Wrapped =3D <#typ as ::common::opaque::Wrapper>::Wrapped; } impl #name { - pub unsafe fn from_raw<'a>(ptr: *mut ::Wrapped) -> &'a Self { + pub unsafe fn from_raw<'a>(ptr: *mut ::Wrapped) -> &'a Self { let ptr =3D ::std::ptr::NonNull::new(ptr).unwrap().cast::<= Self>(); unsafe { ptr.as_ref() } } =20 - pub const fn as_mut_ptr(&self) -> *mut ::Wrapped { + pub const fn as_mut_ptr(&self) -> *mut ::Wrapped { self.0.as_mut_ptr() } =20 - pub const fn as_ptr(&self) -> *const ::Wrapped { + pub const fn as_ptr(&self) -> *const ::Wrapped { self.0.as_ptr() } =20 @@ -139,7 +139,7 @@ pub const fn as_void_ptr(&self) -> *mut ::core::ffi::c_= void { self.0.as_void_ptr() } =20 - pub const fn raw_get(slot: *mut Self) -> *mut ::Wrapped { + pub const fn raw_get(slot: *mut Self) -> *mut ::Wrapped { slot.cast() } } diff --git a/rust/qemu-api-macros/src/tests.rs b/rust/qemu-api-macros/src/t= ests.rs index d6dcd62fcf..42d5fa50bd 100644 --- a/rust/qemu-api-macros/src/tests.rs +++ b/rust/qemu-api-macros/src/tests.rs @@ -58,7 +58,7 @@ struct Foo { } }, quote! { - ::qemu_api::assert_field_type!( + ::common::assert_field_type!( Foo, _unused, ::qemu_api::qom::ParentField<::ParentType> diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index 603327945f..12774c356a 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -14,6 +14,7 @@ repository.workspace =3D true rust-version.workspace =3D true =20 [dependencies] +common =3D { path =3D "../common" } qemu_api_macros =3D { path =3D "../qemu-api-macros" } anyhow =3D "~1.0" libc =3D "0.2.162" diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index 062009f161..6177e26819 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -52,10 +52,7 @@ _qemu_api_rs =3D static_library( structured_sources( [ 'src/lib.rs', - 'src/assertions.rs', 'src/bindings.rs', - 'src/bitops.rs', - 'src/callbacks.rs', 'src/cell.rs', 'src/chardev.rs', 'src/errno.rs', @@ -69,16 +66,14 @@ _qemu_api_rs =3D static_library( 'src/qom.rs', 'src/sysbus.rs', 'src/timer.rs', - 'src/uninit.rs', 'src/vmstate.rs', - 'src/zeroable.rs', ], {'.' : _qemu_api_bindings_inc_rs}, ), override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _qemu_api_cfg, - dependencies: [anyhow_rs, foreign_rs, libc_rs, qemu_api_macros, qemuutil= _rs, + dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, qemu_api_macro= s, qemuutil_rs, qom, hwcore, chardev, migration], ) =20 @@ -104,7 +99,7 @@ test('rust-qemu-api-integration', override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_args: ['--test'], install: false, - dependencies: [qemu_api]), + dependencies: [common_rs, qemu_api]), args: [ '--test', '--test-threads', '1', '--format', 'pretty', diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs index b8104dea8b..3acdd903b5 100644 --- a/rust/qemu-api/src/bindings.rs +++ b/rust/qemu-api/src/bindings.rs @@ -20,6 +20,8 @@ =20 //! `bindgen`-generated declarations. =20 +use common::Zeroable; + #[cfg(MESON)] include!("bindings.inc.rs"); =20 @@ -56,3 +58,22 @@ unsafe impl Sync for VMStateField {} =20 unsafe impl Send for VMStateInfo {} unsafe impl Sync for VMStateInfo {} + +// bindgen does not derive Default here +#[allow(clippy::derivable_impls)] +impl Default for crate::bindings::VMStateFlags { + fn default() -> Self { + Self(0) + } +} + +unsafe impl Zeroable for crate::bindings::Property__bindgen_ty_1 {} +unsafe impl Zeroable for crate::bindings::Property {} +unsafe impl Zeroable for crate::bindings::VMStateFlags {} +unsafe impl Zeroable for crate::bindings::VMStateField {} +unsafe impl Zeroable for crate::bindings::VMStateDescription {} +unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_1 {} +unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_2 {} +unsafe impl Zeroable for crate::bindings::MemoryRegionOps {} +unsafe impl Zeroable for crate::bindings::MemTxAttrs {} +unsafe impl Zeroable for crate::bindings::CharBackend {} diff --git a/rust/qemu-api/src/cell.rs b/rust/qemu-api/src/cell.rs index 27063b049d..98d720caf9 100644 --- a/rust/qemu-api/src/cell.rs +++ b/rust/qemu-api/src/cell.rs @@ -141,82 +141,13 @@ //! Multiple immutable borrows are allowed via [`borrow`](BqlRefCell::borr= ow), //! or a single mutable borrow via [`borrow_mut`](BqlRefCell::borrow_mut).= The //! thread will panic if these rules are violated or if the BQL is not hel= d. -//! -//! ## Opaque wrappers -//! -//! The cell types from the previous section are useful at the boundaries -//! of code that requires interior mutability. When writing glue code that -//! interacts directly with C structs, however, it is useful to operate -//! at a lower level. -//! -//! C functions often violate Rust's fundamental assumptions about memory -//! safety by modifying memory even if it is shared. Furthermore, C struc= ts -//! often start their life uninitialized and may be populated lazily. -//! -//! For this reason, this module provides the [`Opaque`] type to opt out -//! of Rust's usual guarantees about the wrapped type. Access to the wrapp= ed -//! value is always through raw pointers, obtained via methods like -//! [`as_mut_ptr()`](Opaque::as_mut_ptr) and [`as_ptr()`](Opaque::as_ptr).= These -//! pointers can then be passed to C functions or dereferenced; both actio= ns -//! require `unsafe` blocks, making it clear where safety guarantees must = be -//! manually verified. For example -//! -//! ```ignore -//! unsafe { -//! let state =3D Opaque::::uninit(); -//! qemu_struct_init(state.as_mut_ptr()); -//! } -//! ``` -//! -//! [`Opaque`] will usually be wrapped one level further, so that -//! bridge methods can be added to the wrapper: -//! -//! ```ignore -//! pub struct MyStruct(Opaque); -//! -//! impl MyStruct { -//! fn new() -> Pin> { -//! let result =3D Box::pin(unsafe { Opaque::uninit() }); -//! unsafe { qemu_struct_init(result.as_mut_ptr()) }; -//! result -//! } -//! } -//! ``` -//! -//! This pattern of wrapping bindgen-generated types in [`Opaque`] prov= ides -//! several advantages: -//! -//! * The choice of traits to be implemented is not limited by the -//! bindgen-generated code. For example, [`Drop`] can be added without -//! disabling [`Copy`] on the underlying bindgen type -//! -//! * [`Send`] and [`Sync`] implementations can be controlled by the wrapp= er -//! type rather than being automatically derived from the C struct's lay= out -//! -//! * Methods can be implemented in a separate crate from the bindgen-gene= rated -//! bindings -//! -//! * [`Debug`](std::fmt::Debug) and [`Display`](std::fmt::Display) -//! implementations can be customized to be more readable than the raw C -//! struct representation -//! -//! The [`Opaque`] type does not include BQL validation; it is possible= to -//! assert in the code that the right lock is taken, to use it together -//! with a custom lock guard type, or to let C code take the lock, as -//! appropriate. It is also possible to use it with non-thread-safe -//! types, since by default (unlike [`BqlCell`] and [`BqlRefCell`] -//! it is neither `Sync` nor `Send`. -//! -//! While [`Opaque`] is necessary for C interop, it should be used spar= ingly -//! and only at FFI boundaries. For QEMU-specific types that need interior -//! mutability, prefer [`BqlCell`] or [`BqlRefCell`]. =20 use std::{ cell::{Cell, UnsafeCell}, cmp::Ordering, fmt, - marker::{PhantomData, PhantomPinned}, - mem::{self, MaybeUninit}, + marker::PhantomData, + mem, ops::{Deref, DerefMut}, ptr::NonNull, }; @@ -935,167 +866,3 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Res= ult { (**self).fmt(f) } } - -/// Stores an opaque value that is shared with C code. -/// -/// Often, C structs can changed when calling a C function even if they are -/// behind a shared Rust reference, or they can be initialized lazily and = have -/// invalid bit patterns (e.g. `3` for a [`bool`]). This goes against Rus= t's -/// strict aliasing rules, which normally prevent mutation through shared -/// references. -/// -/// Wrapping the struct with `Opaque` ensures that the Rust compiler do= es not -/// assume the usual constraints that Rust structs require, and allows usi= ng -/// shared references on the Rust side. -/// -/// `Opaque` is `#[repr(transparent)]`, so that it matches the memory l= ayout -/// of `T`. -#[repr(transparent)] -pub struct Opaque { - value: UnsafeCell>, - // PhantomPinned also allows multiple references to the `Opaque`, i= .e. - // one `&mut Opaque` can coexist with a `&mut T` or any number of `= &T`; - // see https://docs.rs/pinned-aliasable/latest/pinned_aliasable/. - _pin: PhantomPinned, -} - -impl Opaque { - /// Creates a new shared reference from a C pointer - /// - /// # Safety - /// - /// The pointer must be valid, though it need not point to a valid val= ue. - pub unsafe fn from_raw<'a>(ptr: *mut T) -> &'a Self { - let ptr =3D NonNull::new(ptr).unwrap().cast::(); - // SAFETY: Self is a transparent wrapper over T - unsafe { ptr.as_ref() } - } - - /// Creates a new opaque object with uninitialized contents. - /// - /// # Safety - /// - /// Ultimately the pointer to the returned value will be dereferenced - /// in another `unsafe` block, for example when passing it to a C func= tion, - /// but the functions containing the dereference are usually safe. The - /// value returned from `uninit()` must be initialized and pinned befo= re - /// calling them. - #[allow(clippy::missing_const_for_fn)] - pub unsafe fn uninit() -> Self { - Self { - value: UnsafeCell::new(MaybeUninit::uninit()), - _pin: PhantomPinned, - } - } - - /// Creates a new opaque object with zeroed contents. - /// - /// # Safety - /// - /// Ultimately the pointer to the returned value will be dereferenced - /// in another `unsafe` block, for example when passing it to a C func= tion, - /// but the functions containing the dereference are usually safe. The - /// value returned from `uninit()` must be pinned (and possibly initia= lized) - /// before calling them. - #[allow(clippy::missing_const_for_fn)] - pub unsafe fn zeroed() -> Self { - Self { - value: UnsafeCell::new(MaybeUninit::zeroed()), - _pin: PhantomPinned, - } - } - - /// Returns a raw mutable pointer to the opaque data. - pub const fn as_mut_ptr(&self) -> *mut T { - UnsafeCell::get(&self.value).cast() - } - - /// Returns a raw pointer to the opaque data. - pub const fn as_ptr(&self) -> *const T { - self.as_mut_ptr().cast_const() - } - - /// Returns a raw pointer to the opaque data that can be passed to a - /// C function as `void *`. - pub const fn as_void_ptr(&self) -> *mut std::ffi::c_void { - UnsafeCell::get(&self.value).cast() - } - - /// Converts a raw pointer to the wrapped type. - pub const fn raw_get(slot: *mut Self) -> *mut T { - // Compare with Linux's raw_get method, which goes through an Unsa= feCell - // because it takes a *const Self instead. - slot.cast() - } -} - -impl fmt::Debug for Opaque { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut name: String =3D "Opaque<".to_string(); - name +=3D std::any::type_name::(); - name +=3D ">"; - f.debug_tuple(&name).field(&self.as_ptr()).finish() - } -} - -impl Opaque { - /// Creates a new opaque object with default contents. - /// - /// # Safety - /// - /// Ultimately the pointer to the returned value will be dereferenced - /// in another `unsafe` block, for example when passing it to a C func= tion, - /// but the functions containing the dereference are usually safe. The - /// value returned from `uninit()` must be pinned before calling them. - pub unsafe fn new() -> Self { - Self { - value: UnsafeCell::new(MaybeUninit::new(T::default())), - _pin: PhantomPinned, - } - } -} - -/// Annotates [`Self`] as a transparent wrapper for another type. -/// -/// Usually defined via the [`qemu_api_macros::Wrapper`] derive macro. -/// -/// # Examples -/// -/// ``` -/// # use std::mem::ManuallyDrop; -/// # use qemu_api::cell::Wrapper; -/// #[repr(transparent)] -/// pub struct Example { -/// inner: ManuallyDrop, -/// } -/// -/// unsafe impl Wrapper for Example { -/// type Wrapped =3D String; -/// } -/// ``` -/// -/// # Safety -/// -/// `Self` must be a `#[repr(transparent)]` wrapper for the `Wrapped` type, -/// whether directly or indirectly. -/// -/// # Methods -/// -/// By convention, types that implement Wrapper also implement the followi= ng -/// methods: -/// -/// ```ignore -/// pub const unsafe fn from_raw<'a>(value: *mut Self::Wrapped) -> &'a Sel= f; -/// pub const unsafe fn as_mut_ptr(&self) -> *mut Self::Wrapped; -/// pub const unsafe fn as_ptr(&self) -> *const Self::Wrapped; -/// pub const unsafe fn raw_get(slot: *mut Self) -> *const Self::Wrapped; -/// ``` -/// -/// They are not defined here to allow them to be `const`. -pub unsafe trait Wrapper { - type Wrapped; -} - -unsafe impl Wrapper for Opaque { - type Wrapped =3D T; -} diff --git a/rust/qemu-api/src/chardev.rs b/rust/qemu-api/src/chardev.rs index 6e0590d758..e2cb5f4379 100644 --- a/rust/qemu-api/src/chardev.rs +++ b/rust/qemu-api/src/chardev.rs @@ -18,10 +18,11 @@ slice, }; =20 +use common::{callbacks::FnCall, Opaque}; + use crate::{ bindings, - callbacks::FnCall, - cell::{BqlRefMut, Opaque}, + cell::{BqlRefCell, BqlRefMut}, prelude::*, }; =20 diff --git a/rust/qemu-api/src/errno.rs b/rust/qemu-api/src/errno.rs index 18d101448b..e9478c4eb4 100644 --- a/rust/qemu-api/src/errno.rs +++ b/rust/qemu-api/src/errno.rs @@ -240,8 +240,9 @@ pub fn into_neg_errno>(va= lue: Result) -> T:: mod tests { use std::io::ErrorKind; =20 + use common::assert_match; + use super::*; - use crate::assert_match; =20 #[test] pub fn test_from_u8() { diff --git a/rust/qemu-api/src/error.rs b/rust/qemu-api/src/error.rs index e114fc4178..8bac3cbec8 100644 --- a/rust/qemu-api/src/error.rs +++ b/rust/qemu-api/src/error.rs @@ -316,10 +316,11 @@ mod tests { use std::ffi::CStr; =20 use anyhow::anyhow; + use common::assert_match; use foreign::OwnedPointer; =20 use super::*; - use crate::{assert_match, bindings}; + use crate::bindings; =20 #[track_caller] fn error_for_test(msg: &CStr) -> OwnedPointer { diff --git a/rust/qemu-api/src/irq.rs b/rust/qemu-api/src/irq.rs index 1526e6f63a..ea6b32848c 100644 --- a/rust/qemu-api/src/irq.rs +++ b/rust/qemu-api/src/irq.rs @@ -10,9 +10,10 @@ ptr, }; =20 +use common::Opaque; + use crate::{ bindings::{self, qemu_set_irq}, - cell::Opaque, prelude::*, qom::ObjectClass, }; diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 0f9231f398..7a2b29f28f 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -13,9 +13,6 @@ #[rustfmt::skip] pub mod prelude; =20 -pub mod assertions; -pub mod bitops; -pub mod callbacks; pub mod cell; pub mod chardev; pub mod errno; @@ -28,8 +25,6 @@ pub mod qom; pub mod sysbus; pub mod timer; -pub mod uninit; pub mod vmstate; -pub mod zeroable; =20 pub use error::{Error, Result}; diff --git a/rust/qemu-api/src/memory.rs b/rust/qemu-api/src/memory.rs index e40fad6cf1..f790cb5fd2 100644 --- a/rust/qemu-api/src/memory.rs +++ b/rust/qemu-api/src/memory.rs @@ -10,14 +10,11 @@ }; =20 pub use bindings::{hwaddr, MemTxAttrs}; +use common::{callbacks::FnCall, uninit::MaybeUninitField, zeroable::Zeroab= le, Opaque}; =20 use crate::{ bindings::{self, device_endian, memory_region_init_io}, - callbacks::FnCall, - cell::Opaque, prelude::*, - uninit::MaybeUninitField, - zeroable::Zeroable, }; =20 pub struct MemoryRegionOps( diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs index 8f9e23ee2c..ad157f9655 100644 --- a/rust/qemu-api/src/prelude.rs +++ b/rust/qemu-api/src/prelude.rs @@ -4,8 +4,6 @@ =20 //! Commonly used traits and types for QEMU. =20 -pub use crate::bitops::IntegerExt; - pub use crate::cell::BqlCell; pub use crate::cell::BqlRefCell; =20 @@ -19,8 +17,8 @@ pub use crate::qom::IsA; pub use crate::qom::Object; pub use crate::qom::ObjectCast; -pub use crate::qom::ObjectDeref; pub use crate::qom::ObjectClassMethods; +pub use crate::qom::ObjectDeref; pub use crate::qom::ObjectMethods; pub use crate::qom::ObjectType; =20 diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs index 36f02fb57d..bf17558cdb 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/qemu-api/src/qdev.rs @@ -10,11 +10,11 @@ }; =20 pub use bindings::{ClockEvent, DeviceClass, Property, ResetType}; +use common::{callbacks::FnCall, Opaque}; =20 use crate::{ bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, ResettableClas= s}, - callbacks::FnCall, - cell::{bql_locked, Opaque}, + cell::bql_locked, chardev::Chardev, error::{Error, Result}, irq::InterruptSource, @@ -198,7 +198,7 @@ macro_rules! define_property { bitnr: $bitnr, set_default: true, defval: $crate::bindings::Property__bindgen_ty_1 { u: $defval = as u64 }, - ..$crate::zeroable::Zeroable::ZERO + ..::common::zeroable::Zeroable::ZERO } }; ($name:expr, $state:ty, $field:ident, $prop:expr, $type:ty, default = =3D $defval:expr$(,)*) =3D> { @@ -209,7 +209,7 @@ macro_rules! define_property { offset: ::std::mem::offset_of!($state, $field) as isize, set_default: true, defval: $crate::bindings::Property__bindgen_ty_1 { u: $defval = as u64 }, - ..$crate::zeroable::Zeroable::ZERO + ..::common::zeroable::Zeroable::ZERO } }; ($name:expr, $state:ty, $field:ident, $prop:expr, $type:ty$(,)*) =3D> { @@ -219,7 +219,7 @@ macro_rules! define_property { info: $prop, offset: ::std::mem::offset_of!($state, $field) as isize, set_default: false, - ..$crate::zeroable::Zeroable::ZERO + ..::common::zeroable::Zeroable::ZERO } }; } diff --git a/rust/qemu-api/src/qom.rs b/rust/qemu-api/src/qom.rs index e20ee014cb..c2f9a682bb 100644 --- a/rust/qemu-api/src/qom.rs +++ b/rust/qemu-api/src/qom.rs @@ -102,13 +102,14 @@ }; =20 pub use bindings::ObjectClass; +use common::Opaque; =20 use crate::{ bindings::{ self, object_class_dynamic_cast, object_dynamic_cast, object_get_c= lass, object_get_typename, object_new, object_ref, object_unref, TypeInf= o, }, - cell::{bql_locked, Opaque}, + cell::bql_locked, }; =20 /// A safe wrapper around [`bindings::Object`]. diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs index e92502a8fe..4a5b4cbbf6 100644 --- a/rust/qemu-api/src/sysbus.rs +++ b/rust/qemu-api/src/sysbus.rs @@ -7,10 +7,11 @@ use std::{ffi::CStr, ptr::addr_of_mut}; =20 pub use bindings::SysBusDeviceClass; +use common::Opaque; =20 use crate::{ bindings, - cell::{bql_locked, Opaque}, + cell::bql_locked, irq::{IRQState, InterruptSource}, memory::MemoryRegion, prelude::*, diff --git a/rust/qemu-api/src/timer.rs b/rust/qemu-api/src/timer.rs index 0a2d111d49..441072a949 100644 --- a/rust/qemu-api/src/timer.rs +++ b/rust/qemu-api/src/timer.rs @@ -7,10 +7,10 @@ pin::Pin, }; =20 -use crate::{ - bindings::{self, qemu_clock_get_ns, timer_del, timer_init_full, timer_= mod, QEMUClockType}, - callbacks::FnCall, - cell::Opaque, +use common::{callbacks::FnCall, Opaque}; + +use crate::bindings::{ + self, qemu_clock_get_ns, timer_del, timer_init_full, timer_mod, QEMUCl= ockType, }; =20 /// A safe wrapper around [`bindings::QEMUTimer`]. diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs index 812f390d78..6a9cc0b975 100644 --- a/rust/qemu-api/src/vmstate.rs +++ b/rust/qemu-api/src/vmstate.rs @@ -27,10 +27,10 @@ use core::{marker::PhantomData, mem, ptr::NonNull}; use std::ffi::{c_int, c_void}; =20 +use common::{callbacks::FnCall, Zeroable}; + pub use crate::bindings::{VMStateDescription, VMStateField}; -use crate::{ - bindings::VMStateFlags, callbacks::FnCall, prelude::*, qom::Owned, zer= oable::Zeroable, -}; +use crate::{bindings::VMStateFlags, prelude::*, qom::Owned}; =20 /// This macro is used to call a function with a generic argument bound /// to the type of a field. The function must take a @@ -343,7 +343,7 @@ unsafe impl<$base> VMState for $type where $base: VMSta= te $($where)* { impl_vmstate_transparent!(std::pin::Pin where T: VMState); impl_vmstate_transparent!(crate::cell::BqlCell where T: VMState); impl_vmstate_transparent!(crate::cell::BqlRefCell where T: VMState); -impl_vmstate_transparent!(crate::cell::Opaque where T: VMState); +impl_vmstate_transparent!(::common::Opaque where T: VMState); =20 #[macro_export] macro_rules! impl_vmstate_bitsized { @@ -431,7 +431,7 @@ macro_rules! vmstate_unused { size: $size, info: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate= _info_unused_buffer) }, flags: $crate::bindings::VMStateFlags::VMS_BUFFER, - ..$crate::zeroable::Zeroable::ZERO + ..::common::zeroable::Zeroable::ZERO } }}; } @@ -454,7 +454,7 @@ pub extern "C" fn rust_vms_test_field_exists {{ - const fn test_cb_builder__ $crate::callbacks::FnCall= <(&'a T, u8), bool>>( + const fn test_cb_builder__ ::common::callbacks::FnCa= ll<(&'a T, u8), bool>>( _phantom: ::core::marker::PhantomData, ) -> $crate::vmstate::VMSFieldExistCb { let _: () =3D F::ASSERT_IS_SOME; @@ -485,14 +485,14 @@ macro_rules! vmstate_struct { .as_ptr() as *const ::std::os::raw::c_char, $(num_offset: ::std::mem::offset_of!($struct_name, $num),)? offset: { - $crate::assert_field_type!($struct_name, $field_name, $typ= e $(, num =3D $num)?); + ::common::assert_field_type!($struct_name, $field_name, $t= ype $(, num =3D $num)?); ::std::mem::offset_of!($struct_name, $field_name) }, 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 + ..::common::zeroable::Zeroable::ZERO } $(.with_varray_flag_unchecked( $crate::call_func_with_field!( $crate::vmstate::vmstate_varray_flag, @@ -513,7 +513,7 @@ macro_rules! vmstate_clock { .as_bytes() .as_ptr() as *const ::std::os::raw::c_char, offset: { - $crate::assert_field_type!( + ::common::assert_field_type!( $struct_name, $field_name, $crate::qom::Owned<$crate::qdev::Clock> $(, num =3D $n= um)? @@ -526,7 +526,7 @@ macro_rules! vmstate_clock { | $crate::bindings::VMStateFlags::VMS_POINTER.0, ), vmsd: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate= _clock) }, - ..$crate::zeroable::Zeroable::ZERO + ..::common::zeroable::Zeroable::ZERO } $(.with_varray_flag_unchecked( $crate::call_func_with_field!( $crate::vmstate::vmstate_varray_flag, @@ -548,7 +548,7 @@ macro_rules! vmstate_fields { $($field),*, $crate::bindings::VMStateField { flags: $crate::bindings::VMStateFlags::VMS_END, - ..$crate::zeroable::Zeroable::ZERO + ..::common::zeroable::Zeroable::ZERO } ]; _FIELDS.as_ptr() @@ -567,7 +567,7 @@ macro_rules! vmstate_validate { | $crate::bindings::VMStateFlags::VMS_ARRAY.0, ), num: 0, // 0 elements: no data, only run test_fn callback - ..$crate::zeroable::Zeroable::ZERO + ..::common::zeroable::Zeroable::ZERO } }; } diff --git a/rust/qemu-api/src/zeroable.rs b/rust/qemu-api/src/zeroable.rs deleted file mode 100644 index d8239d0856..0000000000 --- a/rust/qemu-api/src/zeroable.rs +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -//! Defines a trait for structs that can be safely initialized with zero b= ytes. - -/// Encapsulates the requirement that -/// `MaybeUninit::::zeroed().assume_init()` does not cause undefined -/// behavior. -/// -/// # Safety -/// -/// Do not add this trait to a type unless all-zeroes is a valid value for= the -/// type. In particular, raw pointers can be zero, but references and -/// `NonNull` cannot. -pub unsafe trait Zeroable: Default { - /// Return a value of Self whose memory representation consists of all - /// zeroes, with the possible exclusion of padding bytes. - const ZERO: Self =3D unsafe { ::core::mem::MaybeUninit::::zeroed= ().assume_init() }; -} - -// bindgen does not derive Default here -#[allow(clippy::derivable_impls)] -impl Default for crate::bindings::VMStateFlags { - fn default() -> Self { - Self(0) - } -} - -unsafe impl Zeroable for crate::bindings::Property__bindgen_ty_1 {} -unsafe impl Zeroable for crate::bindings::Property {} -unsafe impl Zeroable for crate::bindings::VMStateFlags {} -unsafe impl Zeroable for crate::bindings::VMStateField {} -unsafe impl Zeroable for crate::bindings::VMStateDescription {} -unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_1 {} -unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_2 {} -unsafe impl Zeroable for crate::bindings::MemoryRegionOps {} -unsafe impl Zeroable for crate::bindings::MemTxAttrs {} -unsafe impl Zeroable for crate::bindings::CharBackend {} diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index a658a49fcf..2594e5465d 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -4,6 +4,7 @@ =20 use std::{ffi::CStr, ptr::addr_of}; =20 +use common::Zeroable; use qemu_api::{ bindings::{module_call_init, module_init_type, qdev_prop_bool}, cell::{self, BqlCell}, @@ -13,7 +14,6 @@ qom::{ObjectImpl, ParentField}, sysbus::SysBusDevice, vmstate::VMStateDescription, - zeroable::Zeroable, }; =20 mod vmstate_tests; diff --git a/rust/qemu-api/tests/vmstate_tests.rs b/rust/qemu-api/tests/vms= tate_tests.rs index bded836eb6..1ec80c483e 100644 --- a/rust/qemu-api/tests/vmstate_tests.rs +++ b/rust/qemu-api/tests/vmstate_tests.rs @@ -9,16 +9,16 @@ slice, }; =20 +use common::{Opaque, Zeroable}; use qemu_api::{ bindings::{ vmstate_info_bool, vmstate_info_int32, vmstate_info_int64, vmstate= _info_int8, vmstate_info_uint64, vmstate_info_uint8, vmstate_info_unused_buffe= r, VMStateFlags, }, - cell::{BqlCell, Opaque}, + cell::BqlCell, impl_vmstate_forward, vmstate::{VMStateDescription, VMStateField}, vmstate_fields, vmstate_of, vmstate_struct, vmstate_unused, vmstate_va= lidate, - zeroable::Zeroable, }; =20 const FOO_ARRAY_MAX: usize =3D 3; --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217219; cv=none; d=zohomail.com; s=zohoarc; b=XVqeaVMQXi2mcJJ4tci7v/snuHTdGRG0mhTWoytX719S8XagGJrb8N/F569/FHqOQ1zQv6xu3Ftq4vJoVGegaFk2DKqMT4dzxubVc8164p52V3Aa1LyYr61dalbxVX6EqgTHos5BzW4bT/Mx1n3oFyrkx7L6K1kw9LadKhn6EEE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217219; h=Content-Type: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=Bkt36Pr5/qRqxqma3g03PLfI44a//mDVlHn7f70r8wg=; b=gDwNUi+RUirzmitEt8U+nh+dOB8ipXKazCuFGgYzWxafXdFLy9LN01ayeaWQh+RNSDLGgR84UNxdKoTSH0SE3h0k7UMbi9wU0fNYyacjfYxn6wyY5O0hYjzIJNp/AHSF88/M/GZ9apDNBwNbUk/YIeBsnMz95QICJd8meu2fZk0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217219075352.3596584951298; Tue, 26 Aug 2025 07:06:59 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJA-00068n-62; Tue, 26 Aug 2025 10:05:56 -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 1uquIr-00060u-Fs for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:40 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquIe-00070U-5h for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:37 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-552--fHai1W7PdeatJX2kdZ6rQ-1; Tue, 26 Aug 2025 10:05:17 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 965DE18002C3; Tue, 26 Aug 2025 14:05:16 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D96341955F24; Tue, 26 Aug 2025 14:05:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217121; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Bkt36Pr5/qRqxqma3g03PLfI44a//mDVlHn7f70r8wg=; b=YziMPF9u8z50DFmmL6Zs2ZL0gRa/VFUlHiDq2qEfHYkduTtIIi3CMDXSGp7lYnN3g4azZ+ eVYCY2fSD5w0bO5qejRCvcIJpZzYL6RxH2fSk5lxRLd1kc85lmLB9LBa0i4rI6o8SH6drG gLizwuNo5GovP3FQlrNE9LIqElm3xTc= X-MC-Unique: -fHai1W7PdeatJX2kdZ6rQ-1 X-Mimecast-MFC-AGG-ID: -fHai1W7PdeatJX2kdZ6rQ_1756217116 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 04/18] rust: split "util" crate Date: Tue, 26 Aug 2025 18:04:32 +0400 Message-ID: <20250826140449.4190022-5-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1756217221765116600 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau --- MAINTAINERS | 1 + rust/qemu-api/wrapper.h | 6 --- rust/util/wrapper.h | 32 ++++++++++++++ rust/Cargo.lock | 14 ++++++ rust/Cargo.toml | 5 +-- rust/hw/char/pl011/Cargo.toml | 1 + rust/hw/char/pl011/meson.build | 1 + rust/hw/char/pl011/src/device.rs | 7 ++- rust/hw/timer/hpet/Cargo.toml | 1 + rust/hw/timer/hpet/meson.build | 1 + rust/hw/timer/hpet/src/device.rs | 6 +-- rust/meson.build | 1 + rust/qemu-api-macros/src/lib.rs | 2 +- rust/qemu-api-macros/src/tests.rs | 2 +- rust/qemu-api/Cargo.toml | 1 + rust/qemu-api/meson.build | 12 ++---- rust/qemu-api/src/bindings.rs | 1 + rust/qemu-api/src/chardev.rs | 10 ++--- rust/qemu-api/src/lib.rs | 7 --- rust/qemu-api/src/prelude.rs | 4 -- rust/qemu-api/src/qdev.rs | 4 +- rust/qemu-api/src/sysbus.rs | 2 +- rust/qemu-api/src/vmstate.rs | 2 +- rust/qemu-api/tests/tests.rs | 3 +- rust/util/Cargo.toml | 23 ++++++++++ rust/util/build.rs | 43 +++++++++++++++++++ rust/util/meson.build | 61 +++++++++++++++++++++++++++ rust/util/src/bindings.rs | 25 +++++++++++ rust/{qemu-api =3D> util}/src/errno.rs | 10 ++--- rust/{qemu-api =3D> util}/src/error.rs | 7 ++- rust/util/src/lib.rs | 10 +++++ rust/{qemu-api =3D> util}/src/log.rs | 12 +++--- rust/{qemu-api =3D> util}/src/module.rs | 2 +- rust/{qemu-api =3D> util}/src/timer.rs | 0 34 files changed, 255 insertions(+), 64 deletions(-) create mode 100644 rust/util/wrapper.h create mode 100644 rust/util/Cargo.toml create mode 100644 rust/util/build.rs create mode 100644 rust/util/meson.build create mode 100644 rust/util/src/bindings.rs rename rust/{qemu-api =3D> util}/src/errno.rs (98%) rename rust/{qemu-api =3D> util}/src/error.rs (98%) create mode 100644 rust/util/src/lib.rs rename rust/{qemu-api =3D> util}/src/log.rs (93%) rename rust/{qemu-api =3D> util}/src/module.rs (97%) rename rust/{qemu-api =3D> util}/src/timer.rs (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 80c0f80657..22d7847804 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3514,6 +3514,7 @@ F: rust/common/ F: rust/qemu-api F: rust/qemu-api-macros F: rust/rustfmt.toml +F: rust/util/ F: scripts/get-wraps-from-cargo-registry.py =20 Rust-related patches CC here diff --git a/rust/qemu-api/wrapper.h b/rust/qemu-api/wrapper.h index 15a1b19847..cc7112406b 100644 --- a/rust/qemu-api/wrapper.h +++ b/rust/qemu-api/wrapper.h @@ -48,9 +48,6 @@ typedef enum memory_order { #endif /* __CLANG_STDATOMIC_H */ =20 #include "qemu/osdep.h" -#include "qemu/log.h" -#include "qemu/log-for-trace.h" -#include "qemu/module.h" #include "qemu-io.h" #include "system/system.h" #include "hw/sysbus.h" @@ -61,11 +58,8 @@ typedef enum memory_order { #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" #include "hw/irq.h" -#include "qapi/error.h" -#include "qapi/error-internal.h" #include "migration/vmstate.h" #include "chardev/char-serial.h" #include "exec/memattrs.h" -#include "qemu/timer.h" #include "system/address-spaces.h" #include "hw/char/pl011.h" diff --git a/rust/util/wrapper.h b/rust/util/wrapper.h new file mode 100644 index 0000000000..b9ed68a01d --- /dev/null +++ b/rust/util/wrapper.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * This header file is meant to be used as input to the `bindgen` applicat= ion + * 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 sym= bols + * 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 "qapi/error.h" +#include "qapi/error-internal.h" +#include "qemu/log-for-trace.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "qemu/timer.h" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index ac105bd499..5cc3306b21 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -70,6 +70,7 @@ dependencies =3D [ "common", "qemu_api", "qemu_api_macros", + "util", ] =20 [[package]] @@ -97,6 +98,7 @@ dependencies =3D [ "common", "qemu_api", "qemu_api_macros", + "util", ] =20 [[package]] @@ -140,6 +142,7 @@ dependencies =3D [ "foreign", "libc", "qemu_api_macros", + "util", ] =20 [[package]] @@ -177,6 +180,17 @@ version =3D "1.0.12" source =3D "registry+https://github.com/rust-lang/crates.io-index" checksum =3D "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0f= ee4b" =20 +[[package]] +name =3D "util" +version =3D "0.1.0" +dependencies =3D [ + "anyhow", + "common", + "foreign", + "libc", + "qemu_api_macros", +] + [[package]] name =3D "version_check" version =3D "0.9.4" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index bb27db7931..04dac19c32 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -7,6 +7,7 @@ members =3D [ "qemu-api", "hw/char/pl011", "hw/timer/hpet", + "util", ] =20 [workspace.package] @@ -18,9 +19,7 @@ rust-version =3D "1.77.0" authors =3D ["The QEMU Project Developers "] =20 [workspace.lints.rust] -unexpected_cfgs =3D { level =3D "deny", check-cfg =3D [ - 'cfg(MESON)', -] } +unexpected_cfgs =3D { level =3D "deny", check-cfg =3D ['cfg(MESON)'] } =20 # Occasionally, we may need to silence warnings and clippy lints that # were only introduced in newer Rust compiler versions. Do not croak diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml index 6d15f107df..0cf9943fe8 100644 --- a/rust/hw/char/pl011/Cargo.toml +++ b/rust/hw/char/pl011/Cargo.toml @@ -17,6 +17,7 @@ bilge =3D { version =3D "0.2.0" } bilge-impl =3D { version =3D "0.2.0" } bits =3D { path =3D "../../../bits" } common =3D { path =3D "../../../common" } +util =3D { path =3D "../../../util" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build index 67bd295c3d..41cf46ead1 100644 --- a/rust/hw/char/pl011/meson.build +++ b/rust/hw/char/pl011/meson.build @@ -8,6 +8,7 @@ _libpl011_rs =3D static_library( bilge_impl_rs, bits_rs, common_rs, + util_rs, qemu_api, qemu_api_macros, ], diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 0c27c42c31..eb94cf6ba7 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -14,8 +14,6 @@ chardev::{CharBackend, Chardev, Event}, impl_vmstate_forward, irq::{IRQState, InterruptSource}, - log::Log, - log_mask_ln, memory::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder= }, prelude::*, qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType= , ResettablePhasesImpl}, @@ -24,6 +22,7 @@ vmstate::VMStateDescription, vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct, vmstate_sub= sections, vmstate_unused, }; +use util::{log::Log, log_mask_ln}; =20 use crate::registers::{self, Interrupt, RegisterOffset}; =20 @@ -180,7 +179,7 @@ fn properties() -> &'static [Property] { fn vmsd() -> Option<&'static VMStateDescription> { Some(&VMSTATE_PL011) } - const REALIZE: Option qemu_api::Result<()>> =3D Some(Self= ::realize); + const REALIZE: Option util::Result<()>> =3D Some(Self::re= alize); } =20 impl ResettablePhasesImpl for PL011State { @@ -627,7 +626,7 @@ fn event(&self, event: Event) { } } =20 - fn realize(&self) -> qemu_api::Result<()> { + fn realize(&self) -> util::Result<()> { self.char_backend .enable_handlers(self, Self::can_receive, Self::receive, Self:= :event); Ok(()) diff --git a/rust/hw/timer/hpet/Cargo.toml b/rust/hw/timer/hpet/Cargo.toml index ba7354f07e..dd9a5ed3d4 100644 --- a/rust/hw/timer/hpet/Cargo.toml +++ b/rust/hw/timer/hpet/Cargo.toml @@ -12,6 +12,7 @@ rust-version.workspace =3D true =20 [dependencies] common =3D { path =3D "../../../common" } +util =3D { path =3D "../../../util" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/timer/hpet/meson.build b/rust/hw/timer/hpet/meson.build index 05f8bd240a..f413893aa5 100644 --- a/rust/hw/timer/hpet/meson.build +++ b/rust/hw/timer/hpet/meson.build @@ -5,6 +5,7 @@ _libhpet_rs =3D static_library( rust_abi: 'rust', dependencies: [ common_rs, + util_rs, qemu_api, qemu_api_macros, ], diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index f3c324f243..672c88c46c 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -26,10 +26,10 @@ qom::{ObjectImpl, ObjectType, ParentField, ParentInit}, qom_isa, sysbus::{SysBusDevice, SysBusDeviceImpl}, - timer::{Timer, CLOCK_VIRTUAL, NANOSECONDS_PER_SECOND}, vmstate::VMStateDescription, vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmsta= te_validate, }; +use util::timer::{Timer, CLOCK_VIRTUAL, NANOSECONDS_PER_SECOND}; =20 use crate::fw_cfg::HPETFwConfig; =20 @@ -723,7 +723,7 @@ fn post_init(&self) { } } =20 - fn realize(&self) -> qemu_api::Result<()> { + fn realize(&self) -> util::Result<()> { if self.num_timers < HPET_MIN_TIMERS || self.num_timers > HPET_MAX= _TIMERS { Err(format!( "hpet.num_timers must be between {HPET_MIN_TIMERS} and {HP= ET_MAX_TIMERS}" @@ -1039,7 +1039,7 @@ fn vmsd() -> Option<&'static VMStateDescription> { Some(&VMSTATE_HPET) } =20 - const REALIZE: Option qemu_api::Result<()>> =3D Some(Self= ::realize); + const REALIZE: Option util::Result<()>> =3D Some(Self::re= alize); } =20 impl ResettablePhasesImpl for HPETState { diff --git a/rust/meson.build b/rust/meson.build index 402f8d6600..a9d715e6e9 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -25,6 +25,7 @@ genrs =3D [] subdir('common') subdir('qemu-api-macros') subdir('bits') +subdir('util') subdir('qemu-api') =20 subdir('hw') diff --git a/rust/qemu-api-macros/src/lib.rs b/rust/qemu-api-macros/src/lib= .rs index 850e3b1596..b5f77f06f5 100644 --- a/rust/qemu-api-macros/src/lib.rs +++ b/rust/qemu-api-macros/src/lib.rs @@ -91,7 +91,7 @@ fn derive_object_or_error(input: DeriveInput) -> Result::ParentType>); =20 - ::qemu_api::module_init! { + ::util::module_init! { MODULE_INIT_QOM =3D> unsafe { ::qemu_api::bindings::type_register_static(&<#name as ::qe= mu_api::qom::ObjectImpl>::TYPE_INFO); } diff --git a/rust/qemu-api-macros/src/tests.rs b/rust/qemu-api-macros/src/t= ests.rs index 42d5fa50bd..52683e46d5 100644 --- a/rust/qemu-api-macros/src/tests.rs +++ b/rust/qemu-api-macros/src/tests.rs @@ -63,7 +63,7 @@ struct Foo { _unused, ::qemu_api::qom::ParentField<::ParentType> ); - ::qemu_api::module_init! { + ::util::module_init! { MODULE_INIT_QOM =3D> unsafe { ::qemu_api::bindings::type_register_static(&::TYPE_INFO); } diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index 12774c356a..28e5969e7a 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -15,6 +15,7 @@ rust-version.workspace =3D true =20 [dependencies] common =3D { path =3D "../common" } +util =3D { path =3D "../util" } qemu_api_macros =3D { path =3D "../qemu-api-macros" } anyhow =3D "~1.0" libc =3D "0.2.162" diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index 6177e26819..8a2950dfe4 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -14,10 +14,8 @@ c_enums =3D [ 'MigrationPolicy', 'MigrationPriority', 'QEMUChrEvent', - 'QEMUClockType', 'ResetType', 'device_endian', - 'module_init_type', ] _qemu_api_bindgen_args =3D [] foreach enum : c_enums @@ -31,6 +29,7 @@ foreach enum : c_bitfields _qemu_api_bindgen_args +=3D ['--bitfield-enum', enum] endforeach =20 +_qemu_api_bindgen_args +=3D ['--blocklist-type', 'Error'] # TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. # # Rust bindings generation with `bindgen` might fail in some cases where t= he @@ -55,17 +54,12 @@ _qemu_api_rs =3D static_library( 'src/bindings.rs', 'src/cell.rs', 'src/chardev.rs', - 'src/errno.rs', - 'src/error.rs', 'src/irq.rs', - 'src/log.rs', 'src/memory.rs', - 'src/module.rs', 'src/prelude.rs', 'src/qdev.rs', 'src/qom.rs', 'src/sysbus.rs', - 'src/timer.rs', 'src/vmstate.rs', ], {'.' : _qemu_api_bindings_inc_rs}, @@ -73,7 +67,7 @@ _qemu_api_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _qemu_api_cfg, - dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, qemu_api_macro= s, qemuutil_rs, + dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, qemu_api_macro= s, qemuutil_rs, util_rs, qom, hwcore, chardev, migration], ) =20 @@ -99,7 +93,7 @@ test('rust-qemu-api-integration', override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_args: ['--test'], install: false, - dependencies: [common_rs, qemu_api]), + dependencies: [common_rs, util_rs, qemu_api]), args: [ '--test', '--test-threads', '1', '--format', 'pretty', diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs index 3acdd903b5..aedf42b652 100644 --- a/rust/qemu-api/src/bindings.rs +++ b/rust/qemu-api/src/bindings.rs @@ -21,6 +21,7 @@ //! `bindgen`-generated declarations. =20 use common::Zeroable; +use util::bindings::Error; =20 #[cfg(MESON)] include!("bindings.inc.rs"); diff --git a/rust/qemu-api/src/chardev.rs b/rust/qemu-api/src/chardev.rs index e2cb5f4379..c2bea23e82 100644 --- a/rust/qemu-api/src/chardev.rs +++ b/rust/qemu-api/src/chardev.rs @@ -54,7 +54,7 @@ fn write(&mut self, buf: &[u8]) -> io::Result { =20 let len =3D buf.len().try_into().unwrap(); let r =3D unsafe { bindings::qemu_chr_fe_write(addr_of_mut!(*chr),= buf.as_ptr(), len) }; - errno::into_io_result(r).map(|cnt| cnt as usize) + ::util::errno::into_io_result(r).map(|cnt| cnt as usize) } =20 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { @@ -62,7 +62,7 @@ fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { =20 let len =3D buf.len().try_into().unwrap(); let r =3D unsafe { bindings::qemu_chr_fe_write_all(addr_of_mut!(*c= hr), buf.as_ptr(), len) }; - errno::into_io_result(r).and_then(|cnt| { + ::util::errno::into_io_result(r).and_then(|cnt| { if cnt as usize =3D=3D buf.len() { Ok(()) } else { @@ -215,7 +215,7 @@ pub fn send_break(&self, long: bool) -> io::Result<()> { ) }; =20 - errno::into_io_result(r).map(|_| ()) + ::util::errno::into_io_result(r).map(|_| ()) } =20 /// Write data to a character backend from the front end. This functi= on @@ -229,7 +229,7 @@ pub fn write(&self, buf: &[u8]) -> io::Result { let len =3D buf.len().try_into().unwrap(); // SAFETY: qemu_chr_fe_write is thread-safe let r =3D unsafe { bindings::qemu_chr_fe_write(self.inner.as_ptr()= , buf.as_ptr(), len) }; - errno::into_io_result(r).map(|cnt| cnt as usize) + ::util::errno::into_io_result(r).map(|cnt| cnt as usize) } =20 /// Write data to a character backend from the front end. This functi= on @@ -243,7 +243,7 @@ pub fn write_all(&self, buf: &[u8]) -> io::Result<()> { let len =3D buf.len().try_into().unwrap(); // SAFETY: qemu_chr_fe_write_all is thread-safe let r =3D unsafe { bindings::qemu_chr_fe_write_all(self.inner.as_p= tr(), buf.as_ptr(), len) }; - errno::into_io_result(r).and_then(|cnt| { + ::util::errno::into_io_result(r).and_then(|cnt| { if cnt as usize =3D=3D buf.len() { Ok(()) } else { diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 7a2b29f28f..db81841a8f 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -15,16 +15,9 @@ =20 pub mod cell; pub mod chardev; -pub mod errno; -pub mod error; pub mod irq; -pub mod log; pub mod memory; -pub mod module; pub mod qdev; pub mod qom; pub mod sysbus; -pub mod timer; pub mod vmstate; - -pub use error::{Error, Result}; diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs index ad157f9655..3d771481e4 100644 --- a/rust/qemu-api/src/prelude.rs +++ b/rust/qemu-api/src/prelude.rs @@ -7,10 +7,6 @@ pub use crate::cell::BqlCell; pub use crate::cell::BqlRefCell; =20 -pub use crate::errno; - -pub use crate::log_mask_ln; - pub use crate::qdev::DeviceMethods; =20 pub use crate::qom::InterfaceType; diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs index bf17558cdb..02e9d55e6a 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/qemu-api/src/qdev.rs @@ -11,12 +11,12 @@ =20 pub use bindings::{ClockEvent, DeviceClass, Property, ResetType}; use common::{callbacks::FnCall, Opaque}; +pub use util::{Error, Result}; =20 use crate::{ bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, ResettableClas= s}, cell::bql_locked, chardev::Chardev, - error::{Error, Result}, irq::InterruptSource, prelude::*, qom::{ObjectClass, ObjectImpl, Owned, ParentInit}, @@ -135,7 +135,7 @@ fn vmsd() -> Option<&'static VMStateDescription> { /// readable/writeable from one thread at any time. unsafe extern "C" fn rust_realize_fn( dev: *mut bindings::DeviceState, - errp: *mut *mut bindings::Error, + errp: *mut *mut util::bindings::Error, ) { let state =3D NonNull::new(dev).unwrap().cast::(); let result =3D T::REALIZE.unwrap()(unsafe { state.as_ref() }); diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs index 4a5b4cbbf6..2dbfc31dbd 100644 --- a/rust/qemu-api/src/sysbus.rs +++ b/rust/qemu-api/src/sysbus.rs @@ -114,7 +114,7 @@ fn sysbus_realize(&self) { unsafe { bindings::sysbus_realize( self.upcast().as_mut_ptr(), - addr_of_mut!(bindings::error_fatal), + addr_of_mut!(util::bindings::error_fatal), ); } } diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs index 6a9cc0b975..4e2b7e2db0 100644 --- a/rust/qemu-api/src/vmstate.rs +++ b/rust/qemu-api/src/vmstate.rs @@ -390,7 +390,7 @@ unsafe impl VMState for $type { impl_vmstate_scalar!(vmstate_info_uint16, u16, VMS_VARRAY_UINT16); impl_vmstate_scalar!(vmstate_info_uint32, u32, VMS_VARRAY_UINT32); impl_vmstate_scalar!(vmstate_info_uint64, u64); -impl_vmstate_scalar!(vmstate_info_timer, crate::timer::Timer); +impl_vmstate_scalar!(vmstate_info_timer, util::timer::Timer); =20 // Pointer types using the underlying type's VMState plus VMS_POINTER // Note that references are not supported, though references to cells diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 2594e5465d..1dd4e29754 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -6,7 +6,7 @@ =20 use common::Zeroable; use qemu_api::{ - bindings::{module_call_init, module_init_type, qdev_prop_bool}, + bindings::qdev_prop_bool, cell::{self, BqlCell}, declare_properties, define_property, prelude::*, @@ -15,6 +15,7 @@ sysbus::SysBusDevice, vmstate::VMStateDescription, }; +use util::bindings::{module_call_init, module_init_type}; =20 mod vmstate_tests; =20 diff --git a/rust/util/Cargo.toml b/rust/util/Cargo.toml new file mode 100644 index 0000000000..aa10f03384 --- /dev/null +++ b/rust/util/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name =3D "util" +version =3D "0.1.0" +description =3D "Rust bindings for QEMU/util" +resolver =3D "2" +publish =3D false + +authors.workspace =3D true +edition.workspace =3D true +homepage.workspace =3D true +license.workspace =3D true +repository.workspace =3D true +rust-version.workspace =3D true + +[dependencies] +anyhow =3D "~1.0" +libc =3D "0.2.162" +foreign =3D "~0.3.1" +common =3D { path =3D "../common" } +qemu_api_macros =3D { path =3D "../qemu-api-macros" } + +[lints] +workspace =3D true diff --git a/rust/util/build.rs b/rust/util/build.rs new file mode 100644 index 0000000000..cac57cc5b9 --- /dev/null +++ b/rust/util/build.rs @@ -0,0 +1,43 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis +// SPDX-License-Identifier: GPL-2.0-or-later + +#[cfg(unix)] +use std::os::unix::fs::symlink as symlink_file; +#[cfg(windows)] +use std::os::windows::fs::symlink_file; +use std::{env, fs::remove_file, io::Result, path::Path}; + +fn main() -> Result<()> { + let file =3D if let Ok(root) =3D env::var("MESON_BUILD_ROOT") { + format!("{root}/rust/util/bindings.inc.rs") + } else { + // Placing bindings.inc.rs in the source directory is supported + // but not documented or encouraged. + format!("{}/src/bindings.inc.rs", env!("CARGO_MANIFEST_DIR")) + }; + + let file =3D Path::new(&file); + if !Path::new(&file).exists() { + panic!(concat!( + "\n", + " No generated C bindings found! Maybe you wanted one of\n", + " `make clippy`, `make rustfmt`, `make rustdoc`?\n", + "\n", + " For other uses of `cargo`, start a subshell with\n", + " `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n= ", + " the top of the build tree." + )); + } + + let out_dir =3D env::var("OUT_DIR").unwrap(); + let dest_path =3D format!("{out_dir}/bindings.inc.rs"); + let dest_path =3D Path::new(&dest_path); + if dest_path.symlink_metadata().is_ok() { + remove_file(dest_path)?; + } + symlink_file(file, dest_path)?; + + println!("cargo:rerun-if-changed=3Dbuild.rs"); + Ok(()) +} diff --git a/rust/util/meson.build b/rust/util/meson.build new file mode 100644 index 0000000000..3fe8e3975f --- /dev/null +++ b/rust/util/meson.build @@ -0,0 +1,61 @@ +_util_cfg =3D run_command(rustc_args, + '--config-headers', config_host_h, '--features', files('Cargo.toml'), + capture: true, check: true).stdout().strip().splitlines() + +_util_bindgen_args =3D [] +c_enums =3D [ + 'module_init_type', + 'QEMUClockType', +] +foreach enum : c_enums + _util_bindgen_args +=3D ['--rustified-enum', enum] +endforeach + +# +# TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. +# +# Rust bindings generation with `bindgen` might fail in some cases where t= he +# 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 +_util_bindings_inc_rs =3D rust.bindgen( + input: 'wrapper.h', + dependencies: common_ss.all_dependencies(), + output: 'bindings.inc.rs', + include_directories: bindings_incdir, + bindgen_version: ['>=3D0.60.0'], + args: bindgen_args_common + _util_bindgen_args, +) + +_util_rs =3D static_library( + 'util', + structured_sources( + [ + 'src/lib.rs', + 'src/bindings.rs', + 'src/errno.rs', + 'src/error.rs', + 'src/log.rs', + 'src/module.rs', + 'src/timer.rs', + ], + {'.': _util_bindings_inc_rs} + ), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_abi: 'rust', + rust_args: _util_cfg, + dependencies: [anyhow_rs, libc_rs, foreign_rs, qemuutil_rs, common_rs, q= emu_api_macros], +) + +util_rs =3D declare_dependency(link_with: [_util_rs], dependencies: [qemuu= til_rs, qom]) + +# Doctests are essentially integration tests, so they need the same depend= encies. +# Note that running them requires the object files for C code, so place th= em +# in a separate suite that is run by the "build" CI jobs rather than "chec= k". +rust.doctest('rust-util-rs-doctests', + _util_rs, + protocol: 'rust', + dependencies: util_rs, + suite: ['doc', 'rust'] +) diff --git a/rust/util/src/bindings.rs b/rust/util/src/bindings.rs new file mode 100644 index 0000000000..9ffff12cde --- /dev/null +++ b/rust/util/src/bindings.rs @@ -0,0 +1,25 @@ +// 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 +)] + +#[cfg(MESON)] +include!("bindings.inc.rs"); + +#[cfg(not(MESON))] +include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); diff --git a/rust/qemu-api/src/errno.rs b/rust/util/src/errno.rs similarity index 98% rename from rust/qemu-api/src/errno.rs rename to rust/util/src/errno.rs index e9478c4eb4..f3d27ccf65 100644 --- a/rust/qemu-api/src/errno.rs +++ b/rust/util/src/errno.rs @@ -176,7 +176,7 @@ fn map_ok(self) -> i32 { /// are interpreted as negated `errno` and turned into an `Err`. /// /// ``` -/// # use qemu_api::errno::into_io_result; +/// # use util::errno::into_io_result; /// # use std::io::ErrorKind; /// let ok =3D into_io_result(1i32).unwrap(); /// assert_eq!(ok, 1u32); @@ -192,7 +192,7 @@ fn map_ok(self) -> i32 { /// likely overflows and will panic: /// /// ```should_panic -/// # use qemu_api::errno::into_io_result; +/// # use util::errno::into_io_result; /// # #[allow(dead_code)] /// let err =3D into_io_result(-0x1234_5678i32); // panic /// ``` @@ -204,7 +204,7 @@ pub fn into_io_result(value: T) -> io::Res= ult { /// values to report errors. /// /// ``` -/// # use qemu_api::errno::into_neg_errno; +/// # use util::errno::into_neg_errno; /// # use std::io::{self, ErrorKind}; /// let ok: io::Result<()> =3D Ok(()); /// assert_eq!(into_neg_errno(ok), 0); @@ -223,7 +223,7 @@ pub fn into_io_result(value: T) -> io::Res= ult { /// positive: /// /// ```should_panic -/// # use qemu_api::errno::into_neg_errno; +/// # use util::errno::into_neg_errno; /// # use std::io; /// let err: io::Result =3D Ok(0x8899_AABB); /// into_neg_errno(err) // panic @@ -240,7 +240,7 @@ pub fn into_neg_errno>(va= lue: Result) -> T:: mod tests { use std::io::ErrorKind; =20 - use common::assert_match; + use bindings::assert_match; =20 use super::*; =20 diff --git a/rust/qemu-api/src/error.rs b/rust/util/src/error.rs similarity index 98% rename from rust/qemu-api/src/error.rs rename to rust/util/src/error.rs index 8bac3cbec8..a1b11a97ca 100644 --- a/rust/qemu-api/src/error.rs +++ b/rust/util/src/error.rs @@ -19,7 +19,7 @@ //! //! This module is most commonly used at the boundary between C and Rust c= ode; //! other code will usually access it through the -//! [`qemu_api::Result`](crate::Result) type alias, and will use the +//! [`utils::Result`](crate::Result) type alias, and will use the //! [`std::error::Error`] interface to let C errors participate in Rust's = error //! handling functionality. //! @@ -30,7 +30,7 @@ //! type up to C code, or from a combination of the two. //! //! The third case, corresponding to [`Error::with_error`], is the only on= e that -//! requires mentioning [`qemu_api::Error`](crate::Error) explicitly. Sim= ilar +//! requires mentioning [`utils::Error`](crate::Error) explicitly. Similar //! to how QEMU's C code handles errno values, the string and the //! `anyhow::Error` object will be concatenated with `:` as the separator. =20 @@ -316,11 +316,10 @@ mod tests { use std::ffi::CStr; =20 use anyhow::anyhow; - use common::assert_match; + use bindings::assert_match; use foreign::OwnedPointer; =20 use super::*; - use crate::bindings; =20 #[track_caller] fn error_for_test(msg: &CStr) -> OwnedPointer { diff --git a/rust/util/src/lib.rs b/rust/util/src/lib.rs new file mode 100644 index 0000000000..3463d937b4 --- /dev/null +++ b/rust/util/src/lib.rs @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pub mod bindings; +pub mod errno; +pub mod error; +pub mod log; +pub mod module; +pub mod timer; + +pub use error::{Error, Result}; diff --git a/rust/qemu-api/src/log.rs b/rust/util/src/log.rs similarity index 93% rename from rust/qemu-api/src/log.rs rename to rust/util/src/log.rs index a441b8c1f2..2e2c1cf3f8 100644 --- a/rust/qemu-api/src/log.rs +++ b/rust/util/src/log.rs @@ -47,7 +47,7 @@ impl LogGuard { /// # Examples /// /// ``` - /// # use qemu_api::log::LogGuard; + /// # use util::log::LogGuard; /// # use std::io::Write; /// if let Some(mut log) =3D LogGuard::new() { /// writeln!(log, "test"); @@ -114,7 +114,7 @@ fn drop(&mut self) { /// # Example /// /// ``` -/// use qemu_api::{log::Log, log_mask_ln}; +/// use util::{log::Log, log_mask_ln}; /// /// let error_address =3D 0xbad; /// log_mask_ln!(Log::GuestError, "Address 0x{error_address:x} out of rang= e"); @@ -124,7 +124,7 @@ fn drop(&mut self) { /// trailing `,`: /// /// ``` -/// use qemu_api::{log::Log, log_mask_ln}; +/// use util::{log::Log, log_mask_ln}; /// /// let error_address =3D 0xbad; /// log_mask_ln!( @@ -137,12 +137,12 @@ fn drop(&mut self) { macro_rules! log_mask_ln { ($mask:expr, $fmt:tt $($args:tt)*) =3D> {{ // Type assertion to enforce type `Log` for $mask - let _: Log =3D $mask; + let _: $crate::log::Log =3D $mask; =20 if unsafe { - (::qemu_api::bindings::qemu_loglevel & ($mask as std::os::raw:= :c_int)) !=3D 0 + ($crate::bindings::qemu_loglevel & ($mask as std::os::raw::c_i= nt)) !=3D 0 } { - _ =3D ::qemu_api::log::LogGuard::log_fmt( + _ =3D $crate::log::LogGuard::log_fmt( format_args!("{}\n", format_args!($fmt $($args)*))); } }}; diff --git a/rust/qemu-api/src/module.rs b/rust/util/src/module.rs similarity index 97% rename from rust/qemu-api/src/module.rs rename to rust/util/src/module.rs index fa5cea3598..06c45fc142 100644 --- a/rust/qemu-api/src/module.rs +++ b/rust/util/src/module.rs @@ -36,7 +36,7 @@ extern "C" fn ctor_fn() { =20 // shortcut because it's quite common that $body needs unsafe {} ($type:ident =3D> unsafe $body:block) =3D> { - $crate::module_init! { + ::util::module_init! { $type =3D> { unsafe { $body } } } }; diff --git a/rust/qemu-api/src/timer.rs b/rust/util/src/timer.rs similarity index 100% rename from rust/qemu-api/src/timer.rs rename to rust/util/src/timer.rs --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217485; cv=none; d=zohomail.com; s=zohoarc; b=T5hfudxzCLD6WSwPFqFgzwwULYj4+pH1mkZ5q8iK5UMikmYroHBTpEcYdxNqLVgoK3z5tLis677zv8EJtMI3PxZhiCAK7G6MoJ2MO4Y+15qOtJKqEg6VhxBJSVGNCsPdQgo9cJVjEcsKeRnRVMe2o2hG3g2FNzUS5UJ3tTnq75I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217485; h=Content-Type: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=CFTCJrN/ErsTKJeHGSYgSgdl79/H5tHqcfewRtfo3pU=; b=bK0wwb1itm30JGkqb0GOJyystgv6sXLpNsQbBZCQZf+6s8gZzyXl+H8fl7KlzMN+cdSi1A+lGduMxiQXd4Lw0i/4DJuiq8PxQlLibkTAXETnJ1r+ra+92+fjT4/dVx9ZOCiD27T79PpRCVX4dXXHRJkgeOA/He9DF5g81oiW108= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217485423279.91160539970406; Tue, 26 Aug 2025 07:11:25 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJC-0006AS-FO; Tue, 26 Aug 2025 10:05:58 -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 1uquIy-00062T-Lq for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:45 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquIm-00071I-1H for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:41 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-389-9ss3N93bOLOtMTDz7dGBpA-1; Tue, 26 Aug 2025 10:05:23 -0400 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6E22A19560A1; Tue, 26 Aug 2025 14:05:22 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 30DCA30001A2; Tue, 26 Aug 2025 14:05:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217127; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CFTCJrN/ErsTKJeHGSYgSgdl79/H5tHqcfewRtfo3pU=; b=aOoUBkvBMvByC5J0JbJWRbthnNqxFpwdpmclb+li0GvQq53n7K8YjNDjWTAR1Y1j9kUxPj 7HbhlNCKPA4l0ndR6r3imF+iRnOv6b0ohGVNjwE6QC47HExQlfz+slT784kbBuPDelaNkn SQla8ur9rqp9/QZXB8Y5rc8+acr/2eA= X-MC-Unique: 9ss3N93bOLOtMTDz7dGBpA-1 X-Mimecast-MFC-AGG-ID: 9ss3N93bOLOtMTDz7dGBpA_1756217122 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 05/18] rust: move vmstate_clock!() to qdev module Date: Tue, 26 Aug 2025 18:04:33 +0400 Message-ID: <20250826140449.4190022-6-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 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=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1756217486164116600 From: Marc-Andr=C3=A9 Lureau This will allow to split vmstate to a standalone crate next. Signed-off-by: Marc-Andr=C3=A9 Lureau --- rust/qemu-api/src/qdev.rs | 34 ++++++++++++++++++++++++++++++++++ rust/qemu-api/src/vmstate.rs | 34 ---------------------------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs index 02e9d55e6a..5469eef22a 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/qemu-api/src/qdev.rs @@ -408,3 +408,37 @@ unsafe impl ObjectType for Clock { unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_CLOCK)= }; } qom_isa!(Clock: Object); + +#[doc(alias =3D "VMSTATE_CLOCK")] +#[macro_export] +macro_rules! vmstate_clock { + ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:exp= r)?])?) =3D> {{ + $crate::bindings::VMStateField { + name: ::core::concat!(::core::stringify!($field_name), "\0") + .as_bytes() + .as_ptr() as *const ::std::os::raw::c_char, + offset: { + ::common::assert_field_type!( + $struct_name, + $field_name, + $crate::qom::Owned<$crate::qdev::Clock> $(, num =3D $n= um)? + ); + ::std::mem::offset_of!($struct_name, $field_name) + }, + size: ::core::mem::size_of::<*const $crate::qdev::Clock>(), + flags: $crate::bindings::VMStateFlags( + $crate::bindings::VMStateFlags::VMS_STRUCT.0 + | $crate::bindings::VMStateFlags::VMS_POINTER.0, + ), + vmsd: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate= _clock) }, + ..::common::zeroable::Zeroable::ZERO + } $(.with_varray_flag_unchecked( + $crate::call_func_with_field!( + $crate::vmstate::vmstate_varray_flag, + $struct_name, + $num + ) + ) + $(.with_varray_multiply($factor))?)? + }}; +} diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs index 4e2b7e2db0..ff64d2c6a2 100644 --- a/rust/qemu-api/src/vmstate.rs +++ b/rust/qemu-api/src/vmstate.rs @@ -504,40 +504,6 @@ macro_rules! vmstate_struct { }; } =20 -#[doc(alias =3D "VMSTATE_CLOCK")] -#[macro_export] -macro_rules! vmstate_clock { - ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:exp= r)?])?) =3D> {{ - $crate::bindings::VMStateField { - name: ::core::concat!(::core::stringify!($field_name), "\0") - .as_bytes() - .as_ptr() as *const ::std::os::raw::c_char, - offset: { - ::common::assert_field_type!( - $struct_name, - $field_name, - $crate::qom::Owned<$crate::qdev::Clock> $(, num =3D $n= um)? - ); - ::std::mem::offset_of!($struct_name, $field_name) - }, - size: ::core::mem::size_of::<*const $crate::qdev::Clock>(), - flags: $crate::bindings::VMStateFlags( - $crate::bindings::VMStateFlags::VMS_STRUCT.0 - | $crate::bindings::VMStateFlags::VMS_POINTER.0, - ), - vmsd: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate= _clock) }, - ..::common::zeroable::Zeroable::ZERO - } $(.with_varray_flag_unchecked( - $crate::call_func_with_field!( - $crate::vmstate::vmstate_varray_flag, - $struct_name, - $num - ) - ) - $(.with_varray_multiply($factor))?)? - }}; -} - /// Helper macro to declare a list of /// ([`VMStateField`](`crate::bindings::VMStateField`)) into a static and = return /// a pointer to the array of values it created. --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217575; cv=none; d=zohomail.com; s=zohoarc; b=JHBGC04PAfffM6MuFLrQH9afm+W3rC6Dd0qaTkja7Wr0LhjbnEFHzx4C3MjCByeHm44HHeoC9HPpksknCMhx3oEzuk+p0HeRExW/ERHmnYR0cS1IOLllcpTzlaH0nhC/VavuVeyxpTk1bK0n2Xu6Qgol9Mv2DR92i8D2lO0LbWw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217575; h=Content-Type: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=o2GQ5VjLakir0/k6HgSkaXNO8ljFlfMT2OkBfKsfPEU=; b=eaQ97pMww1EcG+5UTlG8mr5RH5D8ubD2ssApur2QuaP/1dqoI9aQu9VyXeuVDVaQT3BinGmEeAav7Jmn02iV9YJMnN24wggGnX4lQXSSohHNkF2WG93ypH8o6g9eMmltAS5KpvGs6MIdoCk2RK6TUexBhGyerl05V+tHTVjG0UM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217575913427.8904916244006; Tue, 26 Aug 2025 07:12:55 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJ7-000670-EC; Tue, 26 Aug 2025 10:05:53 -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 1uquJ2-00063w-BF for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:49 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquIr-000728-V7 for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:48 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-25-lPBflaZQPK26Uhz6Di2OVA-1; Tue, 26 Aug 2025 10:05:29 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 1B1A518002A4; Tue, 26 Aug 2025 14:05:28 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7FD401800447; Tue, 26 Aug 2025 14:05:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217133; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=o2GQ5VjLakir0/k6HgSkaXNO8ljFlfMT2OkBfKsfPEU=; b=BVdr9D1a0JXpPhnKHjram9MgyHGagwjpY5MLQrHIVginHq8r7JetH3XTmRlSizB9DudaSj pcJzBr4T8xpMshvhSqeEW6hzV12etdct3zrCwTfL3cqFXjosTszIuhljiK/ymUwmyL9wYu +9XhQ7CbupH7ZTuLh11eo4DOIMxBA8Y= X-MC-Unique: lPBflaZQPK26Uhz6Di2OVA-1 X-Mimecast-MFC-AGG-ID: lPBflaZQPK26Uhz6Di2OVA_1756217128 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 06/18] rust: move VMState handling to QOM module Date: Tue, 26 Aug 2025 18:04:34 +0400 Message-ID: <20250826140449.4190022-7-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_PASS=-0.001, T_SPF_HELO_TEMPERROR=0.01 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 @redhat.com) X-ZM-MESSAGEID: 1756217578789124100 From: Marc-Andr=C3=A9 Lureau This will allow to split vmstate to a standalone crate next. Signed-off-by: Marc-Andr=C3=A9 Lureau --- rust/qemu-api/src/qom.rs | 3 +++ rust/qemu-api/src/vmstate.rs | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/rust/qemu-api/src/qom.rs b/rust/qemu-api/src/qom.rs index c2f9a682bb..56feff3e17 100644 --- a/rust/qemu-api/src/qom.rs +++ b/rust/qemu-api/src/qom.rs @@ -110,6 +110,7 @@ object_get_typename, object_new, object_ref, object_unref, TypeInf= o, }, cell::bql_locked, + impl_vmstate_pointer, }; =20 /// A safe wrapper around [`bindings::Object`]. @@ -949,3 +950,5 @@ fn debug_fmt(&self, f: &mut fmt::Formatter) -> fmt::Res= ult { =20 impl ObjectClassMethods for T where T: IsA {} impl ObjectMethods for R where R::Target: IsA {} + +impl_vmstate_pointer!(Owned where T: VMState + ObjectType); diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs index ff64d2c6a2..c1e2b06390 100644 --- a/rust/qemu-api/src/vmstate.rs +++ b/rust/qemu-api/src/vmstate.rs @@ -29,8 +29,8 @@ =20 use common::{callbacks::FnCall, Zeroable}; =20 +use crate::bindings::VMStateFlags; pub use crate::bindings::{VMStateDescription, VMStateField}; -use crate::{bindings::VMStateFlags, prelude::*, qom::Owned}; =20 /// This macro is used to call a function with a generic argument bound /// to the type of a field. The function must take a @@ -396,11 +396,12 @@ unsafe impl VMState for $type { // Note that references are not supported, though references to cells // could be allowed. =20 +#[macro_export] macro_rules! impl_vmstate_pointer { ($type:ty where $base:tt: VMState $($where:tt)*) =3D> { - unsafe impl<$base> VMState for $type where $base: VMState $($where= )* { - const SCALAR_TYPE: VMStateFieldType =3D ::SCALAR= _TYPE; - const BASE: VMStateField =3D <$base as VMState>::BASE.with_poi= nter_flag(); + unsafe impl<$base> $crate::vmstate::VMState for $type where $base:= $crate::vmstate::VMState $($where)* { + const SCALAR_TYPE: $crate::vmstate::VMStateFieldType =3D ::SCALAR_TYPE; + const BASE: $crate::vmstate::VMStateField =3D <$base as $crate= ::vmstate::VMState>::BASE.with_pointer_flag(); } }; } @@ -412,7 +413,6 @@ unsafe impl<$base> VMState for $type where $base: VMSta= te $($where)* { // Unlike C pointers, Box is always non-null therefore there is no need // to specify VMS_ALLOC. impl_vmstate_pointer!(Box where T: VMState); -impl_vmstate_pointer!(Owned where T: VMState + ObjectType); =20 // Arrays using the underlying type's VMState plus // VMS_ARRAY/VMS_ARRAY_OF_POINTER --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217440; cv=none; d=zohomail.com; s=zohoarc; b=PCDyr0Xy+pZWuGRM7O8pZM30fSuDvu22GYfs8kyqqKlkxFcvI5POEji/1/VLMcdGRoXUwKZpA1o2PKfZkgIJ6q08mEb2wkRz0Zo+qpWb9rHeUySoazSa4c9RMtzKUVADJ2uXwVpH8yMdUw9sUxtJizVRyDAqgP8cAyev8q94Av8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217440; h=Content-Type: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=cmT1dEKaRl4M6Vu85AUODd3c7+AYcnMdCM+EQuaUcmg=; b=HiApASaTx6xStckZAauSaU+NJvNy2W+VVj5AFIzKrKRZYd1GbhqvCikirV4hPDLPEd9Amsj6MXPc7Ru4CCJRx2Xfph/dqlTGgCDaBSQ2szZJ87v3lahUMf1WRKbPyIRb7HBuYhjoViUybEfbU6qlyXAkl3T28kvHd25VS9llVK4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217440794104.8864247892352; Tue, 26 Aug 2025 07:10:40 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJ8-00068L-Cq; Tue, 26 Aug 2025 10:05:55 -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 1uquJ3-00064A-Ca for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:49 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquIt-00072S-H1 for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:49 -0400 Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-110-ovozX8_pNl29YiHehVD1vA-1; Tue, 26 Aug 2025 10:05:34 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 95F7B1956095; Tue, 26 Aug 2025 14:05:33 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 89F1818004A3; Tue, 26 Aug 2025 14:05:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217136; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cmT1dEKaRl4M6Vu85AUODd3c7+AYcnMdCM+EQuaUcmg=; b=KX5uiFNq74KGceMNHQD/8dtZ761Ptc/ugKZZiRyL4t8Qq566OIP151x3tvmoy2+uoetdSu SPcRYcZmqrNhjPvIkjs+ghFrV4xyUnDl21Opgo/f2t449pTqyXcw2BfzOEz5s7upcyzZx0 bIKelyGvD0+aigE/GOYozCIQPFu9YKs= X-MC-Unique: ovozX8_pNl29YiHehVD1vA-1 X-Mimecast-MFC-AGG-ID: ovozX8_pNl29YiHehVD1vA_1756217133 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 07/18] rust: move Cell vmstate impl Date: Tue, 26 Aug 2025 18:04:35 +0400 Message-ID: <20250826140449.4190022-8-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-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 @redhat.com) X-ZM-MESSAGEID: 1756217441517116600 From: Marc-Andr=C3=A9 Lureau This will allow to split vmstate to a standalone crate next. Signed-off-by: Marc-Andr=C3=A9 Lureau --- rust/qemu-api/src/cell.rs | 5 ++++- rust/qemu-api/src/vmstate.rs | 16 +++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/rust/qemu-api/src/cell.rs b/rust/qemu-api/src/cell.rs index 98d720caf9..4bce526e45 100644 --- a/rust/qemu-api/src/cell.rs +++ b/rust/qemu-api/src/cell.rs @@ -152,7 +152,7 @@ ptr::NonNull, }; =20 -use crate::bindings; +use crate::{bindings, impl_vmstate_transparent}; =20 /// An internal function that is used by doctests. pub fn bql_start_test() { @@ -866,3 +866,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Resul= t { (**self).fmt(f) } } + +impl_vmstate_transparent!(BqlCell where T: VMState); +impl_vmstate_transparent!(BqlRefCell where T: VMState); diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs index c1e2b06390..9d33997c57 100644 --- a/rust/qemu-api/src/vmstate.rs +++ b/rust/qemu-api/src/vmstate.rs @@ -29,8 +29,7 @@ =20 use common::{callbacks::FnCall, Zeroable}; =20 -use crate::bindings::VMStateFlags; -pub use crate::bindings::{VMStateDescription, VMStateField}; +pub use crate::bindings::{VMStateDescription, VMStateField, VMStateFlags}; =20 /// This macro is used to call a function with a generic argument bound /// to the type of a field. The function must take a @@ -325,15 +324,16 @@ unsafe impl $crate::vmstate::VMState for $tuple { =20 // Transparent wrappers: just use the internal type =20 +#[macro_export] macro_rules! impl_vmstate_transparent { ($type:ty where $base:tt: VMState $($where:tt)*) =3D> { - unsafe impl<$base> VMState for $type where $base: VMState $($where= )* { - const SCALAR_TYPE: VMStateFieldType =3D <$base as VMState>::SC= ALAR_TYPE; - const BASE: VMStateField =3D VMStateField { + unsafe impl<$base> $crate::vmstate::VMState for $type where $base:= $crate::vmstate::VMState $($where)* { + const SCALAR_TYPE: $crate::vmstate::VMStateFieldType =3D <$bas= e as $crate::vmstate::VMState>::SCALAR_TYPE; + const BASE: $crate::vmstate::VMStateField =3D $crate::vmstate:= :VMStateField { size: mem::size_of::<$type>(), - ..<$base as VMState>::BASE + ..<$base as $crate::vmstate::VMState>::BASE }; - const VARRAY_FLAG: VMStateFlags =3D <$base as VMState>::VARRAY= _FLAG; + const VARRAY_FLAG: $crate::vmstate::VMStateFlags =3D <$base as= $crate::vmstate::VMState>::VARRAY_FLAG; } }; } @@ -341,8 +341,6 @@ unsafe impl<$base> VMState for $type where $base: VMSta= te $($where)* { impl_vmstate_transparent!(std::cell::Cell where T: VMState); impl_vmstate_transparent!(std::cell::UnsafeCell where T: VMState); impl_vmstate_transparent!(std::pin::Pin where T: VMState); -impl_vmstate_transparent!(crate::cell::BqlCell where T: VMState); -impl_vmstate_transparent!(crate::cell::BqlRefCell where T: VMState); impl_vmstate_transparent!(::common::Opaque where T: VMState); =20 #[macro_export] --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217441; cv=none; d=zohomail.com; s=zohoarc; b=Sp+7KmzqPwg454hUqnpHFR0NSVNy5EHUu9u4YwQ2VAo6nYqJmO1HdhsUr2Kl6PKk3DirHVqdtBv/DZ9qJERHgciaDN8oH/qLVLPgyUnB5HaCgVOL8Ovt1fkc7cD1gqhIqxTiodDwt6UCxdZl/G7dpsjDHAjkZ0Kp0/OYMZ/3Qc4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217441; h=Content-Type: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=zdeMNCuUl3adRu4sZvTVCrBsS8WLaOcL3XKzJAkTot0=; b=N0MDyl9klxvclkNvmL6xZ85RIX0WzsHFvPR5M61u9BLjFOQ4tYjgUNyAnLHZU6C72tPhyX8e1Ex+wYNcDx01z/MxC7wqlmc0z9C86MnhMa81Anp4Rd++jZPJfdZal0XU7pQgqnBMLqXP8k4a7UAnX2fRzSPIZsCx0vmCR4r4Iy8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217441762523.6503687035165; Tue, 26 Aug 2025 07:10:41 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJD-0006B4-RX; Tue, 26 Aug 2025 10:05:59 -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 1uquJC-0006AT-Ja for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:58 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquJ5-00073n-Uw for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:05:58 -0400 Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-374-Aj6l097aPNef5uGwuUjE1g-1; Tue, 26 Aug 2025 10:05:41 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id ECAD919560B7; Tue, 26 Aug 2025 14:05:39 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 31FCF18004A3; Tue, 26 Aug 2025 14:05:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217145; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=zdeMNCuUl3adRu4sZvTVCrBsS8WLaOcL3XKzJAkTot0=; b=coIRJcofUEOlwTMHGsr8+Kt5k9wu34pFxYDUee2aYpG825RzHgT3rPp/eY5otbOYMqpizb La3A0+d/SV4J0hg6XmkFrQkk7LhutxJjQ/3xxvg+if6GmQGVUzmeMzJ+UjKdT8kVJetnBW 5X/afbw3sIk60Uaep+2DQ4NQNj3oyko= X-MC-Unique: Aj6l097aPNef5uGwuUjE1g-1 X-Mimecast-MFC-AGG-ID: Aj6l097aPNef5uGwuUjE1g_1756217140 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 08/18] rust: split "migration" crate Date: Tue, 26 Aug 2025 18:04:36 +0400 Message-ID: <20250826140449.4190022-9-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_FILL_THIS_FORM_SHORT=0.01 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1756217443929116601 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau --- MAINTAINERS | 1 + rust/migration/wrapper.h | 51 ++++++++++ rust/qemu-api/wrapper.h | 1 - rust/Cargo.lock | 12 +++ rust/Cargo.toml | 1 + rust/hw/char/pl011/Cargo.toml | 1 + rust/hw/char/pl011/meson.build | 1 + rust/hw/char/pl011/src/device.rs | 8 +- rust/hw/char/pl011/src/registers.rs | 2 +- rust/hw/timer/hpet/Cargo.toml | 1 + rust/hw/timer/hpet/meson.build | 1 + rust/hw/timer/hpet/src/device.rs | 8 +- rust/meson.build | 1 + rust/migration/Cargo.toml | 21 ++++ rust/migration/build.rs | 43 ++++++++ rust/migration/meson.build | 57 +++++++++++ rust/migration/src/bindings.rs | 48 +++++++++ rust/migration/src/lib.rs | 4 + rust/{qemu-api =3D> migration}/src/vmstate.rs | 104 +++++++++++--------- rust/qemu-api/Cargo.toml | 1 + rust/qemu-api/meson.build | 10 +- rust/qemu-api/src/bindings.rs | 21 +--- rust/qemu-api/src/cell.rs | 4 +- rust/qemu-api/src/lib.rs | 1 - rust/qemu-api/src/prelude.rs | 2 - rust/qemu-api/src/qdev.rs | 10 +- rust/qemu-api/src/qom.rs | 2 +- rust/qemu-api/tests/tests.rs | 2 +- rust/qemu-api/tests/vmstate_tests.rs | 16 +-- 29 files changed, 338 insertions(+), 97 deletions(-) create mode 100644 rust/migration/wrapper.h create mode 100644 rust/migration/Cargo.toml create mode 100644 rust/migration/build.rs create mode 100644 rust/migration/meson.build create mode 100644 rust/migration/src/bindings.rs create mode 100644 rust/migration/src/lib.rs rename rust/{qemu-api =3D> migration}/src/vmstate.rs (86%) diff --git a/MAINTAINERS b/MAINTAINERS index 22d7847804..bb4f5f011f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3511,6 +3511,7 @@ Rust M: Manos Pitsidianakis S: Maintained F: rust/common/ +F: rust/migration/ F: rust/qemu-api F: rust/qemu-api-macros F: rust/rustfmt.toml diff --git a/rust/migration/wrapper.h b/rust/migration/wrapper.h new file mode 100644 index 0000000000..daf316aed4 --- /dev/null +++ b/rust/migration/wrapper.h @@ -0,0 +1,51 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2024 Linaro Ltd. + * + * Authors: Manos Pitsidianakis + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * 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 OT= HER + * 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` applicat= ion + * 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 sym= bols + * 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 "migration/vmstate.h" diff --git a/rust/qemu-api/wrapper.h b/rust/qemu-api/wrapper.h index cc7112406b..b99df9f568 100644 --- a/rust/qemu-api/wrapper.h +++ b/rust/qemu-api/wrapper.h @@ -58,7 +58,6 @@ typedef enum memory_order { #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" #include "hw/irq.h" -#include "migration/vmstate.h" #include "chardev/char-serial.h" #include "exec/memattrs.h" #include "system/address-spaces.h" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 5cc3306b21..58bfbaf545 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -68,6 +68,7 @@ name =3D "hpet" version =3D "0.1.0" dependencies =3D [ "common", + "migration", "qemu_api", "qemu_api_macros", "util", @@ -88,6 +89,15 @@ version =3D "0.2.162" source =3D "registry+https://github.com/rust-lang/crates.io-index" checksum =3D "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef0150= 6398" =20 +[[package]] +name =3D "migration" +version =3D "0.1.0" +dependencies =3D [ + "common", + "qemu_api_macros", + "util", +] + [[package]] name =3D "pl011" version =3D "0.1.0" @@ -96,6 +106,7 @@ dependencies =3D [ "bilge-impl", "bits", "common", + "migration", "qemu_api", "qemu_api_macros", "util", @@ -141,6 +152,7 @@ dependencies =3D [ "common", "foreign", "libc", + "migration", "qemu_api_macros", "util", ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 04dac19c32..df6a385d64 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -3,6 +3,7 @@ resolver =3D "2" members =3D [ "bits", "common", + "migration", "qemu-api-macros", "qemu-api", "hw/char/pl011", diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml index 0cf9943fe8..7fd7531823 100644 --- a/rust/hw/char/pl011/Cargo.toml +++ b/rust/hw/char/pl011/Cargo.toml @@ -18,6 +18,7 @@ bilge-impl =3D { version =3D "0.2.0" } bits =3D { path =3D "../../../bits" } common =3D { path =3D "../../../common" } util =3D { path =3D "../../../util" } +migration =3D { path =3D "../../../migration" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build index 41cf46ead1..e3ddd17351 100644 --- a/rust/hw/char/pl011/meson.build +++ b/rust/hw/char/pl011/meson.build @@ -9,6 +9,7 @@ _libpl011_rs =3D static_library( bits_rs, common_rs, util_rs, + migration_rs, qemu_api, qemu_api_macros, ], diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index eb94cf6ba7..904faa80a9 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -9,18 +9,20 @@ }; =20 use common::{static_assert, uninit_field_mut, Zeroable}; +use migration::{ + impl_vmstate_forward, vmstate_fields, vmstate_of, vmstate_struct, vmst= ate_subsections, + vmstate_unused, VMStateDescription, +}; use qemu_api::{ bindings::{qdev_prop_bool, qdev_prop_chr}, chardev::{CharBackend, Chardev, Event}, - impl_vmstate_forward, irq::{IRQState, InterruptSource}, memory::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder= }, prelude::*, qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType= , ResettablePhasesImpl}, qom::{ObjectImpl, Owned, ParentField, ParentInit}, sysbus::{SysBusDevice, SysBusDeviceImpl}, - vmstate::VMStateDescription, - vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct, vmstate_sub= sections, vmstate_unused, + vmstate_clock, }; use util::{log::Log, log_mask_ln}; =20 diff --git a/rust/hw/char/pl011/src/registers.rs b/rust/hw/char/pl011/src/r= egisters.rs index 7ececd39f8..2bfbd81095 100644 --- a/rust/hw/char/pl011/src/registers.rs +++ b/rust/hw/char/pl011/src/registers.rs @@ -10,7 +10,7 @@ =20 use bilge::prelude::*; use bits::bits; -use qemu_api::{impl_vmstate_bitsized, impl_vmstate_forward}; +use migration::{impl_vmstate_bitsized, impl_vmstate_forward}; =20 /// Offset of each register from the base memory address of the device. #[doc(alias =3D "offset")] diff --git a/rust/hw/timer/hpet/Cargo.toml b/rust/hw/timer/hpet/Cargo.toml index dd9a5ed3d4..70acdf03d6 100644 --- a/rust/hw/timer/hpet/Cargo.toml +++ b/rust/hw/timer/hpet/Cargo.toml @@ -13,6 +13,7 @@ rust-version.workspace =3D true [dependencies] common =3D { path =3D "../../../common" } util =3D { path =3D "../../../util" } +migration =3D { path =3D "../../../migration" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/timer/hpet/meson.build b/rust/hw/timer/hpet/meson.build index f413893aa5..2c605dcf9d 100644 --- a/rust/hw/timer/hpet/meson.build +++ b/rust/hw/timer/hpet/meson.build @@ -6,6 +6,7 @@ _libhpet_rs =3D static_library( dependencies: [ common_rs, util_rs, + migration_rs, qemu_api, qemu_api_macros, ], diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index 672c88c46c..35b968cca7 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -11,6 +11,10 @@ }; =20 use common::{bitops::IntegerExt, uninit_field_mut, Zeroable}; +use migration::{ + vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmsta= te_validate, + VMStateDescription, VMStateFieldHelper, +}; use qemu_api::{ bindings::{ address_space_memory, address_space_stl_le, qdev_prop_bit, qdev_pr= op_bool, @@ -26,8 +30,6 @@ qom::{ObjectImpl, ObjectType, ParentField, ParentInit}, qom_isa, sysbus::{SysBusDevice, SysBusDeviceImpl}, - vmstate::VMStateDescription, - vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmsta= te_validate, }; use util::timer::{Timer, CLOCK_VIRTUAL, NANOSECONDS_PER_SECOND}; =20 @@ -1021,7 +1023,7 @@ impl ObjectImpl for HPETState { vmstate_of!(HPETState, counter), vmstate_of!(HPETState, num_timers_save), vmstate_validate!(HPETState, VALIDATE_TIMERS_NAME, HPETState::vali= date_num_timers), - vmstate_struct!(HPETState, timers[0 .. num_timers_save], &VMSTATE_= HPET_TIMER, BqlRefCell, HPETState::validate_num_timers).with_ver= sion_id(0), + VMStateFieldHelper(vmstate_struct!(HPETState, timers[0 .. num_time= rs_save], &VMSTATE_HPET_TIMER, BqlRefCell, HPETState::validate_n= um_timers)).with_version_id(0).0, }, subsections: vmstate_subsections! { VMSTATE_HPET_RTC_IRQ_LEVEL, diff --git a/rust/meson.build b/rust/meson.build index a9d715e6e9..826949b2e6 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -26,6 +26,7 @@ subdir('common') subdir('qemu-api-macros') subdir('bits') subdir('util') +subdir('migration') subdir('qemu-api') =20 subdir('hw') diff --git a/rust/migration/Cargo.toml b/rust/migration/Cargo.toml new file mode 100644 index 0000000000..98e6df2109 --- /dev/null +++ b/rust/migration/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name =3D "migration" +version =3D "0.1.0" +description =3D "Rust bindings for QEMU/migration" +resolver =3D "2" +publish =3D false + +authors.workspace =3D true +edition.workspace =3D true +homepage.workspace =3D true +license.workspace =3D true +repository.workspace =3D true +rust-version.workspace =3D true + +[dependencies] +common =3D { path =3D "../common" } +util =3D { path =3D "../util" } +qemu_api_macros =3D { path =3D "../qemu-api-macros" } + +[lints] +workspace =3D true diff --git a/rust/migration/build.rs b/rust/migration/build.rs new file mode 100644 index 0000000000..50be521b16 --- /dev/null +++ b/rust/migration/build.rs @@ -0,0 +1,43 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis +// SPDX-License-Identifier: GPL-2.0-or-later + +#[cfg(unix)] +use std::os::unix::fs::symlink as symlink_file; +#[cfg(windows)] +use std::os::windows::fs::symlink_file; +use std::{env, fs::remove_file, io::Result, path::Path}; + +fn main() -> Result<()> { + let file =3D if let Ok(root) =3D env::var("MESON_BUILD_ROOT") { + format!("{root}/rust/migration/bindings.inc.rs") + } else { + // Placing bindings.inc.rs in the source directory is supported + // but not documented or encouraged. + format!("{}/src/bindings.inc.rs", env!("CARGO_MANIFEST_DIR")) + }; + + let file =3D Path::new(&file); + if !Path::new(&file).exists() { + panic!(concat!( + "\n", + " No generated C bindings found! Maybe you wanted one of\n", + " `make clippy`, `make rustfmt`, `make rustdoc`?\n", + "\n", + " For other uses of `cargo`, start a subshell with\n", + " `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n= ", + " the top of the build tree." + )); + } + + let out_dir =3D env::var("OUT_DIR").unwrap(); + let dest_path =3D format!("{out_dir}/bindings.inc.rs"); + let dest_path =3D Path::new(&dest_path); + if dest_path.symlink_metadata().is_ok() { + remove_file(dest_path)?; + } + symlink_file(file, dest_path)?; + + println!("cargo:rerun-if-changed=3Dbuild.rs"); + Ok(()) +} diff --git a/rust/migration/meson.build b/rust/migration/meson.build new file mode 100644 index 0000000000..d6d6a7c98e --- /dev/null +++ b/rust/migration/meson.build @@ -0,0 +1,57 @@ +_migration_cfg =3D run_command(rustc_args, + '--config-headers', config_host_h, '--features', files('Cargo.toml'), + capture: true, check: true).stdout().strip().splitlines() + +_migration_bindgen_args =3D [] +c_bitfields =3D [ + 'MigrationPolicy', + 'MigrationPriority', + 'VMStateFlags', +] +foreach enum : c_bitfields + _migration_bindgen_args +=3D ['--bitfield-enum', enum] +endforeach +# +# TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. +# +# Rust bindings generation with `bindgen` might fail in some cases where t= he +# 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 +_migration_bindings_inc_rs =3D rust.bindgen( + input: 'wrapper.h', + dependencies: common_ss.all_dependencies(), + output: 'bindings.inc.rs', + include_directories: bindings_incdir, + bindgen_version: ['>=3D0.60.0'], + args: bindgen_args_common + _migration_bindgen_args, + ) + +_migration_rs =3D static_library( + 'migration', + structured_sources( + [ + 'src/lib.rs', + 'src/bindings.rs', + 'src/vmstate.rs', + ], + {'.' : _migration_bindings_inc_rs}, + ), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_abi: 'rust', + rust_args: _migration_cfg, + dependencies: [qemuutil_rs, common_rs, util_rs, migration], +) + +migration_rs =3D declare_dependency(link_with: [_migration_rs], + dependencies: [migration]) + +# Doctests are essentially integration tests, so they need the same depend= encies. +# Note that running them requires the object files for C code, so place th= em +# in a separate suite that is run by the "build" CI jobs rather than "chec= k". +rust.doctest('rust-migration-rs-doctests', + _migration_rs, + protocol: 'rust', + dependencies: migration_rs, + suite: ['doc', 'rust']) diff --git a/rust/migration/src/bindings.rs b/rust/migration/src/bindings.rs new file mode 100644 index 0000000000..8ce13a9000 --- /dev/null +++ b/rust/migration/src/bindings.rs @@ -0,0 +1,48 @@ +// 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 +)] + +use common::Zeroable; + +#[cfg(MESON)] +include!("bindings.inc.rs"); + +#[cfg(not(MESON))] +include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); + +unsafe impl Send for VMStateDescription {} +unsafe impl Sync for VMStateDescription {} + +unsafe impl Send for VMStateField {} +unsafe impl Sync for VMStateField {} + +unsafe impl Send for VMStateInfo {} +unsafe impl Sync for VMStateInfo {} + +// bindgen does not derive Default here +#[allow(clippy::derivable_impls)] +impl Default for VMStateFlags { + fn default() -> Self { + Self(0) + } +} + +unsafe impl Zeroable for VMStateFlags {} +unsafe impl Zeroable for VMStateField {} +unsafe impl Zeroable for VMStateDescription {} diff --git a/rust/migration/src/lib.rs b/rust/migration/src/lib.rs new file mode 100644 index 0000000000..f2a6bb9f27 --- /dev/null +++ b/rust/migration/src/lib.rs @@ -0,0 +1,4 @@ +pub mod bindings; + +pub mod vmstate; +pub use vmstate::*; diff --git a/rust/qemu-api/src/vmstate.rs b/rust/migration/src/vmstate.rs similarity index 86% rename from rust/qemu-api/src/vmstate.rs rename to rust/migration/src/vmstate.rs index 9d33997c57..4f95ab0d49 100644 --- a/rust/qemu-api/src/vmstate.rs +++ b/rust/migration/src/vmstate.rs @@ -27,7 +27,7 @@ use core::{marker::PhantomData, mem, ptr::NonNull}; use std::ffi::{c_int, c_void}; =20 -use common::{callbacks::FnCall, Zeroable}; +use common::callbacks::FnCall; =20 pub use crate::bindings::{VMStateDescription, VMStateField, VMStateFlags}; =20 @@ -39,7 +39,7 @@ /// # Examples /// /// ``` -/// # use qemu_api::call_func_with_field; +/// # use migration::call_func_with_field; /// # use core::marker::PhantomData; /// const fn size_of_field(_: PhantomData) -> usize { /// std::mem::size_of::() @@ -197,6 +197,10 @@ pub const fn vmstate_varray_flag(_: Phanto= mData) -> VMStateFlags /// for them. The macros /// [`impl_vmstate_bitsized!`](crate::impl_vmstate_bitsized) /// and [`impl_vmstate_forward!`](crate::impl_vmstate_forward) help with t= his. +/// +/// [`BqlCell`]: ../../qemu_api/cell/struct.BqlCell.html +/// [`BqlRefCell`]: ../../qemu_api/cell/struct.BqlRefCell.html +/// [`Owned`]: ../../qemu_api/qom/struct.Owned.html #[macro_export] macro_rules! vmstate_of { ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:exp= r)?])? $(, $test_fn:expr)? $(,)?) =3D> { @@ -214,20 +218,25 @@ macro_rules! vmstate_of { $struct_name, $field_name )), - ..$crate::call_func_with_field!( + ..$crate::vmstate::VMStateFieldHelper($crate::call_func_with_f= ield!( $crate::vmstate::vmstate_base, $struct_name, $field_name - )$(.with_varray_flag($crate::call_func_with_field!( + ))$(.with_varray_flag($crate::call_func_with_field!( $crate::vmstate::vmstate_varray_flag, $struct_name, $num)) $(.with_varray_multiply($factor))?)? + .0 } }; } =20 -impl VMStateFlags { +pub trait VMStateFlagsExt { + const VMS_VARRAY_FLAGS: VMStateFlags; +} + +impl VMStateFlagsExt for VMStateFlags { const VMS_VARRAY_FLAGS: VMStateFlags =3D VMStateFlags( VMStateFlags::VMS_VARRAY_INT32.0 | VMStateFlags::VMS_VARRAY_UINT8.0 @@ -236,62 +245,66 @@ impl VMStateFlags { ); } =20 +// using extension traits would be nicer, unfortunately it doesn't allow c= onst +// fn yet +pub struct VMStateFieldHelper(pub VMStateField); + // Add a couple builder-style methods to VMStateField, allowing // easy derivation of VMStateField constants from other types. -impl VMStateField { +impl VMStateFieldHelper { #[must_use] pub const fn with_version_id(mut self, version_id: i32) -> Self { assert!(version_id >=3D 0); - self.version_id =3D version_id; + self.0.version_id =3D version_id; self } =20 #[must_use] pub const fn with_array_flag(mut self, num: usize) -> Self { assert!(num <=3D 0x7FFF_FFFFusize); - assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) =3D=3D 0); - assert!((self.flags.0 & VMStateFlags::VMS_VARRAY_FLAGS.0) =3D=3D 0= ); - if (self.flags.0 & VMStateFlags::VMS_POINTER.0) !=3D 0 { - self.flags =3D VMStateFlags(self.flags.0 & !VMStateFlags::VMS_= POINTER.0); - self.flags =3D VMStateFlags(self.flags.0 | VMStateFlags::VMS_A= RRAY_OF_POINTER.0); + assert!((self.0.flags.0 & VMStateFlags::VMS_ARRAY.0) =3D=3D 0); + assert!((self.0.flags.0 & VMStateFlags::VMS_VARRAY_FLAGS.0) =3D=3D= 0); + if (self.0.flags.0 & VMStateFlags::VMS_POINTER.0) !=3D 0 { + self.0.flags =3D VMStateFlags(self.0.flags.0 & !VMStateFlags::= VMS_POINTER.0); + self.0.flags =3D VMStateFlags(self.0.flags.0 | VMStateFlags::V= MS_ARRAY_OF_POINTER.0); // VMS_ARRAY_OF_POINTER flag stores the size of pointer. // FIXME: *const, *mut, NonNull and Box<> have the same size a= s usize. // Resize if more smart pointers are supported. - self.size =3D std::mem::size_of::(); + self.0.size =3D std::mem::size_of::(); } - self.flags =3D VMStateFlags(self.flags.0 & !VMStateFlags::VMS_SING= LE.0); - self.flags =3D VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY= .0); - self.num =3D num as i32; + self.0.flags =3D VMStateFlags(self.0.flags.0 & !VMStateFlags::VMS_= SINGLE.0); + self.0.flags =3D VMStateFlags(self.0.flags.0 | VMStateFlags::VMS_A= RRAY.0); + self.0.num =3D num as i32; self } =20 #[must_use] pub const fn with_pointer_flag(mut self) -> Self { - assert!((self.flags.0 & VMStateFlags::VMS_POINTER.0) =3D=3D 0); - self.flags =3D VMStateFlags(self.flags.0 | VMStateFlags::VMS_POINT= ER.0); + assert!((self.0.flags.0 & VMStateFlags::VMS_POINTER.0) =3D=3D 0); + self.0.flags =3D VMStateFlags(self.0.flags.0 | VMStateFlags::VMS_P= OINTER.0); self } =20 #[must_use] - pub const fn with_varray_flag_unchecked(mut self, flag: VMStateFlags) = -> VMStateField { - self.flags =3D VMStateFlags(self.flags.0 & !VMStateFlags::VMS_ARRA= Y.0); - self.flags =3D VMStateFlags(self.flags.0 | flag.0); - self.num =3D 0; // varray uses num_offset instead of num. + pub const fn with_varray_flag_unchecked(mut self, flag: VMStateFlags) = -> Self { + self.0.flags =3D VMStateFlags(self.0.flags.0 & !VMStateFlags::VMS_= ARRAY.0); + self.0.flags =3D VMStateFlags(self.0.flags.0 | flag.0); + self.0.num =3D 0; // varray uses num_offset instead of num. self } =20 #[must_use] #[allow(unused_mut)] - pub const fn with_varray_flag(mut self, flag: VMStateFlags) -> VMState= Field { - assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) !=3D 0); + pub const fn with_varray_flag(mut self, flag: VMStateFlags) -> Self { + assert!((self.0.flags.0 & VMStateFlags::VMS_ARRAY.0) !=3D 0); self.with_varray_flag_unchecked(flag) } =20 #[must_use] - pub const fn with_varray_multiply(mut self, num: u32) -> VMStateField { + pub const fn with_varray_multiply(mut self, num: u32) -> Self { assert!(num <=3D 0x7FFF_FFFFu32); - self.flags =3D VMStateFlags(self.flags.0 | VMStateFlags::VMS_MULTI= PLY_ELEMENTS.0); - self.num =3D num as i32; + self.0.flags =3D VMStateFlags(self.0.flags.0 | VMStateFlags::VMS_M= ULTIPLY_ELEMENTS.0); + self.0.num =3D num as i32; self } } @@ -303,7 +316,7 @@ pub const fn with_varray_multiply(mut self, num: u32) -= > VMStateField { /// # Examples /// /// ``` -/// # use qemu_api::impl_vmstate_forward; +/// # use migration::impl_vmstate_forward; /// pub struct Fifo([u8; 16]); /// impl_vmstate_forward!(Fifo); /// ``` @@ -341,7 +354,7 @@ unsafe impl<$base> $crate::vmstate::VMState for $type w= here $base: $crate::vmsta impl_vmstate_transparent!(std::cell::Cell where T: VMState); impl_vmstate_transparent!(std::cell::UnsafeCell where T: VMState); impl_vmstate_transparent!(std::pin::Pin where T: VMState); -impl_vmstate_transparent!(::common::Opaque where T: VMState); +impl_vmstate_transparent!(common::Opaque where T: VMState); =20 #[macro_export] macro_rules! impl_vmstate_bitsized { @@ -367,12 +380,12 @@ unsafe impl $crate::vmstate::VMState for $type { =20 macro_rules! impl_vmstate_scalar { ($info:ident, $type:ty$(, $varray_flag:ident)?) =3D> { - unsafe impl VMState for $type { - const SCALAR_TYPE: VMStateFieldType =3D VMStateFieldType::$inf= o; - const BASE: VMStateField =3D VMStateField { - size: mem::size_of::<$type>(), - flags: VMStateFlags::VMS_SINGLE, - ..Zeroable::ZERO + unsafe impl $crate::vmstate::VMState for $type { + const SCALAR_TYPE: $crate::vmstate::VMStateFieldType =3D $crat= e::vmstate::VMStateFieldType::$info; + const BASE: $crate::vmstate::VMStateField =3D $crate::vmstate:= :VMStateField { + size: ::std::mem::size_of::<$type>(), + flags: $crate::vmstate::VMStateFlags::VMS_SINGLE, + ..::common::zeroable::Zeroable::ZERO }; $(const VARRAY_FLAG: VMStateFlags =3D VMStateFlags::$varray_fl= ag;)? } @@ -399,7 +412,7 @@ macro_rules! impl_vmstate_pointer { ($type:ty where $base:tt: VMState $($where:tt)*) =3D> { unsafe impl<$base> $crate::vmstate::VMState for $type where $base:= $crate::vmstate::VMState $($where)* { const SCALAR_TYPE: $crate::vmstate::VMStateFieldType =3D ::SCALAR_TYPE; - const BASE: $crate::vmstate::VMStateField =3D <$base as $crate= ::vmstate::VMState>::BASE.with_pointer_flag(); + const BASE: $crate::vmstate::VMStateField =3D $crate::vmstate:= :VMStateFieldHelper(<$base as $crate::vmstate::VMState>::BASE).with_pointer= _flag().0; } }; } @@ -417,7 +430,9 @@ unsafe impl<$base> $crate::vmstate::VMState for $type w= here $base: $crate::vmsta =20 unsafe impl VMState for [T; N] { const SCALAR_TYPE: VMStateFieldType =3D ::SCALAR_TYPE; - const BASE: VMStateField =3D ::BASE.with_array_flag(N); + const BASE: VMStateField =3D VMStateFieldHelper(::BASE) + .with_array_flag(N) + .0; } =20 #[doc(alias =3D "VMSTATE_UNUSED")] @@ -429,7 +444,7 @@ macro_rules! vmstate_unused { size: $size, info: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate= _info_unused_buffer) }, flags: $crate::bindings::VMStateFlags::VMS_BUFFER, - ..::common::zeroable::Zeroable::ZERO + ..::common::Zeroable::ZERO } }}; } @@ -452,7 +467,7 @@ pub extern "C" fn rust_vms_test_field_exists {{ - const fn test_cb_builder__ ::common::callbacks::FnCa= ll<(&'a T, u8), bool>>( + const fn test_cb_builder__ ::common::FnCall<(&'a T, = u8), bool>>( _phantom: ::core::marker::PhantomData, ) -> $crate::vmstate::VMSFieldExistCb { let _: () =3D F::ASSERT_IS_SOME; @@ -477,7 +492,7 @@ const fn phantom__(_: &T) -> ::core::marker::Phantom= Data { #[macro_export] macro_rules! vmstate_struct { ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:exp= r)?])?, $vmsd:expr, $type:ty $(, $test_fn:expr)? $(,)?) =3D> { - $crate::bindings::VMStateField { + $crate::vmstate::VMStateFieldHelper($crate::bindings::VMStateField= { name: ::core::concat!(::core::stringify!($field_name), "\0") .as_bytes() .as_ptr() as *const ::std::os::raw::c_char, @@ -490,8 +505,8 @@ macro_rules! vmstate_struct { flags: $crate::bindings::VMStateFlags::VMS_STRUCT, vmsd: $vmsd, $(field_exists: $crate::vmstate_exist_fn!($struct_name, $test_= fn),)? - ..::common::zeroable::Zeroable::ZERO - } $(.with_varray_flag_unchecked( + ..::common::Zeroable::ZERO + }) $(.with_varray_flag_unchecked( $crate::call_func_with_field!( $crate::vmstate::vmstate_varray_flag, $struct_name, @@ -499,6 +514,7 @@ macro_rules! vmstate_struct { ) ) $(.with_varray_multiply($factor))?)? + .0 }; } =20 @@ -512,7 +528,7 @@ macro_rules! vmstate_fields { $($field),*, $crate::bindings::VMStateField { flags: $crate::bindings::VMStateFlags::VMS_END, - ..::common::zeroable::Zeroable::ZERO + ..::common::Zeroable::ZERO } ]; _FIELDS.as_ptr() @@ -531,7 +547,7 @@ macro_rules! vmstate_validate { | $crate::bindings::VMStateFlags::VMS_ARRAY.0, ), num: 0, // 0 elements: no data, only run test_fn callback - ..::common::zeroable::Zeroable::ZERO + ..common::Zeroable::ZERO } }; } diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index 28e5969e7a..e040b93224 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -15,6 +15,7 @@ rust-version.workspace =3D true =20 [dependencies] common =3D { path =3D "../common" } +migration =3D { path =3D "../migration" } util =3D { path =3D "../util" } qemu_api_macros =3D { path =3D "../qemu-api-macros" } anyhow =3D "~1.0" diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index 8a2950dfe4..ee6311cd3f 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -11,8 +11,6 @@ c_enums =3D [ 'GpioPolarity', 'MachineInitPhase', 'MemoryDeviceInfoKind', - 'MigrationPolicy', - 'MigrationPriority', 'QEMUChrEvent', 'ResetType', 'device_endian', @@ -23,12 +21,13 @@ foreach enum : c_enums endforeach c_bitfields =3D [ 'ClockEvent', - 'VMStateFlags', ] foreach enum : c_bitfields _qemu_api_bindgen_args +=3D ['--bitfield-enum', enum] endforeach =20 +_qemu_api_bindgen_args +=3D ['--blocklist-type', 'VMStateDescription'] + _qemu_api_bindgen_args +=3D ['--blocklist-type', 'Error'] # TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. # @@ -60,14 +59,13 @@ _qemu_api_rs =3D static_library( 'src/qdev.rs', 'src/qom.rs', 'src/sysbus.rs', - 'src/vmstate.rs', ], {'.' : _qemu_api_bindings_inc_rs}, ), override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _qemu_api_cfg, - dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, qemu_api_macro= s, qemuutil_rs, util_rs, + dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, qemu_api_macro= s, qemuutil_rs, util_rs, migration_rs, qom, hwcore, chardev, migration], ) =20 @@ -93,7 +91,7 @@ test('rust-qemu-api-integration', override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_args: ['--test'], install: false, - dependencies: [common_rs, util_rs, qemu_api]), + dependencies: [common_rs, util_rs, migration_rs, qemu_api]), args: [ '--test', '--test-threads', '1', '--format', 'pretty', diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs index aedf42b652..ce00a6e0e4 100644 --- a/rust/qemu-api/src/bindings.rs +++ b/rust/qemu-api/src/bindings.rs @@ -21,6 +21,7 @@ //! `bindgen`-generated declarations. =20 use common::Zeroable; +use migration::bindings::VMStateDescription; use util::bindings::Error; =20 #[cfg(MESON)] @@ -51,28 +52,8 @@ unsafe impl Sync for Property {} unsafe impl Send for TypeInfo {} unsafe impl Sync for TypeInfo {} =20 -unsafe impl Send for VMStateDescription {} -unsafe impl Sync for VMStateDescription {} - -unsafe impl Send for VMStateField {} -unsafe impl Sync for VMStateField {} - -unsafe impl Send for VMStateInfo {} -unsafe impl Sync for VMStateInfo {} - -// bindgen does not derive Default here -#[allow(clippy::derivable_impls)] -impl Default for crate::bindings::VMStateFlags { - fn default() -> Self { - Self(0) - } -} - unsafe impl Zeroable for crate::bindings::Property__bindgen_ty_1 {} unsafe impl Zeroable for crate::bindings::Property {} -unsafe impl Zeroable for crate::bindings::VMStateFlags {} -unsafe impl Zeroable for crate::bindings::VMStateField {} -unsafe impl Zeroable for crate::bindings::VMStateDescription {} unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_1 {} unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_2 {} unsafe impl Zeroable for crate::bindings::MemoryRegionOps {} diff --git a/rust/qemu-api/src/cell.rs b/rust/qemu-api/src/cell.rs index 4bce526e45..70cee2ca7a 100644 --- a/rust/qemu-api/src/cell.rs +++ b/rust/qemu-api/src/cell.rs @@ -152,7 +152,9 @@ ptr::NonNull, }; =20 -use crate::{bindings, impl_vmstate_transparent}; +use migration::impl_vmstate_transparent; + +use crate::bindings; =20 /// An internal function that is used by doctests. pub fn bql_start_test() { diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index db81841a8f..52e4d5889b 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -20,4 +20,3 @@ pub mod qdev; pub mod qom; pub mod sysbus; -pub mod vmstate; diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs index 3d771481e4..c10c171158 100644 --- a/rust/qemu-api/src/prelude.rs +++ b/rust/qemu-api/src/prelude.rs @@ -21,5 +21,3 @@ pub use crate::qom_isa; =20 pub use crate::sysbus::SysBusDeviceMethods; - -pub use crate::vmstate::VMState; diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs index 5469eef22a..15e1fdff96 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/qemu-api/src/qdev.rs @@ -11,6 +11,7 @@ =20 pub use bindings::{ClockEvent, DeviceClass, Property, ResetType}; use common::{callbacks::FnCall, Opaque}; +use migration::vmstate::VMStateDescription; pub use util::{Error, Result}; =20 use crate::{ @@ -20,7 +21,6 @@ irq::InterruptSource, prelude::*, qom::{ObjectClass, ObjectImpl, Owned, ParentInit}, - vmstate::VMStateDescription, }; =20 /// A safe wrapper around [`bindings::Clock`]. @@ -413,7 +413,7 @@ unsafe impl ObjectType for Clock { #[macro_export] macro_rules! vmstate_clock { ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:exp= r)?])?) =3D> {{ - $crate::bindings::VMStateField { + ::migration::VMStateField { name: ::core::concat!(::core::stringify!($field_name), "\0") .as_bytes() .as_ptr() as *const ::std::os::raw::c_char, @@ -426,9 +426,9 @@ macro_rules! vmstate_clock { ::std::mem::offset_of!($struct_name, $field_name) }, size: ::core::mem::size_of::<*const $crate::qdev::Clock>(), - flags: $crate::bindings::VMStateFlags( - $crate::bindings::VMStateFlags::VMS_STRUCT.0 - | $crate::bindings::VMStateFlags::VMS_POINTER.0, + flags: ::migration::VMStateFlags( + ::migration::VMStateFlags::VMS_STRUCT.0 + | ::migration::VMStateFlags::VMS_POINTER.0, ), vmsd: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate= _clock) }, ..::common::zeroable::Zeroable::ZERO diff --git a/rust/qemu-api/src/qom.rs b/rust/qemu-api/src/qom.rs index 56feff3e17..901445013c 100644 --- a/rust/qemu-api/src/qom.rs +++ b/rust/qemu-api/src/qom.rs @@ -103,6 +103,7 @@ =20 pub use bindings::ObjectClass; use common::Opaque; +use migration::impl_vmstate_pointer; =20 use crate::{ bindings::{ @@ -110,7 +111,6 @@ object_get_typename, object_new, object_ref, object_unref, TypeInf= o, }, cell::bql_locked, - impl_vmstate_pointer, }; =20 /// A safe wrapper around [`bindings::Object`]. diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 1dd4e29754..2ea4f88dd1 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -5,6 +5,7 @@ use std::{ffi::CStr, ptr::addr_of}; =20 use common::Zeroable; +use migration::VMStateDescription; use qemu_api::{ bindings::qdev_prop_bool, cell::{self, BqlCell}, @@ -13,7 +14,6 @@ qdev::{DeviceImpl, DeviceState, Property, ResettablePhasesImpl}, qom::{ObjectImpl, ParentField}, sysbus::SysBusDevice, - vmstate::VMStateDescription, }; use util::bindings::{module_call_init, module_init_type}; =20 diff --git a/rust/qemu-api/tests/vmstate_tests.rs b/rust/qemu-api/tests/vms= tate_tests.rs index 1ec80c483e..3f64eb46c0 100644 --- a/rust/qemu-api/tests/vmstate_tests.rs +++ b/rust/qemu-api/tests/vmstate_tests.rs @@ -10,16 +10,16 @@ }; =20 use common::{Opaque, Zeroable}; -use qemu_api::{ +use migration::{ bindings::{ vmstate_info_bool, vmstate_info_int32, vmstate_info_int64, vmstate= _info_int8, vmstate_info_uint64, vmstate_info_uint8, vmstate_info_unused_buffe= r, VMStateFlags, }, - cell::BqlCell, impl_vmstate_forward, - vmstate::{VMStateDescription, VMStateField}, + vmstate::{VMStateDescription, VMStateField, VMStateFieldHelper}, vmstate_fields, vmstate_of, vmstate_struct, vmstate_unused, vmstate_va= lidate, }; +use qemu_api::cell::BqlCell; =20 const FOO_ARRAY_MAX: usize =3D 3; =20 @@ -48,7 +48,7 @@ struct FooA { fields: vmstate_fields! { vmstate_of!(FooA, elem), vmstate_unused!(size_of::()), - vmstate_of!(FooA, arr[0 .. num]).with_version_id(0), + VMStateFieldHelper(vmstate_of!(FooA, arr[0 .. num])).with_version_= id(0).0, vmstate_of!(FooA, arr_mul[0 .. num_mul * 16]), }, ..Zeroable::ZERO @@ -176,10 +176,10 @@ fn validate_foob(_state: &FooB, _version_id: u8) -> b= ool { version_id: 2, minimum_version_id: 1, fields: vmstate_fields! { - vmstate_of!(FooB, val).with_version_id(2), + VMStateFieldHelper(vmstate_of!(FooB, val)).with_version_id(2).0, 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_FOO= A, FooA).with_version_id(2), + VMStateFieldHelper(vmstate_struct!(FooB, arr_a[0 .. num_a], &VMSTA= TE_FOOA, FooA)).with_version_id(1).0, + VMStateFieldHelper(vmstate_struct!(FooB, arr_a_mul[0 .. num_a_mul = * 32], &VMSTATE_FOOA, FooA)).with_version_id(2).0, vmstate_of!(FooB, arr_i64), vmstate_struct!(FooB, arr_a_wrap[0 .. num_a_wrap], &VMSTATE_FOOA, = FooA, validate_foob), }, @@ -340,7 +340,7 @@ struct FooC { version_id: 3, minimum_version_id: 1, fields: vmstate_fields! { - vmstate_of!(FooC, ptr).with_version_id(2), + VMStateFieldHelper(vmstate_of!(FooC, ptr)).with_version_id(2).0, // FIXME: Currently vmstate_struct doesn't support the pointer to = structure. // VMSTATE_STRUCT_POINTER: vmstate_struct!(FooC, ptr_a, VMSTATE_FO= OA, NonNull) vmstate_unused!(size_of::>()), --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217637; cv=none; d=zohomail.com; s=zohoarc; b=d6L32nBx+cZQgB8KzJQDtOVoVKlc79uN3O9RMpDkrNyTf7iQIiRUeluWaaU9wXhwPSFyjD2A7+x/KzOvmcjV+e/jOBk/yBldogstC/jhhdab+WwyS912HWKMLAmqVRAt7WoJ1SeNFJpdH2lkYN6i1V8x4GPCyPXwkr2ZMPbkHO4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217637; h=Content-Type: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=hAhCOinPzLOZ8/yDe5DrUzvaJfEUXbPjqrXWT+2TUeM=; b=Oh0L/8uGyzuhsDxZjcI7mmmbbNhnytUmaxeDkCzrDdYQMR5aJhQIhtgOxAEL1YIENlrpOoUXg4/T7ubM1o+YyjnZ6a9HUA3/jCC2jOxjoVFyQ+0u9PjtS2kT18NWpy59De0SwPgAKzz6XDp8Vvp/82CT5q34/WrIzFC71U97axA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217637964181.4048418104245; Tue, 26 Aug 2025 07:13:57 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJO-0006FB-JU; Tue, 26 Aug 2025 10:06:10 -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 1uquJL-0006Dh-8v for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:07 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquJ8-00074y-Pv for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:06 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-274-nYmq-5a4NmqjK8hwq1Hd4g-1; Tue, 26 Aug 2025 10:05:48 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id F2CC31800290; Tue, 26 Aug 2025 14:05:45 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 545171800446; Tue, 26 Aug 2025 14:05:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217151; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hAhCOinPzLOZ8/yDe5DrUzvaJfEUXbPjqrXWT+2TUeM=; b=Ujn9zzfz4Y/ZkKZNU2n9kGU1kq/LQnb1IAhIGSro3XCdH9F6S3E9lBWrgh9GyNh0ejJ5G0 2IBoKiZUgeUL9VJyj+9kcmLvAfSzoN0o2DJtTVDq5ZY/PI67pX5CMSu+1ogn/rn0+eKRR4 GEqX1da0kFOe17xYaUXKwIBsCcwHxho= X-MC-Unique: nYmq-5a4NmqjK8hwq1Hd4g-1 X-Mimecast-MFC-AGG-ID: nYmq-5a4NmqjK8hwq1Hd4g_1756217146 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 09/18] rust: split "bql" crate Date: Tue, 26 Aug 2025 18:04:37 +0400 Message-ID: <20250826140449.4190022-10-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 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=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_INVALID=0.1, DKIM_SIGNED=0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, T_SPF_TEMPERROR=0.01 autolearn=no 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 @redhat.com) X-ZM-MESSAGEID: 1756217639846124100 From: Marc-Andr=C3=A9 Lureau Unfortunately, an example had to be compile-time disabled, since it relies on higher level crates (qdev, irq etc). The alternative is probably to move that code to an example in qemu-api or elsewere and make a link to it, or include_str. Signed-off-by: Marc-Andr=C3=A9 Lureau --- MAINTAINERS | 1 + rust/bql/wrapper.h | 27 ++++++++ rust/Cargo.lock | 10 +++ rust/Cargo.toml | 1 + rust/bql/Cargo.toml | 23 +++++++ rust/bql/build.rs | 43 +++++++++++++ rust/bql/meson.build | 52 ++++++++++++++++ rust/bql/src/bindings.rs | 25 ++++++++ rust/{qemu-api =3D> bql}/src/cell.rs | 92 ++++++++++------------------ rust/bql/src/lib.rs | 29 +++++++++ rust/common/src/opaque.rs | 4 +- rust/hw/char/pl011/Cargo.toml | 1 + rust/hw/char/pl011/meson.build | 1 + rust/hw/char/pl011/src/device.rs | 1 + rust/hw/timer/hpet/Cargo.toml | 1 + rust/hw/timer/hpet/meson.build | 1 + rust/hw/timer/hpet/src/device.rs | 2 +- rust/hw/timer/hpet/src/fw_cfg.rs | 5 +- rust/meson.build | 1 + rust/migration/src/vmstate.rs | 4 +- rust/qemu-api/Cargo.toml | 1 + rust/qemu-api/meson.build | 9 +-- rust/qemu-api/src/chardev.rs | 17 +++-- rust/qemu-api/src/irq.rs | 1 + rust/qemu-api/src/lib.rs | 1 - rust/qemu-api/src/prelude.rs | 3 - rust/qemu-api/src/qdev.rs | 5 +- rust/qemu-api/src/qom.rs | 13 ++-- rust/qemu-api/src/sysbus.rs | 13 ++-- rust/qemu-api/tests/tests.rs | 4 +- rust/qemu-api/tests/vmstate_tests.rs | 2 +- 31 files changed, 286 insertions(+), 107 deletions(-) create mode 100644 rust/bql/wrapper.h create mode 100644 rust/bql/Cargo.toml create mode 100644 rust/bql/build.rs create mode 100644 rust/bql/meson.build create mode 100644 rust/bql/src/bindings.rs rename rust/{qemu-api =3D> bql}/src/cell.rs (92%) create mode 100644 rust/bql/src/lib.rs diff --git a/MAINTAINERS b/MAINTAINERS index bb4f5f011f..0b5f327d4f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3510,6 +3510,7 @@ F: include/hw/registerfields.h Rust M: Manos Pitsidianakis S: Maintained +F: rust/bql/ F: rust/common/ F: rust/migration/ F: rust/qemu-api diff --git a/rust/bql/wrapper.h b/rust/bql/wrapper.h new file mode 100644 index 0000000000..2ef9a96e1d --- /dev/null +++ b/rust/bql/wrapper.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * This header file is meant to be used as input to the `bindgen` applicat= ion + * 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 sym= bols + * 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/main-loop.h" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 58bfbaf545..76ff79f81a 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -44,6 +44,13 @@ dependencies =3D [ "qemu_api_macros", ] =20 +[[package]] +name =3D "bql" +version =3D "0.1.0" +dependencies =3D [ + "migration", +] + [[package]] name =3D "common" version =3D "0.1.0" @@ -67,6 +74,7 @@ dependencies =3D [ name =3D "hpet" version =3D "0.1.0" dependencies =3D [ + "bql", "common", "migration", "qemu_api", @@ -105,6 +113,7 @@ dependencies =3D [ "bilge", "bilge-impl", "bits", + "bql", "common", "migration", "qemu_api", @@ -149,6 +158,7 @@ name =3D "qemu_api" version =3D "0.1.0" dependencies =3D [ "anyhow", + "bql", "common", "foreign", "libc", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index df6a385d64..3ce1977ee0 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -2,6 +2,7 @@ resolver =3D "2" members =3D [ "bits", + "bql", "common", "migration", "qemu-api-macros", diff --git a/rust/bql/Cargo.toml b/rust/bql/Cargo.toml new file mode 100644 index 0000000000..1041bd4ea9 --- /dev/null +++ b/rust/bql/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name =3D "bql" +version =3D "0.1.0" +description =3D "Rust bindings for QEMU/BQL" +resolver =3D "2" +publish =3D false + +authors.workspace =3D true +edition.workspace =3D true +homepage.workspace =3D true +license.workspace =3D true +repository.workspace =3D true +rust-version.workspace =3D true + +[dependencies] +migration =3D { path =3D "../migration" } + +[features] +default =3D ["debug_cell"] +debug_cell =3D [] + +[lints] +workspace =3D true diff --git a/rust/bql/build.rs b/rust/bql/build.rs new file mode 100644 index 0000000000..5a68a1e64a --- /dev/null +++ b/rust/bql/build.rs @@ -0,0 +1,43 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis +// SPDX-License-Identifier: GPL-2.0-or-later + +#[cfg(unix)] +use std::os::unix::fs::symlink as symlink_file; +#[cfg(windows)] +use std::os::windows::fs::symlink_file; +use std::{env, fs::remove_file, io::Result, path::Path}; + +fn main() -> Result<()> { + let file =3D if let Ok(root) =3D env::var("MESON_BUILD_ROOT") { + format!("{root}/rust/bql/bindings.inc.rs") + } else { + // Placing bindings.inc.rs in the source directory is supported + // but not documented or encouraged. + format!("{}/src/bindings.inc.rs", env!("CARGO_MANIFEST_DIR")) + }; + + let file =3D Path::new(&file); + if !Path::new(&file).exists() { + panic!(concat!( + "\n", + " No generated C bindings found! Maybe you wanted one of\n", + " `make clippy`, `make rustfmt`, `make rustdoc`?\n", + "\n", + " For other uses of `cargo`, start a subshell with\n", + " `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n= ", + " the top of the build tree." + )); + } + + let out_dir =3D env::var("OUT_DIR").unwrap(); + let dest_path =3D format!("{out_dir}/bindings.inc.rs"); + let dest_path =3D Path::new(&dest_path); + if dest_path.symlink_metadata().is_ok() { + remove_file(dest_path)?; + } + symlink_file(file, dest_path)?; + + println!("cargo:rerun-if-changed=3Dbuild.rs"); + Ok(()) +} diff --git a/rust/bql/meson.build b/rust/bql/meson.build new file mode 100644 index 0000000000..465774a5b2 --- /dev/null +++ b/rust/bql/meson.build @@ -0,0 +1,52 @@ +_bql_cfg =3D run_command(rustc_args, + '--config-headers', config_host_h, '--features', files('Cargo.toml'), + capture: true, check: true).stdout().strip().splitlines() + +if get_option('debug_mutex') + _bql_cfg +=3D ['--cfg', 'feature=3D"debug_cell"'] +endif + +# +# TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. +# +# Rust bindings generation with `bindgen` might fail in some cases where t= he +# 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 +_bql_bindings_inc_rs =3D rust.bindgen( + input: 'wrapper.h', + dependencies: common_ss.all_dependencies(), + output: 'bindings.inc.rs', + include_directories: bindings_incdir, + bindgen_version: ['>=3D0.60.0'], + args: bindgen_args_common, +) + +_bql_rs =3D static_library( + 'bql', + structured_sources( + [ + 'src/lib.rs', + 'src/bindings.rs', + 'src/cell.rs', + ], + {'.': _bql_bindings_inc_rs} + ), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_abi: 'rust', + rust_args: _bql_cfg, + dependencies: [migration_rs, qemuutil_rs], +) + +bql_rs =3D declare_dependency(link_with: [_bql_rs], + dependencies: [qemuutil_rs]) + +# Doctests are essentially integration tests, so they need the same depend= encies. +# Note that running them requires the object files for C code, so place th= em +# in a separate suite that is run by the "build" CI jobs rather than "chec= k". +rust.doctest('rust-bql-rs-doctests', + _bql_rs, + protocol: 'rust', + dependencies: bql_rs, + suite: ['doc', 'rust']) diff --git a/rust/bql/src/bindings.rs b/rust/bql/src/bindings.rs new file mode 100644 index 0000000000..9ffff12cde --- /dev/null +++ b/rust/bql/src/bindings.rs @@ -0,0 +1,25 @@ +// 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 +)] + +#[cfg(MESON)] +include!("bindings.inc.rs"); + +#[cfg(not(MESON))] +include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); diff --git a/rust/qemu-api/src/cell.rs b/rust/bql/src/cell.rs similarity index 92% rename from rust/qemu-api/src/cell.rs rename to rust/bql/src/cell.rs index 70cee2ca7a..43109130c5 100644 --- a/rust/qemu-api/src/cell.rs +++ b/rust/bql/src/cell.rs @@ -75,9 +75,10 @@ //! //! ### Example //! -//! ``` +//! ```ignore +//! # use bql::BqlRefCell; //! # use qemu_api::prelude::*; -//! # use qemu_api::{cell::BqlRefCell, irq::InterruptSource, irq::IRQState= }; +//! # use qemu_api::{irq::InterruptSource, irq::IRQState}; //! # use qemu_api::{sysbus::SysBusDevice, qom::Owned, qom::ParentField}; //! # const N_GPIOS: usize =3D 8; //! # struct PL061Registers { /* ... */ } @@ -141,7 +142,6 @@ //! Multiple immutable borrows are allowed via [`borrow`](BqlRefCell::borr= ow), //! or a single mutable borrow via [`borrow_mut`](BqlRefCell::borrow_mut).= The //! thread will panic if these rules are violated or if the BQL is not hel= d. - use std::{ cell::{Cell, UnsafeCell}, cmp::Ordering, @@ -154,30 +154,6 @@ =20 use migration::impl_vmstate_transparent; =20 -use crate::bindings; - -/// An internal function that is used by doctests. -pub fn bql_start_test() { - // SAFETY: integration tests are run with --test-threads=3D1, while - // unit tests and doctests are not multithreaded and do not have - // any BQL-protected data. Just set bql_locked to true. - unsafe { - bindings::rust_bql_mock_lock(); - } -} - -pub fn bql_locked() -> bool { - // SAFETY: the function does nothing but return a thread-local bool - unsafe { bindings::bql_locked() } -} - -fn bql_block_unlock(increase: bool) { - // SAFETY: this only adjusts a counter - unsafe { - bindings::bql_block_unlock(increase); - } -} - /// A mutable memory location that is protected by the Big QEMU Lock. /// /// # Memory layout @@ -256,8 +232,8 @@ impl BqlCell { /// # Examples /// /// ``` - /// use qemu_api::cell::BqlCell; - /// # qemu_api::cell::bql_start_test(); + /// use bql::BqlCell; + /// # bql::start_test(); /// /// let c =3D BqlCell::new(5); /// ``` @@ -273,8 +249,8 @@ pub const fn new(value: T) -> BqlCell { /// # Examples /// /// ``` - /// use qemu_api::cell::BqlCell; - /// # qemu_api::cell::bql_start_test(); + /// use bql::BqlCell; + /// # bql::start_test(); /// /// let c =3D BqlCell::new(5); /// @@ -291,8 +267,8 @@ pub fn set(&self, val: T) { /// # Examples /// /// ``` - /// use qemu_api::cell::BqlCell; - /// # qemu_api::cell::bql_start_test(); + /// use bql::BqlCell; + /// # bql::start_test(); /// /// let cell =3D BqlCell::new(5); /// assert_eq!(cell.get(), 5); @@ -301,7 +277,7 @@ pub fn set(&self, val: T) { /// ``` #[inline] pub fn replace(&self, val: T) -> T { - assert!(bql_locked()); + assert!(crate::is_locked()); // SAFETY: This can cause data races if called from multiple threa= ds, // but it won't happen as long as C code accesses the value // under BQL protection only. @@ -313,8 +289,8 @@ pub fn replace(&self, val: T) -> T { /// # Examples /// /// ``` - /// use qemu_api::cell::BqlCell; - /// # qemu_api::cell::bql_start_test(); + /// use bql::BqlCell; + /// # bql::start_test(); /// /// let c =3D BqlCell::new(5); /// let five =3D c.into_inner(); @@ -322,7 +298,7 @@ pub fn replace(&self, val: T) -> T { /// assert_eq!(five, 5); /// ``` pub fn into_inner(self) -> T { - assert!(bql_locked()); + assert!(crate::is_locked()); self.value.into_inner() } } @@ -333,8 +309,8 @@ impl BqlCell { /// # Examples /// /// ``` - /// use qemu_api::cell::BqlCell; - /// # qemu_api::cell::bql_start_test(); + /// use bql::BqlCell; + /// # bql::start_test(); /// /// let c =3D BqlCell::new(5); /// @@ -342,7 +318,7 @@ impl BqlCell { /// ``` #[inline] pub fn get(&self) -> T { - assert!(bql_locked()); + assert!(crate::is_locked()); // SAFETY: This can cause data races if called from multiple threa= ds, // but it won't happen as long as C code accesses the value // under BQL protection only. @@ -356,8 +332,8 @@ impl BqlCell { /// # Examples /// /// ``` - /// use qemu_api::cell::BqlCell; - /// # qemu_api::cell::bql_start_test(); + /// use bql::BqlCell; + /// # bql::start_test(); /// /// let c =3D BqlCell::new(5); /// @@ -375,8 +351,8 @@ impl BqlCell { /// # Examples /// /// ``` - /// use qemu_api::cell::BqlCell; - /// # qemu_api::cell::bql_start_test(); + /// use bql::BqlCell; + /// # bql::start_test(); /// /// let c =3D BqlCell::new(5); /// let five =3D c.take(); @@ -445,7 +421,7 @@ impl BqlRefCell { /// # Examples /// /// ``` - /// use qemu_api::cell::BqlRefCell; + /// use bql::BqlRefCell; /// /// let c =3D BqlRefCell::new(5); /// ``` @@ -504,8 +480,8 @@ fn panic_already_borrowed(&self) -> ! { /// # Examples /// /// ``` - /// use qemu_api::cell::BqlRefCell; - /// # qemu_api::cell::bql_start_test(); + /// use bql::BqlRefCell; + /// # bql::start_test(); /// /// let c =3D BqlRefCell::new(5); /// @@ -516,8 +492,8 @@ fn panic_already_borrowed(&self) -> ! { /// An example of panic: /// /// ```should_panic - /// use qemu_api::cell::BqlRefCell; - /// # qemu_api::cell::bql_start_test(); + /// use bql::BqlRefCell; + /// # bql::start_test(); /// /// let c =3D BqlRefCell::new(5); /// @@ -534,7 +510,7 @@ pub fn borrow(&self) -> BqlRef<'_, T> { self.borrowed_at.set(Some(std::panic::Location::caller())); } =20 - bql_block_unlock(true); + crate::block_unlock(true); =20 // SAFETY: `BorrowRef` ensures that there is only immutable ac= cess // to the value while borrowed. @@ -558,8 +534,8 @@ pub fn borrow(&self) -> BqlRef<'_, T> { /// # Examples /// /// ``` - /// use qemu_api::cell::BqlRefCell; - /// # qemu_api::cell::bql_start_test(); + /// use bql::BqlRefCell; + /// # bql::start_test(); /// /// let c =3D BqlRefCell::new("hello".to_owned()); /// @@ -571,8 +547,8 @@ pub fn borrow(&self) -> BqlRef<'_, T> { /// An example of panic: /// /// ```should_panic - /// use qemu_api::cell::BqlRefCell; - /// # qemu_api::cell::bql_start_test(); + /// use bql::BqlRefCell; + /// # bql::start_test(); /// /// let c =3D BqlRefCell::new(5); /// let m =3D c.borrow(); @@ -589,7 +565,7 @@ pub fn borrow_mut(&self) -> BqlRefMut<'_, T> { } =20 // SAFETY: this only adjusts a counter - bql_block_unlock(true); + crate::block_unlock(true); =20 // SAFETY: `BorrowRefMut` guarantees unique access. let value =3D unsafe { NonNull::new_unchecked(self.value.get()= ) }; @@ -608,7 +584,7 @@ pub fn borrow_mut(&self) -> BqlRefMut<'_, T> { /// # Examples /// /// ``` - /// use qemu_api::cell::BqlRefCell; + /// use bql::BqlRefCell; /// /// let c =3D BqlRefCell::new(5); /// @@ -733,7 +709,7 @@ fn drop(&mut self) { let borrow =3D self.borrow.get(); debug_assert!(is_reading(borrow)); self.borrow.set(borrow - 1); - bql_block_unlock(false) + crate::block_unlock(false) } } =20 @@ -823,7 +799,7 @@ fn drop(&mut self) { let borrow =3D self.borrow.get(); debug_assert!(is_writing(borrow)); self.borrow.set(borrow + 1); - bql_block_unlock(false) + crate::block_unlock(false) } } =20 diff --git a/rust/bql/src/lib.rs b/rust/bql/src/lib.rs new file mode 100644 index 0000000000..ef08221e9c --- /dev/null +++ b/rust/bql/src/lib.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +mod bindings; +use bindings::{bql_block_unlock, bql_locked, rust_bql_mock_lock}; + +mod cell; +pub use cell::*; + +/// An internal function that is used by doctests. +pub fn start_test() { + // SAFETY: integration tests are run with --test-threads=3D1, while + // unit tests and doctests are not multithreaded and do not have + // any BQL-protected data. Just set bql_locked to true. + unsafe { + rust_bql_mock_lock(); + } +} + +pub fn is_locked() -> bool { + // SAFETY: the function does nothing but return a thread-local bool + unsafe { bql_locked() } +} + +pub fn block_unlock(increase: bool) { + // SAFETY: this only adjusts a counter + unsafe { + bql_block_unlock(increase); + } +} diff --git a/rust/common/src/opaque.rs b/rust/common/src/opaque.rs index f96b91e25a..e076964634 100644 --- a/rust/common/src/opaque.rs +++ b/rust/common/src/opaque.rs @@ -69,8 +69,8 @@ //! and only at FFI boundaries. For QEMU-specific types that need interior //! mutability, prefer [`BqlCell`] or [`BqlRefCell`]. //! -//! [`BqlCell`]: ../../qemu_api/cell/struct.BqlCell.html -//! [`BqlRefCell`]: ../../qemu_api/cell/struct.BqlRefCell.html +//! [`BqlCell`]: ../../bql/cell/struct.BqlCell.html +//! [`BqlRefCell`]: ../../bql/cell/struct.BqlRefCell.html use std::{cell::UnsafeCell, fmt, marker::PhantomPinned, mem::MaybeUninit, = ptr::NonNull}; =20 /// Stores an opaque value that is shared with C code. diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml index 7fd7531823..1a1d4ba715 100644 --- a/rust/hw/char/pl011/Cargo.toml +++ b/rust/hw/char/pl011/Cargo.toml @@ -18,6 +18,7 @@ bilge-impl =3D { version =3D "0.2.0" } bits =3D { path =3D "../../../bits" } common =3D { path =3D "../../../common" } util =3D { path =3D "../../../util" } +bql =3D { path =3D "../../../bql" } migration =3D { path =3D "../../../migration" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build index e3ddd17351..7062497b7c 100644 --- a/rust/hw/char/pl011/meson.build +++ b/rust/hw/char/pl011/meson.build @@ -10,6 +10,7 @@ _libpl011_rs =3D static_library( common_rs, util_rs, migration_rs, + bql_rs, qemu_api, qemu_api_macros, ], diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 904faa80a9..7cffb894a8 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -8,6 +8,7 @@ ptr::NonNull, }; =20 +use bql::BqlRefCell; use common::{static_assert, uninit_field_mut, Zeroable}; use migration::{ impl_vmstate_forward, vmstate_fields, vmstate_of, vmstate_struct, vmst= ate_subsections, diff --git a/rust/hw/timer/hpet/Cargo.toml b/rust/hw/timer/hpet/Cargo.toml index 70acdf03d6..9fcec38bfa 100644 --- a/rust/hw/timer/hpet/Cargo.toml +++ b/rust/hw/timer/hpet/Cargo.toml @@ -14,6 +14,7 @@ rust-version.workspace =3D true common =3D { path =3D "../../../common" } util =3D { path =3D "../../../util" } migration =3D { path =3D "../../../migration" } +bql =3D { path =3D "../../../bql" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/timer/hpet/meson.build b/rust/hw/timer/hpet/meson.build index 2c605dcf9d..5e01e57210 100644 --- a/rust/hw/timer/hpet/meson.build +++ b/rust/hw/timer/hpet/meson.build @@ -7,6 +7,7 @@ _libhpet_rs =3D static_library( common_rs, util_rs, migration_rs, + bql_rs, qemu_api, qemu_api_macros, ], diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index 35b968cca7..c0e52ce415 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -10,6 +10,7 @@ slice::from_ref, }; =20 +use bql::{BqlCell, BqlRefCell}; use common::{bitops::IntegerExt, uninit_field_mut, Zeroable}; use migration::{ vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmsta= te_validate, @@ -20,7 +21,6 @@ address_space_memory, address_space_stl_le, qdev_prop_bit, qdev_pr= op_bool, qdev_prop_uint32, qdev_prop_usize, }, - cell::{BqlCell, BqlRefCell}, irq::InterruptSource, memory::{ hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder, MEM= TXATTRS_UNSPECIFIED, diff --git a/rust/hw/timer/hpet/src/fw_cfg.rs b/rust/hw/timer/hpet/src/fw_c= fg.rs index 0605225fbb..e569b57b93 100644 --- a/rust/hw/timer/hpet/src/fw_cfg.rs +++ b/rust/hw/timer/hpet/src/fw_cfg.rs @@ -5,7 +5,6 @@ use std::ptr::addr_of_mut; =20 use common::Zeroable; -use qemu_api::cell::bql_locked; =20 /// Each `HPETState` represents a Event Timer Block. The v1 spec supports /// up to 8 blocks. QEMU only uses 1 block (in PC machine). @@ -38,7 +37,7 @@ unsafe impl Zeroable for HPETFwConfig {} =20 impl HPETFwConfig { pub(crate) fn assign_hpet_id() -> Result { - assert!(bql_locked()); + assert!(bql::is_locked()); // SAFETY: all accesses go through these methods, which guarantee // that the accesses are protected by the BQL. let mut fw_cfg =3D unsafe { *addr_of_mut!(hpet_fw_cfg) }; @@ -58,7 +57,7 @@ pub(crate) fn assign_hpet_id() -> Result { } =20 pub(crate) fn update_hpet_cfg(hpet_id: usize, timer_block_id: u32, add= ress: u64) { - assert!(bql_locked()); + assert!(bql::is_locked()); // SAFETY: all accesses go through these methods, which guarantee // that the accesses are protected by the BQL. let mut fw_cfg =3D unsafe { *addr_of_mut!(hpet_fw_cfg) }; diff --git a/rust/meson.build b/rust/meson.build index 826949b2e6..2ba1ea2280 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -27,6 +27,7 @@ subdir('qemu-api-macros') subdir('bits') subdir('util') subdir('migration') +subdir('bql') subdir('qemu-api') =20 subdir('hw') diff --git a/rust/migration/src/vmstate.rs b/rust/migration/src/vmstate.rs index 4f95ab0d49..243f31baf6 100644 --- a/rust/migration/src/vmstate.rs +++ b/rust/migration/src/vmstate.rs @@ -198,8 +198,8 @@ pub const fn vmstate_varray_flag(_: Phantom= Data) -> VMStateFlags /// [`impl_vmstate_bitsized!`](crate::impl_vmstate_bitsized) /// and [`impl_vmstate_forward!`](crate::impl_vmstate_forward) help with t= his. /// -/// [`BqlCell`]: ../../qemu_api/cell/struct.BqlCell.html -/// [`BqlRefCell`]: ../../qemu_api/cell/struct.BqlRefCell.html +/// [`BqlCell`]: ../../bql/cell/struct.BqlCell.html +/// [`BqlRefCell`]: ../../bql/cell/struct.BqlRefCell.html /// [`Owned`]: ../../qemu_api/qom/struct.Owned.html #[macro_export] macro_rules! vmstate_of { diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index e040b93224..511eb6cb89 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -17,6 +17,7 @@ rust-version.workspace =3D true common =3D { path =3D "../common" } migration =3D { path =3D "../migration" } util =3D { path =3D "../util" } +bql =3D { path =3D "../bql" } qemu_api_macros =3D { path =3D "../qemu-api-macros" } anyhow =3D "~1.0" libc =3D "0.2.162" diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index ee6311cd3f..dd829e3348 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -2,10 +2,6 @@ _qemu_api_cfg =3D run_command(rustc_args, '--config-headers', config_host_h, '--features', files('Cargo.toml'), capture: true, check: true).stdout().strip().splitlines() =20 -if get_option('debug_mutex') - _qemu_api_cfg +=3D ['--cfg', 'feature=3D"debug_cell"'] -endif - c_enums =3D [ 'DeviceCategory', 'GpioPolarity', @@ -51,7 +47,6 @@ _qemu_api_rs =3D static_library( [ 'src/lib.rs', 'src/bindings.rs', - 'src/cell.rs', 'src/chardev.rs', 'src/irq.rs', 'src/memory.rs', @@ -65,7 +60,7 @@ _qemu_api_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _qemu_api_cfg, - dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, qemu_api_macro= s, qemuutil_rs, util_rs, migration_rs, + dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, qemu_api_macro= s, qemuutil_rs, util_rs, migration_rs, bql_rs, qom, hwcore, chardev, migration], ) =20 @@ -91,7 +86,7 @@ test('rust-qemu-api-integration', override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_args: ['--test'], install: false, - dependencies: [common_rs, util_rs, migration_rs, qemu_api]), + dependencies: [bql_rs, common_rs, util_rs, migration_rs, qemu_api]= ), args: [ '--test', '--test-threads', '1', '--format', 'pretty', diff --git a/rust/qemu-api/src/chardev.rs b/rust/qemu-api/src/chardev.rs index c2bea23e82..d07e263193 100644 --- a/rust/qemu-api/src/chardev.rs +++ b/rust/qemu-api/src/chardev.rs @@ -18,13 +18,10 @@ slice, }; =20 +use bql::{BqlRefCell, BqlRefMut}; use common::{callbacks::FnCall, Opaque}; =20 -use crate::{ - bindings, - cell::{BqlRefCell, BqlRefMut}, - prelude::*, -}; +use crate::{bindings, prelude::*}; =20 /// A safe wrapper around [`bindings::Chardev`]. #[repr(transparent)] @@ -44,13 +41,15 @@ pub struct CharBackend { _pin: PhantomPinned, } =20 -impl Write for BqlRefMut<'_, bindings::CharBackend> { +pub struct CharBackendMut<'a>(BqlRefMut<'a, bindings::CharBackend>); + +impl Write for CharBackendMut<'_> { fn flush(&mut self) -> io::Result<()> { Ok(()) } =20 fn write(&mut self, buf: &[u8]) -> io::Result { - let chr: &mut bindings::CharBackend =3D self; + let chr: &mut bindings::CharBackend =3D &mut self.0; =20 let len =3D buf.len().try_into().unwrap(); let r =3D unsafe { bindings::qemu_chr_fe_write(addr_of_mut!(*chr),= buf.as_ptr(), len) }; @@ -58,7 +57,7 @@ fn write(&mut self, buf: &[u8]) -> io::Result { } =20 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - let chr: &mut bindings::CharBackend =3D self; + let chr: &mut bindings::CharBackend =3D &mut self.0; =20 let len =3D buf.len().try_into().unwrap(); let r =3D unsafe { bindings::qemu_chr_fe_write_all(addr_of_mut!(*c= hr), buf.as_ptr(), len) }; @@ -198,7 +197,7 @@ pub fn accept_input(&self) { /// the big QEMU lock while the character device is borrowed, as /// that might cause C code to write to the character device. pub fn borrow_mut(&self) -> impl Write + '_ { - self.inner.borrow_mut() + CharBackendMut(self.inner.borrow_mut()) } =20 /// Send a continuous stream of zero bits on the line if `enabled` is diff --git a/rust/qemu-api/src/irq.rs b/rust/qemu-api/src/irq.rs index ea6b32848c..3063fbe97a 100644 --- a/rust/qemu-api/src/irq.rs +++ b/rust/qemu-api/src/irq.rs @@ -10,6 +10,7 @@ ptr, }; =20 +use bql::BqlCell; use common::Opaque; =20 use crate::{ diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 52e4d5889b..37e6c21946 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -13,7 +13,6 @@ #[rustfmt::skip] pub mod prelude; =20 -pub mod cell; pub mod chardev; pub mod irq; pub mod memory; diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs index c10c171158..9da7313016 100644 --- a/rust/qemu-api/src/prelude.rs +++ b/rust/qemu-api/src/prelude.rs @@ -4,9 +4,6 @@ =20 //! Commonly used traits and types for QEMU. =20 -pub use crate::cell::BqlCell; -pub use crate::cell::BqlRefCell; - pub use crate::qdev::DeviceMethods; =20 pub use crate::qom::InterfaceType; diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs index 15e1fdff96..6875c32be7 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/qemu-api/src/qdev.rs @@ -16,7 +16,6 @@ =20 use crate::{ bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, ResettableClas= s}, - cell::bql_locked, chardev::Chardev, irq::InterruptSource, prelude::*, @@ -275,7 +274,7 @@ fn do_init_clock_in( cb: Option, events: ClockEvent, ) -> Owned { - assert!(bql_locked()); + assert!(bql::is_locked()); =20 // SAFETY: the clock is heap allocated, but qdev_init_clock_in= () // does not gift the reference to its caller; so use Owned::fr= om to @@ -346,7 +345,7 @@ pub trait DeviceMethods: ObjectDeref Self::Target: IsA, { fn prop_set_chr(&self, propname: &str, chr: &Owned) { - assert!(bql_locked()); + assert!(bql::is_locked()); let c_propname =3D CString::new(propname).unwrap(); let chr: &Chardev =3D chr; unsafe { diff --git a/rust/qemu-api/src/qom.rs b/rust/qemu-api/src/qom.rs index 901445013c..e797958e4e 100644 --- a/rust/qemu-api/src/qom.rs +++ b/rust/qemu-api/src/qom.rs @@ -105,12 +105,9 @@ use common::Opaque; use migration::impl_vmstate_pointer; =20 -use crate::{ - bindings::{ - self, object_class_dynamic_cast, object_dynamic_cast, object_get_c= lass, - object_get_typename, object_new, object_ref, object_unref, TypeInf= o, - }, - cell::bql_locked, +use crate::bindings::{ + self, object_class_dynamic_cast, object_dynamic_cast, object_get_class= , object_get_typename, + object_new, object_ref, object_unref, TypeInfo, }; =20 /// A safe wrapper around [`bindings::Object`]. @@ -873,7 +870,7 @@ impl ObjectDeref for Owned {} =20 impl Drop for Owned { fn drop(&mut self) { - assert!(bql_locked()); + assert!(bql::is_locked()); // SAFETY: creation method is unsafe, and whoever calls it has // responsibility that the pointer is valid, and remains valid // throughout the lifetime of the `Owned` and its clones. @@ -897,7 +894,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { pub trait ObjectClassMethods: IsA { /// Return a new reference counted instance of this class fn new() -> Owned { - assert!(bql_locked()); + assert!(bql::is_locked()); // SAFETY: the object created by object_new is allocated on // the heap and has a reference count of 1 unsafe { diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs index 2dbfc31dbd..b21883246e 100644 --- a/rust/qemu-api/src/sysbus.rs +++ b/rust/qemu-api/src/sysbus.rs @@ -11,7 +11,6 @@ =20 use crate::{ bindings, - cell::bql_locked, irq::{IRQState, InterruptSource}, memory::MemoryRegion, prelude::*, @@ -56,7 +55,7 @@ pub trait SysBusDeviceMethods: ObjectDeref /// region with a number that corresponds to the order of calls to /// `init_mmio`. fn init_mmio(&self, iomem: &MemoryRegion) { - assert!(bql_locked()); + assert!(bql::is_locked()); unsafe { bindings::sysbus_init_mmio(self.upcast().as_mut_ptr(), iomem.a= s_mut_ptr()); } @@ -67,7 +66,7 @@ fn init_mmio(&self, iomem: &MemoryRegion) { /// whoever creates the sysbus device will refer to the interrupts with /// a number that corresponds to the order of calls to `init_irq`. fn init_irq(&self, irq: &InterruptSource) { - assert!(bql_locked()); + assert!(bql::is_locked()); unsafe { bindings::sysbus_init_irq(self.upcast().as_mut_ptr(), irq.as_p= tr()); } @@ -75,7 +74,7 @@ fn init_irq(&self, irq: &InterruptSource) { =20 // TODO: do we want a type like GuestAddress here? fn mmio_addr(&self, id: u32) -> Option { - assert!(bql_locked()); + assert!(bql::is_locked()); // SAFETY: the BQL ensures that no one else writes to sbd.mmio[], = and // the SysBusDevice must be initialized to get an IsA. let sbd =3D unsafe { *self.upcast().as_ptr() }; @@ -89,7 +88,7 @@ fn mmio_addr(&self, id: u32) -> Option { =20 // TODO: do we want a type like GuestAddress here? fn mmio_map(&self, id: u32, addr: u64) { - assert!(bql_locked()); + assert!(bql::is_locked()); let id: i32 =3D id.try_into().unwrap(); unsafe { bindings::sysbus_mmio_map(self.upcast().as_mut_ptr(), id, addr= ); @@ -100,7 +99,7 @@ fn mmio_map(&self, id: u32, addr: u64) { // object_property_set_link) adds a reference to the IRQState, // which can prolong its life fn connect_irq(&self, id: u32, irq: &Owned) { - assert!(bql_locked()); + assert!(bql::is_locked()); let id: i32 =3D id.try_into().unwrap(); let irq: &IRQState =3D irq; unsafe { @@ -110,7 +109,7 @@ fn connect_irq(&self, id: u32, irq: &Owned) { =20 fn sysbus_realize(&self) { // TODO: return an Error - assert!(bql_locked()); + assert!(bql::is_locked()); unsafe { bindings::sysbus_realize( self.upcast().as_mut_ptr(), diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index 2ea4f88dd1..bc4bd320ce 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -4,11 +4,11 @@ =20 use std::{ffi::CStr, ptr::addr_of}; =20 +use bql::BqlCell; use common::Zeroable; use migration::VMStateDescription; use qemu_api::{ bindings::qdev_prop_bool, - cell::{self, BqlCell}, declare_properties, define_property, prelude::*, qdev::{DeviceImpl, DeviceState, Property, ResettablePhasesImpl}, @@ -113,7 +113,7 @@ pub fn class_init(self: &mut DummyChildC= lass) { fn init_qom() { static ONCE: BqlCell =3D BqlCell::new(false); =20 - cell::bql_start_test(); + bql::start_test(); if !ONCE.get() { unsafe { module_call_init(module_init_type::MODULE_INIT_QOM); diff --git a/rust/qemu-api/tests/vmstate_tests.rs b/rust/qemu-api/tests/vms= tate_tests.rs index 3f64eb46c0..f808aed2c9 100644 --- a/rust/qemu-api/tests/vmstate_tests.rs +++ b/rust/qemu-api/tests/vmstate_tests.rs @@ -9,6 +9,7 @@ slice, }; =20 +use bql::BqlCell; use common::{Opaque, Zeroable}; use migration::{ bindings::{ @@ -19,7 +20,6 @@ vmstate::{VMStateDescription, VMStateField, VMStateFieldHelper}, vmstate_fields, vmstate_of, vmstate_struct, vmstate_unused, vmstate_va= lidate, }; -use qemu_api::cell::BqlCell; =20 const FOO_ARRAY_MAX: usize =3D 3; =20 --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217315; cv=none; d=zohomail.com; s=zohoarc; b=k8GGmzysKZf8cA2fxHnafAUy/8LD2+u5jg+92d8QL2dfJM63lJ7AyQEWZ01RUMUja6KWPmpMat6sXOxNOQ+uLA3ZSnI+5ewptq7/i6my4XURFROVIj0rYGJrPXYEkK4CCJX97q2rAxngX/QHowBEayxaquuwQwHJm9n8r2cDd0s= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217315; h=Content-Type: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=CilHACdL4z9JOWOy0kMpOGpK5N/BedxoPNtfBQCFjbY=; b=Hpz+1jf3z2QrlFhSn8f2Ar1qgKafOY+TXnzo8w7UFYzk6Cs4zgYuoH/LkuFK3GeBsmFjtixBh/vX+i6swxM91TOeZnP/J0S897mpvnB21q9IJMWO7CybbLoD2v87skmyEzQMUEEacQZMOSvtAClznB3YOhi+JB7kIzfxOF/3dxk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217315502475.63583005395276; Tue, 26 Aug 2025 07:08:35 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJe-0006KG-NO; Tue, 26 Aug 2025 10:06:26 -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 1uquJc-0006JZ-3f for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:24 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquJQ-000773-5R for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:23 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-543-bRTbLMeiNDKFZfKAz8dmWw-1; Tue, 26 Aug 2025 10:06:04 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E4CE5180024D; Tue, 26 Aug 2025 14:05:51 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5EE7F1800446; Tue, 26 Aug 2025 14:05:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217166; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CilHACdL4z9JOWOy0kMpOGpK5N/BedxoPNtfBQCFjbY=; b=M8ypXzWBi1LueBzzVOZLsQ8yNv/u7UkbZESTlQgZe3neLP/JYCzEKg5TJSfMEwGb5L+u7Y 9M++7Xeml5naqgQKD+CkyIrbB2C7VoGMR35oTg/b/umqmShwk3o63Nme+ztnlxwhcX1Yah 4zmYZD7TxUaibOypELP3BeKHg0/ELv0= X-MC-Unique: bRTbLMeiNDKFZfKAz8dmWw-1 X-Mimecast-MFC-AGG-ID: bRTbLMeiNDKFZfKAz8dmWw_1756217152 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 10/18] rust: split "qom" crate Date: Tue, 26 Aug 2025 18:04:38 +0400 Message-ID: <20250826140449.4190022-11-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 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=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1756217317748124100 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Zhao Liu --- MAINTAINERS | 1 + rust/qom/wrapper.h | 27 ++++++++++++++ rust/Cargo.lock | 14 +++++++ rust/Cargo.toml | 1 + rust/hw/char/pl011/Cargo.toml | 1 + rust/hw/char/pl011/meson.build | 1 + rust/hw/char/pl011/src/device.rs | 5 ++- rust/hw/timer/hpet/Cargo.toml | 1 + rust/hw/timer/hpet/meson.build | 1 + rust/hw/timer/hpet/src/device.rs | 3 +- rust/meson.build | 1 + rust/migration/src/vmstate.rs | 2 +- rust/qemu-api-macros/src/lib.rs | 4 +- rust/qemu-api-macros/src/tests.rs | 4 +- rust/qemu-api/Cargo.toml | 1 + rust/qemu-api/meson.build | 15 +++++--- rust/qemu-api/src/bindings.rs | 1 + rust/qemu-api/src/chardev.rs | 5 ++- rust/qemu-api/src/irq.rs | 12 +++--- rust/qemu-api/src/lib.rs | 1 - rust/qemu-api/src/memory.rs | 9 ++--- rust/qemu-api/src/prelude.rs | 11 ------ rust/qemu-api/src/qdev.rs | 22 +++++++---- rust/qemu-api/src/sysbus.rs | 8 ++-- rust/qemu-api/tests/tests.rs | 12 +++--- rust/qom/Cargo.toml | 23 ++++++++++++ rust/qom/build.rs | 43 ++++++++++++++++++++++ rust/qom/meson.build | 61 +++++++++++++++++++++++++++++++ rust/qom/src/bindings.rs | 25 +++++++++++++ rust/qom/src/lib.rs | 4 ++ rust/{qemu-api =3D> qom}/src/qom.rs | 4 +- rust/qom/tests/tests.rs | 47 ++++++++++++++++++++++++ 32 files changed, 313 insertions(+), 57 deletions(-) create mode 100644 rust/qom/wrapper.h create mode 100644 rust/qom/Cargo.toml create mode 100644 rust/qom/build.rs create mode 100644 rust/qom/meson.build create mode 100644 rust/qom/src/bindings.rs create mode 100644 rust/qom/src/lib.rs rename rust/{qemu-api =3D> qom}/src/qom.rs (99%) create mode 100644 rust/qom/tests/tests.rs diff --git a/MAINTAINERS b/MAINTAINERS index 0b5f327d4f..8054913502 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3515,6 +3515,7 @@ F: rust/common/ F: rust/migration/ F: rust/qemu-api F: rust/qemu-api-macros +F: rust/qom/ F: rust/rustfmt.toml F: rust/util/ F: scripts/get-wraps-from-cargo-registry.py diff --git a/rust/qom/wrapper.h b/rust/qom/wrapper.h new file mode 100644 index 0000000000..3b71bcd3f5 --- /dev/null +++ b/rust/qom/wrapper.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * This header file is meant to be used as input to the `bindgen` applicat= ion + * 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 sym= bols + * 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 "qom/object.h" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 76ff79f81a..0f1dcea6e4 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -79,6 +79,7 @@ dependencies =3D [ "migration", "qemu_api", "qemu_api_macros", + "qom", "util", ] =20 @@ -118,6 +119,7 @@ dependencies =3D [ "migration", "qemu_api", "qemu_api_macros", + "qom", "util", ] =20 @@ -164,6 +166,7 @@ dependencies =3D [ "libc", "migration", "qemu_api_macros", + "qom", "util", ] =20 @@ -176,6 +179,17 @@ dependencies =3D [ "syn", ] =20 +[[package]] +name =3D "qom" +version =3D "0.1.0" +dependencies =3D [ + "bql", + "common", + "migration", + "qemu_api_macros", + "util", +] + [[package]] name =3D "quote" version =3D "1.0.36" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 3ce1977ee0..fd7cf9b0e1 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -7,6 +7,7 @@ members =3D [ "migration", "qemu-api-macros", "qemu-api", + "qom", "hw/char/pl011", "hw/timer/hpet", "util", diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml index 1a1d4ba715..da89f78727 100644 --- a/rust/hw/char/pl011/Cargo.toml +++ b/rust/hw/char/pl011/Cargo.toml @@ -20,6 +20,7 @@ common =3D { path =3D "../../../common" } util =3D { path =3D "../../../util" } bql =3D { path =3D "../../../bql" } migration =3D { path =3D "../../../migration" } +qom =3D { path =3D "../../../qom" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build index 7062497b7c..cd855408a5 100644 --- a/rust/hw/char/pl011/meson.build +++ b/rust/hw/char/pl011/meson.build @@ -13,6 +13,7 @@ _libpl011_rs =3D static_library( bql_rs, qemu_api, qemu_api_macros, + qom_rs, ], ) =20 diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 7cffb894a8..a3bcd1297a 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -21,10 +21,13 @@ memory::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder= }, prelude::*, qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType= , ResettablePhasesImpl}, - qom::{ObjectImpl, Owned, ParentField, ParentInit}, sysbus::{SysBusDevice, SysBusDeviceImpl}, vmstate_clock, }; +use qom::{ + qom_isa, IsA, Object, ObjectClassMethods, ObjectDeref, ObjectImpl, Obj= ectMethods, ObjectType, + Owned, ParentField, ParentInit, +}; use util::{log::Log, log_mask_ln}; =20 use crate::registers::{self, Interrupt, RegisterOffset}; diff --git a/rust/hw/timer/hpet/Cargo.toml b/rust/hw/timer/hpet/Cargo.toml index 9fcec38bfa..19456ec72b 100644 --- a/rust/hw/timer/hpet/Cargo.toml +++ b/rust/hw/timer/hpet/Cargo.toml @@ -15,6 +15,7 @@ common =3D { path =3D "../../../common" } util =3D { path =3D "../../../util" } migration =3D { path =3D "../../../migration" } bql =3D { path =3D "../../../bql" } +qom =3D { path =3D "../../../qom" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/timer/hpet/meson.build b/rust/hw/timer/hpet/meson.build index 5e01e57210..195dc48e1c 100644 --- a/rust/hw/timer/hpet/meson.build +++ b/rust/hw/timer/hpet/meson.build @@ -10,6 +10,7 @@ _libhpet_rs =3D static_library( bql_rs, qemu_api, qemu_api_macros, + qom_rs, ], ) =20 diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index c0e52ce415..b876b35a43 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -27,10 +27,9 @@ }, prelude::*, qdev::{DeviceImpl, DeviceState, Property, ResetType, ResettablePhasesI= mpl}, - qom::{ObjectImpl, ObjectType, ParentField, ParentInit}, - qom_isa, sysbus::{SysBusDevice, SysBusDeviceImpl}, }; +use qom::{qom_isa, Object, ObjectImpl, ObjectType, ParentField, ParentInit= }; use util::timer::{Timer, CLOCK_VIRTUAL, NANOSECONDS_PER_SECOND}; =20 use crate::fw_cfg::HPETFwConfig; diff --git a/rust/meson.build b/rust/meson.build index 2ba1ea2280..043603d416 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -28,6 +28,7 @@ subdir('bits') subdir('util') subdir('migration') subdir('bql') +subdir('qom') subdir('qemu-api') =20 subdir('hw') diff --git a/rust/migration/src/vmstate.rs b/rust/migration/src/vmstate.rs index 243f31baf6..58a4396c30 100644 --- a/rust/migration/src/vmstate.rs +++ b/rust/migration/src/vmstate.rs @@ -200,7 +200,7 @@ pub const fn vmstate_varray_flag(_: Phantom= Data) -> VMStateFlags /// /// [`BqlCell`]: ../../bql/cell/struct.BqlCell.html /// [`BqlRefCell`]: ../../bql/cell/struct.BqlRefCell.html -/// [`Owned`]: ../../qemu_api/qom/struct.Owned.html +/// [`Owned`]: ../../qom/qom/struct.Owned.html #[macro_export] macro_rules! vmstate_of { ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:exp= r)?])? $(, $test_fn:expr)? $(,)?) =3D> { diff --git a/rust/qemu-api-macros/src/lib.rs b/rust/qemu-api-macros/src/lib= .rs index b5f77f06f5..5d52f22441 100644 --- a/rust/qemu-api-macros/src/lib.rs +++ b/rust/qemu-api-macros/src/lib.rs @@ -89,11 +89,11 @@ fn derive_object_or_error(input: DeriveInput) -> Result= ::ParentType>); + ::qom::ParentField<<#name as ::qom::ObjectImpl>::ParentType>); =20 ::util::module_init! { MODULE_INIT_QOM =3D> unsafe { - ::qemu_api::bindings::type_register_static(&<#name as ::qe= mu_api::qom::ObjectImpl>::TYPE_INFO); + ::qom::type_register_static(&<#name as ::qom::ObjectImpl>:= :TYPE_INFO); } } }) diff --git a/rust/qemu-api-macros/src/tests.rs b/rust/qemu-api-macros/src/t= ests.rs index 52683e46d5..b6da07f24c 100644 --- a/rust/qemu-api-macros/src/tests.rs +++ b/rust/qemu-api-macros/src/tests.rs @@ -61,11 +61,11 @@ struct Foo { ::common::assert_field_type!( Foo, _unused, - ::qemu_api::qom::ParentField<::ParentType> + ::qom::ParentField<::ParentType> ); ::util::module_init! { MODULE_INIT_QOM =3D> unsafe { - ::qemu_api::bindings::type_register_static(&::TYPE_INFO); + ::qom::type_register_static(&::TYPE_INFO); } } } diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index 511eb6cb89..333cef1c5d 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -19,6 +19,7 @@ migration =3D { path =3D "../migration" } util =3D { path =3D "../util" } bql =3D { path =3D "../bql" } qemu_api_macros =3D { path =3D "../qemu-api-macros" } +qom =3D { path =3D "../qom" } anyhow =3D "~1.0" libc =3D "0.2.162" foreign =3D "~0.3.1" diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index dd829e3348..c5038aa5bd 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -22,9 +22,15 @@ foreach enum : c_bitfields _qemu_api_bindgen_args +=3D ['--bitfield-enum', enum] endforeach =20 -_qemu_api_bindgen_args +=3D ['--blocklist-type', 'VMStateDescription'] +blocked_type =3D [ + 'ObjectClass', + 'VMStateDescription', + 'Error', +] +foreach type: blocked_type + _qemu_api_bindgen_args +=3D ['--blocklist-type', type] +endforeach =20 -_qemu_api_bindgen_args +=3D ['--blocklist-type', 'Error'] # TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. # # Rust bindings generation with `bindgen` might fail in some cases where t= he @@ -52,7 +58,6 @@ _qemu_api_rs =3D static_library( 'src/memory.rs', 'src/prelude.rs', 'src/qdev.rs', - 'src/qom.rs', 'src/sysbus.rs', ], {'.' : _qemu_api_bindings_inc_rs}, @@ -60,7 +65,7 @@ _qemu_api_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _qemu_api_cfg, - dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, qemu_api_macro= s, qemuutil_rs, util_rs, migration_rs, bql_rs, + dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, qemu_api_macro= s, qemuutil_rs, util_rs, migration_rs, bql_rs, qom_rs, qom, hwcore, chardev, migration], ) =20 @@ -86,7 +91,7 @@ test('rust-qemu-api-integration', override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_args: ['--test'], install: false, - dependencies: [bql_rs, common_rs, util_rs, migration_rs, qemu_api]= ), + dependencies: [bql_rs, common_rs, util_rs, migration_rs, qom_rs, q= emu_api]), args: [ '--test', '--test-threads', '1', '--format', 'pretty', diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs index ce00a6e0e4..525f136ae2 100644 --- a/rust/qemu-api/src/bindings.rs +++ b/rust/qemu-api/src/bindings.rs @@ -22,6 +22,7 @@ =20 use common::Zeroable; use migration::bindings::VMStateDescription; +use qom::bindings::ObjectClass; use util::bindings::Error; =20 #[cfg(MESON)] diff --git a/rust/qemu-api/src/chardev.rs b/rust/qemu-api/src/chardev.rs index d07e263193..1a6795a938 100644 --- a/rust/qemu-api/src/chardev.rs +++ b/rust/qemu-api/src/chardev.rs @@ -20,8 +20,9 @@ =20 use bql::{BqlRefCell, BqlRefMut}; use common::{callbacks::FnCall, Opaque}; +use qom::{Object, ObjectType}; =20 -use crate::{bindings, prelude::*}; +use crate::bindings; =20 /// A safe wrapper around [`bindings::Chardev`]. #[repr(transparent)] @@ -257,4 +258,4 @@ unsafe impl ObjectType for Chardev { const TYPE_NAME: &'static CStr =3D unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_CHARDE= V) }; } -qom_isa!(Chardev: Object); +qom::qom_isa!(Chardev: Object); diff --git a/rust/qemu-api/src/irq.rs b/rust/qemu-api/src/irq.rs index 3063fbe97a..5a380923fe 100644 --- a/rust/qemu-api/src/irq.rs +++ b/rust/qemu-api/src/irq.rs @@ -12,12 +12,9 @@ =20 use bql::BqlCell; use common::Opaque; +use qom::{Object, ObjectClass, ObjectType}; =20 -use crate::{ - bindings::{self, qemu_set_irq}, - prelude::*, - qom::ObjectClass, -}; +use crate::bindings::{self, qemu_set_irq}; =20 /// An opaque wrapper around [`bindings::IRQState`]. #[repr(transparent)] @@ -36,7 +33,7 @@ /// /// Interrupts are implemented as a pointer to the interrupt "sink", which= has /// type [`IRQState`]. A device exposes its source as a QOM link property= using -/// a function such as [`SysBusDeviceMethods::init_irq`], and +/// a function such as [`crate::sysbus::SysBusDeviceMethods::init_irq`], a= nd /// initially leaves the pointer to a NULL value, representing an unconnec= ted /// interrupt. To connect it, whoever creates the device fills the pointer= with /// the sink's `IRQState *`, for example using `sysbus_connect_irq`. Beca= use @@ -114,4 +111,5 @@ unsafe impl ObjectType for IRQState { const TYPE_NAME: &'static CStr =3D unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_IRQ) }; } -qom_isa!(IRQState: Object); + +qom::qom_isa!(IRQState: Object); diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 37e6c21946..f9551c13a5 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -17,5 +17,4 @@ pub mod irq; pub mod memory; pub mod qdev; -pub mod qom; pub mod sysbus; diff --git a/rust/qemu-api/src/memory.rs b/rust/qemu-api/src/memory.rs index f790cb5fd2..480cc6b0c5 100644 --- a/rust/qemu-api/src/memory.rs +++ b/rust/qemu-api/src/memory.rs @@ -11,11 +11,9 @@ =20 pub use bindings::{hwaddr, MemTxAttrs}; use common::{callbacks::FnCall, uninit::MaybeUninitField, zeroable::Zeroab= le, Opaque}; +use qom::{IsA, Object, ObjectType}; =20 -use crate::{ - bindings::{self, device_endian, memory_region_init_io}, - prelude::*, -}; +use crate::bindings::{self, device_endian, memory_region_init_io}; =20 pub struct MemoryRegionOps( bindings::MemoryRegionOps, @@ -186,7 +184,8 @@ unsafe impl ObjectType for MemoryRegion { const TYPE_NAME: &'static CStr =3D unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_MEMORY= _REGION) }; } -qom_isa!(MemoryRegion: Object); + +qom::qom_isa!(MemoryRegion: Object); =20 /// A special `MemTxAttrs` constant, used to indicate that no memory /// attributes are specified. diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs index 9da7313016..9e9d1c8247 100644 --- a/rust/qemu-api/src/prelude.rs +++ b/rust/qemu-api/src/prelude.rs @@ -6,15 +6,4 @@ =20 pub use crate::qdev::DeviceMethods; =20 -pub use crate::qom::InterfaceType; -pub use crate::qom::IsA; -pub use crate::qom::Object; -pub use crate::qom::ObjectCast; -pub use crate::qom::ObjectClassMethods; -pub use crate::qom::ObjectDeref; -pub use crate::qom::ObjectMethods; -pub use crate::qom::ObjectType; - -pub use crate::qom_isa; - pub use crate::sysbus::SysBusDeviceMethods; diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs index 6875c32be7..a94af90bb1 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/qemu-api/src/qdev.rs @@ -12,14 +12,16 @@ pub use bindings::{ClockEvent, DeviceClass, Property, ResetType}; use common::{callbacks::FnCall, Opaque}; use migration::vmstate::VMStateDescription; +use qom::{ + InterfaceType, IsA, Object, ObjectCast, ObjectClass, ObjectDeref, Obje= ctImpl, ObjectType, + Owned, ParentInit, +}; pub use util::{Error, Result}; =20 use crate::{ bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, ResettableClas= s}, chardev::Chardev, irq::InterruptSource, - prelude::*, - qom::{ObjectClass, ObjectImpl, Owned, ParentInit}, }; =20 /// A safe wrapper around [`bindings::Clock`]. @@ -164,10 +166,14 @@ pub fn class_init(&mut self)= { } } =20 -impl DeviceClass { +pub trait DeviceClassExt { + fn class_init(&mut self); +} + +impl DeviceClassExt for DeviceClass { /// Fill in the virtual methods of `DeviceClass` based on the definiti= ons in /// the `DeviceImpl` trait. - pub fn class_init(&mut self) { + fn class_init(&mut self) { if ::REALIZE.is_some() { self.realize =3D Some(rust_realize_fn::); } @@ -244,7 +250,8 @@ unsafe impl ObjectType for DeviceState { const TYPE_NAME: &'static CStr =3D unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_DEVICE= ) }; } -qom_isa!(DeviceState: Object); + +qom::qom_isa!(DeviceState: Object); =20 /// Initialization methods take a [`ParentInit`] and can be called as /// associated functions. @@ -406,7 +413,8 @@ unsafe impl ObjectType for Clock { const TYPE_NAME: &'static CStr =3D unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_CLOCK)= }; } -qom_isa!(Clock: Object); + +qom::qom_isa!(Clock: Object); =20 #[doc(alias =3D "VMSTATE_CLOCK")] #[macro_export] @@ -420,7 +428,7 @@ macro_rules! vmstate_clock { ::common::assert_field_type!( $struct_name, $field_name, - $crate::qom::Owned<$crate::qdev::Clock> $(, num =3D $n= um)? + ::qom::Owned<$crate::qdev::Clock> $(, num =3D $num)? ); ::std::mem::offset_of!($struct_name, $field_name) }, diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs index b21883246e..016e57935a 100644 --- a/rust/qemu-api/src/sysbus.rs +++ b/rust/qemu-api/src/sysbus.rs @@ -8,14 +8,13 @@ =20 pub use bindings::SysBusDeviceClass; use common::Opaque; +use qom::{IsA, Object, ObjectCast, ObjectDeref, ObjectType, Owned}; =20 use crate::{ bindings, irq::{IRQState, InterruptSource}, memory::MemoryRegion, - prelude::*, - qdev::{DeviceImpl, DeviceState}, - qom::Owned, + qdev::{DeviceClassExt, DeviceImpl, DeviceState}, }; =20 /// A safe wrapper around [`bindings::SysBusDevice`]. @@ -31,7 +30,8 @@ unsafe impl ObjectType for SysBusDevice { const TYPE_NAME: &'static CStr =3D unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_SYS_BU= S_DEVICE) }; } -qom_isa!(SysBusDevice: DeviceState, Object); + +qom::qom_isa!(SysBusDevice: DeviceState, Object); =20 // TODO: add virtual methods pub trait SysBusDeviceImpl: DeviceImpl + IsA {} diff --git a/rust/qemu-api/tests/tests.rs b/rust/qemu-api/tests/tests.rs index bc4bd320ce..821aabe831 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/qemu-api/tests/tests.rs @@ -10,11 +10,13 @@ use qemu_api::{ bindings::qdev_prop_bool, declare_properties, define_property, - prelude::*, - qdev::{DeviceImpl, DeviceState, Property, ResettablePhasesImpl}, - qom::{ObjectImpl, ParentField}, + qdev::{DeviceClassExt, DeviceImpl, DeviceState, Property, ResettablePh= asesImpl}, sysbus::SysBusDevice, }; +use qom::{ + Object, ObjectCast, ObjectClassMethods, ObjectDeref, ObjectImpl, Objec= tMethods, ObjectType, + ParentField, +}; use util::bindings::{module_call_init, module_init_type}; =20 mod vmstate_tests; @@ -33,7 +35,7 @@ pub struct DummyState { migrate_clock: bool, } =20 -qom_isa!(DummyState: Object, DeviceState); +qom::qom_isa!(DummyState: Object, DeviceState); =20 pub struct DummyClass { parent_class: ::Class, @@ -84,7 +86,7 @@ pub struct DummyChildState { parent: ParentField, } =20 -qom_isa!(DummyChildState: Object, DeviceState, DummyState); +qom::qom_isa!(DummyChildState: Object, DeviceState, DummyState); =20 pub struct DummyChildClass { parent_class: ::Class, diff --git a/rust/qom/Cargo.toml b/rust/qom/Cargo.toml new file mode 100644 index 0000000000..46bbf7c7fe --- /dev/null +++ b/rust/qom/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name =3D "qom" +version =3D "0.1.0" +description =3D "Rust bindings for QEMU/QOM" +resolver =3D "2" +publish =3D false + +authors.workspace =3D true +edition.workspace =3D true +homepage.workspace =3D true +license.workspace =3D true +repository.workspace =3D true +rust-version.workspace =3D true + +[dependencies] +common =3D { path =3D "../common" } +bql =3D { path =3D "../bql" } +migration =3D { path =3D "../migration" } +qemu_api_macros =3D { path =3D "../qemu-api-macros" } +util =3D { path =3D "../util" } + +[lints] +workspace =3D true diff --git a/rust/qom/build.rs b/rust/qom/build.rs new file mode 100644 index 0000000000..aca1c54cb8 --- /dev/null +++ b/rust/qom/build.rs @@ -0,0 +1,43 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis +// SPDX-License-Identifier: GPL-2.0-or-later + +#[cfg(unix)] +use std::os::unix::fs::symlink as symlink_file; +#[cfg(windows)] +use std::os::windows::fs::symlink_file; +use std::{env, fs::remove_file, io::Result, path::Path}; + +fn main() -> Result<()> { + let file =3D if let Ok(root) =3D env::var("MESON_BUILD_ROOT") { + format!("{root}/rust/qom/bindings.inc.rs") + } else { + // Placing bindings.inc.rs in the source directory is supported + // but not documented or encouraged. + format!("{}/src/bindings.inc.rs", env!("CARGO_MANIFEST_DIR")) + }; + + let file =3D Path::new(&file); + if !Path::new(&file).exists() { + panic!(concat!( + "\n", + " No generated C bindings found! Maybe you wanted one of\n", + " `make clippy`, `make rustfmt`, `make rustdoc`?\n", + "\n", + " For other uses of `cargo`, start a subshell with\n", + " `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n= ", + " the top of the build tree." + )); + } + + let out_dir =3D env::var("OUT_DIR").unwrap(); + let dest_path =3D format!("{out_dir}/bindings.inc.rs"); + let dest_path =3D Path::new(&dest_path); + if dest_path.symlink_metadata().is_ok() { + remove_file(dest_path)?; + } + symlink_file(file, dest_path)?; + + println!("cargo:rerun-if-changed=3Dbuild.rs"); + Ok(()) +} diff --git a/rust/qom/meson.build b/rust/qom/meson.build new file mode 100644 index 0000000000..6e95d75fa0 --- /dev/null +++ b/rust/qom/meson.build @@ -0,0 +1,61 @@ +_qom_cfg =3D run_command(rustc_args, + '--config-headers', config_host_h, '--features', files('Cargo.toml'), + capture: true, check: true).stdout().strip().splitlines() + +# TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. +# +# Rust bindings generation with `bindgen` might fail in some cases where t= he +# 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 +_qom_bindings_inc_rs =3D rust.bindgen( + input: 'wrapper.h', + dependencies: common_ss.all_dependencies(), + output: 'bindings.inc.rs', + include_directories: bindings_incdir, + bindgen_version: ['>=3D0.60.0'], + args: bindgen_args_common, +) + +_qom_rs =3D static_library( + 'qom', + structured_sources( + [ + 'src/lib.rs', + 'src/bindings.rs', + 'src/qom.rs', + ], + {'.': _qom_bindings_inc_rs} + ), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_abi: 'rust', + rust_args: _qom_cfg, + dependencies: [qemuutil_rs, bql_rs, common_rs, migration_rs, qemu_api_ma= cros, qom], +) + +qom_rs =3D declare_dependency(link_with: [_qom_rs], dependencies: [qemu_ap= i_macros, qom]) + +# Doctests are essentially integration tests, so they need the same depend= encies. +# Note that running them requires the object files for C code, so place th= em +# in a separate suite that is run by the "build" CI jobs rather than "chec= k". +rust.doctest('rust-qom-rs-doctests', + _qom_rs, + protocol: 'rust', + dependencies: qom_rs, + suite: ['doc', 'rust']) + +test('rust-qom-rs-integration', + executable( + 'rust-qom-rs-integration', + files('tests/tests.rs'), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_args: ['--test'], + install: false, + dependencies: [common_rs, qom_rs, bql_rs, util_rs]), + args: [ + '--test', '--test-threads', '1', + '--format', 'pretty', + ], + protocol: 'rust', + suite: ['unit', 'rust']) diff --git a/rust/qom/src/bindings.rs b/rust/qom/src/bindings.rs new file mode 100644 index 0000000000..9ffff12cde --- /dev/null +++ b/rust/qom/src/bindings.rs @@ -0,0 +1,25 @@ +// 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 +)] + +#[cfg(MESON)] +include!("bindings.inc.rs"); + +#[cfg(not(MESON))] +include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); diff --git a/rust/qom/src/lib.rs b/rust/qom/src/lib.rs new file mode 100644 index 0000000000..22520906cf --- /dev/null +++ b/rust/qom/src/lib.rs @@ -0,0 +1,4 @@ +pub mod bindings; + +mod qom; +pub use qom::*; diff --git a/rust/qemu-api/src/qom.rs b/rust/qom/src/qom.rs similarity index 99% rename from rust/qemu-api/src/qom.rs rename to rust/qom/src/qom.rs index e797958e4e..a632ec43f2 100644 --- a/rust/qemu-api/src/qom.rs +++ b/rust/qom/src/qom.rs @@ -101,7 +101,6 @@ ptr::NonNull, }; =20 -pub use bindings::ObjectClass; use common::Opaque; use migration::impl_vmstate_pointer; =20 @@ -109,6 +108,7 @@ self, object_class_dynamic_cast, object_dynamic_cast, object_get_class= , object_get_typename, object_new, object_ref, object_unref, TypeInfo, }; +pub use crate::bindings::{type_register_static, ObjectClass}; =20 /// A safe wrapper around [`bindings::Object`]. #[repr(transparent)] @@ -146,7 +146,7 @@ macro_rules! qom_isa { $( // SAFETY: it is the caller responsibility to have $parent as = the // first field - unsafe impl $crate::qom::IsA<$parent> for $struct {} + unsafe impl $crate::IsA<$parent> for $struct {} =20 impl AsRef<$parent> for $struct { fn as_ref(&self) -> &$parent { diff --git a/rust/qom/tests/tests.rs b/rust/qom/tests/tests.rs new file mode 100644 index 0000000000..49f1cbecf5 --- /dev/null +++ b/rust/qom/tests/tests.rs @@ -0,0 +1,47 @@ +use std::{ffi::CStr, sync::LazyLock}; + +use qom::{qom_isa, Object, ObjectClassMethods, ObjectImpl, ObjectType, Par= entField}; +use util::bindings::{module_call_init, module_init_type}; + +#[repr(C)] +#[derive(qemu_api_macros::Object)] +pub struct DummyObject { + parent: ParentField, +} + +qom_isa!(DummyObject: Object); + +pub struct DummyClass {} + +impl DummyClass { + pub fn class_init(self: &mut DummyClass) { + // + } +} + +unsafe impl ObjectType for DummyObject { + type Class =3D DummyClass; + const TYPE_NAME: &'static CStr =3D c"dummy"; +} + +impl ObjectImpl for DummyObject { + type ParentType =3D Object; + const ABSTRACT: bool =3D false; + const CLASS_INIT: fn(&mut DummyClass) =3D DummyClass::class_init; +} + +fn init_qom() { + static ONCE: LazyLock<()> =3D LazyLock::new(|| unsafe { + module_call_init(module_init_type::MODULE_INIT_QOM); + }); + + bql::start_test(); + LazyLock::force(&ONCE); +} + +#[test] +/// Create and immediately drop an instance. +fn test_object_new() { + init_qom(); + drop(DummyObject::new()); +} --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217283; cv=none; d=zohomail.com; s=zohoarc; b=XjWiBbXJReaVWhI34buPtGSl7LhWt7gd863JRpMOhbi/qEaxRU+5VUx9tPX8wTqzywyr4HSkjWt6JKF5lbSKxCr3KGNCMowOzu56F5HhYFboIRg/YO61jsjijGDhoLE3rpy9CZKC0eoH4bcc2tlRDQKOHQ9gkzxFZ+kxvuIKbLk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217283; h=Content-Type: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=Q99Erc5k50VvV9qqTAakHHbYqOuaMZCi7FIW9o0sOMk=; b=NTLy7wJTHvccWAgYkJtGfUDMsw8y73QuWnFaWeTt3i59bAyeEMQ5yGxJP4VNTBrgN8MWE146D4vZS9IP/99vKtnxOOlIw3T9+ILzJk/8Xy1lNFKw0+1iBc8ztAim8d2CgdO4VNVU9fU3mGT6ezRjQN1cMEBs9RlfdlGIKRmJoUI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217283203234.82020164915605; Tue, 26 Aug 2025 07:08:03 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJY-0006I7-Tr; Tue, 26 Aug 2025 10:06:20 -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 1uquJX-0006HS-Hr for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:19 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquJQ-00077V-5d for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:19 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-408-H1SnMsyzNpylgo3XuiOzZA-1; Tue, 26 Aug 2025 10:06:04 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D7D4119560B6; Tue, 26 Aug 2025 14:05:57 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1D91F1955F24; Tue, 26 Aug 2025 14:05:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217169; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Q99Erc5k50VvV9qqTAakHHbYqOuaMZCi7FIW9o0sOMk=; b=VdHGa7adzkZaurJyqUJdHIgi76DR/gQQLFh2962Q09foC/uSUKZkeh454u/PdaxQ1NzBOS DmP9IDJr6+ZvvvR0LULyrM6zxl2SLkDDQojLRnoSbAoF7c5EhyjckFcEhXZHgrCPmKnd2k HwdkxAZUUXGxmXBYRvKScVHelQOQR/4= X-MC-Unique: H1SnMsyzNpylgo3XuiOzZA-1 X-Mimecast-MFC-AGG-ID: H1SnMsyzNpylgo3XuiOzZA_1756217158 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 11/18] rust: split "chardev" crate Date: Tue, 26 Aug 2025 18:04:39 +0400 Message-ID: <20250826140449.4190022-12-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-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 @redhat.com) X-ZM-MESSAGEID: 1756217285214124100 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau --- MAINTAINERS | 1 + rust/chardev/wrapper.h | 28 ++++++++++++ rust/qemu-api/wrapper.h | 2 - rust/Cargo.lock | 14 ++++++ rust/chardev/Cargo.toml | 24 ++++++++++ rust/chardev/build.rs | 43 ++++++++++++++++++ rust/chardev/meson.build | 54 +++++++++++++++++++++++ rust/chardev/src/bindings.rs | 36 +++++++++++++++ rust/{qemu-api =3D> chardev}/src/chardev.rs | 0 rust/chardev/src/lib.rs | 4 ++ rust/hw/char/pl011/Cargo.toml | 1 + rust/hw/char/pl011/meson.build | 1 + rust/hw/char/pl011/src/device.rs | 2 +- rust/meson.build | 1 + rust/qemu-api/Cargo.toml | 1 + rust/qemu-api/meson.build | 7 ++- rust/qemu-api/src/bindings.rs | 9 +--- rust/qemu-api/src/lib.rs | 1 - rust/qemu-api/src/qdev.rs | 2 +- 19 files changed, 214 insertions(+), 17 deletions(-) create mode 100644 rust/chardev/wrapper.h create mode 100644 rust/chardev/Cargo.toml create mode 100644 rust/chardev/build.rs create mode 100644 rust/chardev/meson.build create mode 100644 rust/chardev/src/bindings.rs rename rust/{qemu-api =3D> chardev}/src/chardev.rs (100%) create mode 100644 rust/chardev/src/lib.rs diff --git a/MAINTAINERS b/MAINTAINERS index 8054913502..4ab89b208c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3511,6 +3511,7 @@ Rust M: Manos Pitsidianakis S: Maintained F: rust/bql/ +F: rust/chardev/ F: rust/common/ F: rust/migration/ F: rust/qemu-api diff --git a/rust/chardev/wrapper.h b/rust/chardev/wrapper.h new file mode 100644 index 0000000000..65ede6ea6d --- /dev/null +++ b/rust/chardev/wrapper.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * This header file is meant to be used as input to the `bindgen` applicat= ion + * 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 sym= bols + * 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 "chardev/char-fe.h" +#include "chardev/char-serial.h" diff --git a/rust/qemu-api/wrapper.h b/rust/qemu-api/wrapper.h index b99df9f568..07dbc9987a 100644 --- a/rust/qemu-api/wrapper.h +++ b/rust/qemu-api/wrapper.h @@ -52,13 +52,11 @@ typedef enum memory_order { #include "system/system.h" #include "hw/sysbus.h" #include "system/memory.h" -#include "chardev/char-fe.h" #include "hw/clock.h" #include "hw/qdev-clock.h" #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" #include "hw/irq.h" -#include "chardev/char-serial.h" #include "exec/memattrs.h" #include "system/address-spaces.h" #include "hw/char/pl011.h" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 0f1dcea6e4..ac325969cc 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -51,6 +51,18 @@ dependencies =3D [ "migration", ] =20 +[[package]] +name =3D "chardev" +version =3D "0.1.0" +dependencies =3D [ + "bql", + "common", + "migration", + "qemu_api_macros", + "qom", + "util", +] + [[package]] name =3D "common" version =3D "0.1.0" @@ -115,6 +127,7 @@ dependencies =3D [ "bilge-impl", "bits", "bql", + "chardev", "common", "migration", "qemu_api", @@ -161,6 +174,7 @@ version =3D "0.1.0" dependencies =3D [ "anyhow", "bql", + "chardev", "common", "foreign", "libc", diff --git a/rust/chardev/Cargo.toml b/rust/chardev/Cargo.toml new file mode 100644 index 0000000000..7df9c677fc --- /dev/null +++ b/rust/chardev/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name =3D "chardev" +version =3D "0.1.0" +description =3D "Rust bindings for QEMU/chardev" +resolver =3D "2" +publish =3D false + +authors.workspace =3D true +edition.workspace =3D true +homepage.workspace =3D true +license.workspace =3D true +repository.workspace =3D true +rust-version.workspace =3D true + +[dependencies] +common =3D { path =3D "../common" } +bql =3D { path =3D "../bql" } +migration =3D { path =3D "../migration" } +qom =3D { path =3D "../qom" } +util =3D { path =3D "../util" } +qemu_api_macros =3D { path =3D "../qemu-api-macros" } + +[lints] +workspace =3D true diff --git a/rust/chardev/build.rs b/rust/chardev/build.rs new file mode 100644 index 0000000000..b684233f7f --- /dev/null +++ b/rust/chardev/build.rs @@ -0,0 +1,43 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis +// SPDX-License-Identifier: GPL-2.0-or-later + +#[cfg(unix)] +use std::os::unix::fs::symlink as symlink_file; +#[cfg(windows)] +use std::os::windows::fs::symlink_file; +use std::{env, fs::remove_file, io::Result, path::Path}; + +fn main() -> Result<()> { + let file =3D if let Ok(root) =3D env::var("MESON_BUILD_ROOT") { + format!("{root}/rust/chardev/bindings.inc.rs") + } else { + // Placing bindings.inc.rs in the source directory is supported + // but not documented or encouraged. + format!("{}/src/bindings.inc.rs", env!("CARGO_MANIFEST_DIR")) + }; + + let file =3D Path::new(&file); + if !Path::new(&file).exists() { + panic!(concat!( + "\n", + " No generated C bindings found! Maybe you wanted one of\n", + " `make clippy`, `make rustfmt`, `make rustdoc`?\n", + "\n", + " For other uses of `cargo`, start a subshell with\n", + " `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n= ", + " the top of the build tree." + )); + } + + let out_dir =3D env::var("OUT_DIR").unwrap(); + let dest_path =3D format!("{out_dir}/bindings.inc.rs"); + let dest_path =3D Path::new(&dest_path); + if dest_path.symlink_metadata().is_ok() { + remove_file(dest_path)?; + } + symlink_file(file, dest_path)?; + + println!("cargo:rerun-if-changed=3Dbuild.rs"); + Ok(()) +} diff --git a/rust/chardev/meson.build b/rust/chardev/meson.build new file mode 100644 index 0000000000..918e0a5224 --- /dev/null +++ b/rust/chardev/meson.build @@ -0,0 +1,54 @@ +_chardev_cfg =3D run_command(rustc_args, + '--config-headers', config_host_h, '--features', files('Cargo.toml'), + capture: true, check: true).stdout().strip().splitlines() + +c_enums =3D [ + 'QEMUChrEvent', +] +_chardev_bindgen_args =3D [] +foreach enum : c_enums + _chardev_bindgen_args +=3D ['--rustified-enum', enum] +endforeach + +# TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. +# +# Rust bindings generation with `bindgen` might fail in some cases where t= he +# 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 +_chardev_bindings_inc_rs =3D rust.bindgen( + input: 'wrapper.h', + dependencies: common_ss.all_dependencies(), + output: 'bindings.inc.rs', + include_directories: bindings_incdir, + bindgen_version: ['>=3D0.60.0'], + args: bindgen_args_common + _chardev_bindgen_args, +) + +_chardev_rs =3D static_library( + 'chardev', + structured_sources( + [ + 'src/lib.rs', + 'src/bindings.rs', + 'src/chardev.rs', + ], + {'.': _chardev_bindings_inc_rs} + ), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_abi: 'rust', + rust_args: _chardev_cfg, + dependencies: [qemuutil_rs, common_rs, bql_rs, migration_rs, qemu_api_ma= cros, qom_rs, util_rs, chardev], +) + +chardev_rs =3D declare_dependency(link_with: [_chardev_rs], dependencies: = [qemu_api_macros, chardev]) + +# Doctests are essentially integration tests, so they need the same depend= encies. +# Note that running them requires the object files for C code, so place th= em +# in a separate suite that is run by the "build" CI jobs rather than "chec= k". +rust.doctest('rust-chardev-rs-doctests', + _chardev_rs, + protocol: 'rust', + dependencies: chardev_rs, + suite: ['doc', 'rust']) diff --git a/rust/chardev/src/bindings.rs b/rust/chardev/src/bindings.rs new file mode 100644 index 0000000000..2d98026d62 --- /dev/null +++ b/rust/chardev/src/bindings.rs @@ -0,0 +1,36 @@ +// 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 +)] + +use common::Zeroable; + +#[cfg(MESON)] +include!("bindings.inc.rs"); + +#[cfg(not(MESON))] +include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); + +// SAFETY: these are implemented in C; the bindings need to assert that the +// BQL is taken, either directly or via `BqlCell` and `BqlRefCell`. +// When bindings for character devices are introduced, this can be +// moved to the Opaque<> wrapper in src/chardev.rs. +unsafe impl Send for CharBackend {} +unsafe impl Sync for CharBackend {} + +unsafe impl Zeroable for CharBackend {} diff --git a/rust/qemu-api/src/chardev.rs b/rust/chardev/src/chardev.rs similarity index 100% rename from rust/qemu-api/src/chardev.rs rename to rust/chardev/src/chardev.rs diff --git a/rust/chardev/src/lib.rs b/rust/chardev/src/lib.rs new file mode 100644 index 0000000000..2863b4c7ad --- /dev/null +++ b/rust/chardev/src/lib.rs @@ -0,0 +1,4 @@ +pub mod bindings; + +mod chardev; +pub use chardev::*; diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml index da89f78727..f7ad5f8e08 100644 --- a/rust/hw/char/pl011/Cargo.toml +++ b/rust/hw/char/pl011/Cargo.toml @@ -21,6 +21,7 @@ util =3D { path =3D "../../../util" } bql =3D { path =3D "../../../bql" } migration =3D { path =3D "../../../migration" } qom =3D { path =3D "../../../qom" } +chardev =3D { path =3D "../../../chardev" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build index cd855408a5..552ccc0d60 100644 --- a/rust/hw/char/pl011/meson.build +++ b/rust/hw/char/pl011/meson.build @@ -14,6 +14,7 @@ _libpl011_rs =3D static_library( qemu_api, qemu_api_macros, qom_rs, + chardev_rs, ], ) =20 diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index a3bcd1297a..b1c65bd79c 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -9,6 +9,7 @@ }; =20 use bql::BqlRefCell; +use chardev::{CharBackend, Chardev, Event}; use common::{static_assert, uninit_field_mut, Zeroable}; use migration::{ impl_vmstate_forward, vmstate_fields, vmstate_of, vmstate_struct, vmst= ate_subsections, @@ -16,7 +17,6 @@ }; use qemu_api::{ bindings::{qdev_prop_bool, qdev_prop_chr}, - chardev::{CharBackend, Chardev, Event}, irq::{IRQState, InterruptSource}, memory::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder= }, prelude::*, diff --git a/rust/meson.build b/rust/meson.build index 043603d416..4d9e291223 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -29,6 +29,7 @@ subdir('util') subdir('migration') subdir('bql') subdir('qom') +subdir('chardev') subdir('qemu-api') =20 subdir('hw') diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index 333cef1c5d..b8aa6d037c 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -15,6 +15,7 @@ rust-version.workspace =3D true =20 [dependencies] common =3D { path =3D "../common" } +chardev =3D { path =3D "../chardev" } migration =3D { path =3D "../migration" } util =3D { path =3D "../util" } bql =3D { path =3D "../bql" } diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index c5038aa5bd..e3af8f86c1 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -7,7 +7,6 @@ c_enums =3D [ 'GpioPolarity', 'MachineInitPhase', 'MemoryDeviceInfoKind', - 'QEMUChrEvent', 'ResetType', 'device_endian', ] @@ -23,9 +22,10 @@ foreach enum : c_bitfields endforeach =20 blocked_type =3D [ + 'Chardev', + 'Error', 'ObjectClass', 'VMStateDescription', - 'Error', ] foreach type: blocked_type _qemu_api_bindgen_args +=3D ['--blocklist-type', type] @@ -53,7 +53,6 @@ _qemu_api_rs =3D static_library( [ 'src/lib.rs', 'src/bindings.rs', - 'src/chardev.rs', 'src/irq.rs', 'src/memory.rs', 'src/prelude.rs', @@ -65,7 +64,7 @@ _qemu_api_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _qemu_api_cfg, - dependencies: [anyhow_rs, common_rs, foreign_rs, libc_rs, qemu_api_macro= s, qemuutil_rs, util_rs, migration_rs, bql_rs, qom_rs, + dependencies: [anyhow_rs, common_rs, chardev_rs, foreign_rs, libc_rs, qe= mu_api_macros, qemuutil_rs, util_rs, migration_rs, bql_rs, qom_rs, qom, hwcore, chardev, migration], ) =20 diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs index 525f136ae2..526bcf8e31 100644 --- a/rust/qemu-api/src/bindings.rs +++ b/rust/qemu-api/src/bindings.rs @@ -20,6 +20,7 @@ =20 //! `bindgen`-generated declarations. =20 +use chardev::bindings::Chardev; use common::Zeroable; use migration::bindings::VMStateDescription; use qom::bindings::ObjectClass; @@ -31,13 +32,6 @@ #[cfg(not(MESON))] include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); =20 -// SAFETY: these are implemented in C; the bindings need to assert that the -// BQL is taken, either directly or via `BqlCell` and `BqlRefCell`. -// When bindings for character devices are introduced, this can be -// moved to the Opaque<> wrapper in src/chardev.rs. -unsafe impl Send for CharBackend {} -unsafe impl Sync for CharBackend {} - // SAFETY: this is a pure data struct unsafe impl Send for CoalescedMemoryRange {} unsafe impl Sync for CoalescedMemoryRange {} @@ -59,4 +53,3 @@ unsafe impl Zeroable for crate::bindings::MemoryRegionOps= __bindgen_ty_1 {} unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_2 {} unsafe impl Zeroable for crate::bindings::MemoryRegionOps {} unsafe impl Zeroable for crate::bindings::MemTxAttrs {} -unsafe impl Zeroable for crate::bindings::CharBackend {} diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index f9551c13a5..712116b585 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -13,7 +13,6 @@ #[rustfmt::skip] pub mod prelude; =20 -pub mod chardev; pub mod irq; pub mod memory; pub mod qdev; diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs index a94af90bb1..98d8593ca5 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/qemu-api/src/qdev.rs @@ -10,6 +10,7 @@ }; =20 pub use bindings::{ClockEvent, DeviceClass, Property, ResetType}; +use chardev::Chardev; use common::{callbacks::FnCall, Opaque}; use migration::vmstate::VMStateDescription; use qom::{ @@ -20,7 +21,6 @@ =20 use crate::{ bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, ResettableClas= s}, - chardev::Chardev, irq::InterruptSource, }; =20 --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217386; cv=none; d=zohomail.com; s=zohoarc; b=R8gbz5odkDEptpNrgkzKAp3b2//M/ggc0VToBLkmbXfxcR6TEiGP+PX1q2x4GI+iZaHUb1jc7EqbN8VEFdsIobra2zymeqa84D5K8CdGS6x/ko4KYsHKiSGBRoBe8t9I9lnBj90o5a9ZJAbdMkATwUUpqcxe7xPMLgk/3GzWrNY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217386; h=Content-Type: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=9WZ7F+XP0Vd0E4zHWQW+CEf4jTjZrCq4Obs8JQIWJzc=; b=ENl3H0709UYTVLQDAP6nOIGUvPROg4op5LqrNGzyU9XunhSgbVkajag9yy6MZRZ1wmZNCPcms7w62mMOsZVfnx7iBdMvlT3qqIUQPWnOKQhJUzYzoeMaSU85aSHUuN53EIsumL2NaR5TFC79RewPHau/DBfZ7YnUHtgpwKY/ZXo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217385804267.5578498297991; Tue, 26 Aug 2025 07:09:45 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJe-0006KP-Pk; Tue, 26 Aug 2025 10:06:26 -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 1uquJd-0006Jx-Bw for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:25 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquJY-00078d-JJ for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:25 -0400 Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-245-vwPEL4FsNVC32u4bsDg0xA-1; Tue, 26 Aug 2025 10:06:12 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 7CFF1195609F; Tue, 26 Aug 2025 14:06:03 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E715419560AB; Tue, 26 Aug 2025 14:06:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217176; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9WZ7F+XP0Vd0E4zHWQW+CEf4jTjZrCq4Obs8JQIWJzc=; b=fmWCW+sOe91UMJjb0YPB6qkaKbUeEf3zptSmhVYn1qT7QN6K0SAWC4LABCmvBH/dj/RDSZ ajyJuMOK7xFjHMbybRrByZ6Gt7EQElgK3Fe7Jje55rNaHUAOnpErIyJNPzBZpMO3KsRXt1 MggZ4GDiTlac81Kmw4s1n5lAK8Nv1tI= X-MC-Unique: vwPEL4FsNVC32u4bsDg0xA-1 X-Mimecast-MFC-AGG-ID: vwPEL4FsNVC32u4bsDg0xA_1756217163 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 12/18] rust: split "system" crate Date: Tue, 26 Aug 2025 18:04:40 +0400 Message-ID: <20250826140449.4190022-13-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 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=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-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 @redhat.com) X-ZM-MESSAGEID: 1756217386854116600 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau --- MAINTAINERS | 1 + rust/qemu-api/wrapper.h | 3 -- rust/system/wrapper.h | 29 +++++++++++++ rust/Cargo.lock | 13 ++++++ rust/Cargo.toml | 1 + rust/bql/src/cell.rs | 5 +-- rust/hw/char/pl011/Cargo.toml | 1 + rust/hw/char/pl011/meson.build | 1 + rust/hw/char/pl011/src/device.rs | 2 +- rust/hw/timer/hpet/Cargo.toml | 1 + rust/hw/timer/hpet/meson.build | 1 + rust/hw/timer/hpet/src/device.rs | 12 +++--- rust/meson.build | 1 + rust/qemu-api/Cargo.toml | 1 + rust/qemu-api/meson.build | 7 +-- rust/qemu-api/src/bindings.rs | 14 +----- rust/qemu-api/src/lib.rs | 1 - rust/qemu-api/src/sysbus.rs | 2 +- rust/system/Cargo.toml | 22 ++++++++++ rust/system/build.rs | 43 +++++++++++++++++++ rust/system/meson.build | 57 +++++++++++++++++++++++++ rust/system/src/bindings.rs | 41 ++++++++++++++++++ rust/system/src/lib.rs | 4 ++ rust/{qemu-api =3D> system}/src/memory.rs | 2 +- 24 files changed, 232 insertions(+), 33 deletions(-) create mode 100644 rust/system/wrapper.h create mode 100644 rust/system/Cargo.toml create mode 100644 rust/system/build.rs create mode 100644 rust/system/meson.build create mode 100644 rust/system/src/bindings.rs create mode 100644 rust/system/src/lib.rs rename rust/{qemu-api =3D> system}/src/memory.rs (99%) diff --git a/MAINTAINERS b/MAINTAINERS index 4ab89b208c..ce8bb3c076 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3518,6 +3518,7 @@ F: rust/qemu-api F: rust/qemu-api-macros F: rust/qom/ F: rust/rustfmt.toml +F: rust/system/ F: rust/util/ F: scripts/get-wraps-from-cargo-registry.py =20 diff --git a/rust/qemu-api/wrapper.h b/rust/qemu-api/wrapper.h index 07dbc9987a..564733b903 100644 --- a/rust/qemu-api/wrapper.h +++ b/rust/qemu-api/wrapper.h @@ -49,14 +49,11 @@ typedef enum memory_order { =20 #include "qemu/osdep.h" #include "qemu-io.h" -#include "system/system.h" #include "hw/sysbus.h" -#include "system/memory.h" #include "hw/clock.h" #include "hw/qdev-clock.h" #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" #include "hw/irq.h" #include "exec/memattrs.h" -#include "system/address-spaces.h" #include "hw/char/pl011.h" diff --git a/rust/system/wrapper.h b/rust/system/wrapper.h new file mode 100644 index 0000000000..48abde8505 --- /dev/null +++ b/rust/system/wrapper.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * This header file is meant to be used as input to the `bindgen` applicat= ion + * 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 sym= bols + * 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 "system/system.h" +#include "system/memory.h" +#include "system/address-spaces.h" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index ac325969cc..e4946549c0 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -92,6 +92,7 @@ dependencies =3D [ "qemu_api", "qemu_api_macros", "qom", + "system", "util", ] =20 @@ -133,6 +134,7 @@ dependencies =3D [ "qemu_api", "qemu_api_macros", "qom", + "system", "util", ] =20 @@ -181,6 +183,7 @@ dependencies =3D [ "migration", "qemu_api_macros", "qom", + "system", "util", ] =20 @@ -224,6 +227,16 @@ dependencies =3D [ "unicode-ident", ] =20 +[[package]] +name =3D "system" +version =3D "0.1.0" +dependencies =3D [ + "common", + "qemu_api_macros", + "qom", + "util", +] + [[package]] name =3D "unicode-ident" version =3D "1.0.12" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index fd7cf9b0e1..1c18e69660 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -8,6 +8,7 @@ members =3D [ "qemu-api-macros", "qemu-api", "qom", + "system", "hw/char/pl011", "hw/timer/hpet", "util", diff --git a/rust/bql/src/cell.rs b/rust/bql/src/cell.rs index 43109130c5..23b21f0214 100644 --- a/rust/bql/src/cell.rs +++ b/rust/bql/src/cell.rs @@ -77,9 +77,8 @@ //! //! ```ignore //! # use bql::BqlRefCell; -//! # use qemu_api::prelude::*; -//! # use qemu_api::{irq::InterruptSource, irq::IRQState}; -//! # use qemu_api::{sysbus::SysBusDevice, qom::Owned, qom::ParentField}; +//! # use qom::{Owned, ParentField}; +//! # use system::{InterruptSource, IRQState, SysBusDevice}; //! # const N_GPIOS: usize =3D 8; //! # struct PL061Registers { /* ... */ } //! # unsafe impl ObjectType for PL061State { diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml index f7ad5f8e08..e4b1c3f1eb 100644 --- a/rust/hw/char/pl011/Cargo.toml +++ b/rust/hw/char/pl011/Cargo.toml @@ -22,6 +22,7 @@ bql =3D { path =3D "../../../bql" } migration =3D { path =3D "../../../migration" } qom =3D { path =3D "../../../qom" } chardev =3D { path =3D "../../../chardev" } +system =3D { path =3D "../../../system" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build index 552ccc0d60..06ebaf7ab9 100644 --- a/rust/hw/char/pl011/meson.build +++ b/rust/hw/char/pl011/meson.build @@ -15,6 +15,7 @@ _libpl011_rs =3D static_library( qemu_api_macros, qom_rs, chardev_rs, + system_rs, ], ) =20 diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index b1c65bd79c..5307ac480b 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -18,7 +18,6 @@ use qemu_api::{ bindings::{qdev_prop_bool, qdev_prop_chr}, irq::{IRQState, InterruptSource}, - memory::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder= }, prelude::*, qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType= , ResettablePhasesImpl}, sysbus::{SysBusDevice, SysBusDeviceImpl}, @@ -28,6 +27,7 @@ qom_isa, IsA, Object, ObjectClassMethods, ObjectDeref, ObjectImpl, Obj= ectMethods, ObjectType, Owned, ParentField, ParentInit, }; +use system::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder= }; use util::{log::Log, log_mask_ln}; =20 use crate::registers::{self, Interrupt, RegisterOffset}; diff --git a/rust/hw/timer/hpet/Cargo.toml b/rust/hw/timer/hpet/Cargo.toml index 19456ec72b..a95b1271c6 100644 --- a/rust/hw/timer/hpet/Cargo.toml +++ b/rust/hw/timer/hpet/Cargo.toml @@ -16,6 +16,7 @@ util =3D { path =3D "../../../util" } migration =3D { path =3D "../../../migration" } bql =3D { path =3D "../../../bql" } qom =3D { path =3D "../../../qom" } +system =3D { path =3D "../../../system" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/timer/hpet/meson.build b/rust/hw/timer/hpet/meson.build index 195dc48e1c..74cbe27df8 100644 --- a/rust/hw/timer/hpet/meson.build +++ b/rust/hw/timer/hpet/meson.build @@ -11,6 +11,7 @@ _libhpet_rs =3D static_library( qemu_api, qemu_api_macros, qom_rs, + system_rs, ], ) =20 diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index b876b35a43..f5cc4ee0ad 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -17,19 +17,17 @@ VMStateDescription, VMStateFieldHelper, }; use qemu_api::{ - bindings::{ - address_space_memory, address_space_stl_le, qdev_prop_bit, qdev_pr= op_bool, - qdev_prop_uint32, qdev_prop_usize, - }, + bindings::{qdev_prop_bit, qdev_prop_bool, qdev_prop_uint32, qdev_prop_= usize}, irq::InterruptSource, - memory::{ - hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder, MEM= TXATTRS_UNSPECIFIED, - }, prelude::*, qdev::{DeviceImpl, DeviceState, Property, ResetType, ResettablePhasesI= mpl}, sysbus::{SysBusDevice, SysBusDeviceImpl}, }; use qom::{qom_isa, Object, ObjectImpl, ObjectType, ParentField, ParentInit= }; +use system::{ + bindings::{address_space_memory, address_space_stl_le, hwaddr}, + MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder, MEMTXATTRS_UNSP= ECIFIED, +}; use util::timer::{Timer, CLOCK_VIRTUAL, NANOSECONDS_PER_SECOND}; =20 use crate::fw_cfg::HPETFwConfig; diff --git a/rust/meson.build b/rust/meson.build index 4d9e291223..d8b71f5506 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -29,6 +29,7 @@ subdir('util') subdir('migration') subdir('bql') subdir('qom') +subdir('system') subdir('chardev') subdir('qemu-api') =20 diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index b8aa6d037c..2429c4eb9f 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -21,6 +21,7 @@ util =3D { path =3D "../util" } bql =3D { path =3D "../bql" } qemu_api_macros =3D { path =3D "../qemu-api-macros" } qom =3D { path =3D "../qom" } +system =3D { path =3D "../system" } anyhow =3D "~1.0" libc =3D "0.2.162" foreign =3D "~0.3.1" diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index e3af8f86c1..644ca44573 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -8,7 +8,6 @@ c_enums =3D [ 'MachineInitPhase', 'MemoryDeviceInfoKind', 'ResetType', - 'device_endian', ] _qemu_api_bindgen_args =3D [] foreach enum : c_enums @@ -24,8 +23,11 @@ endforeach blocked_type =3D [ 'Chardev', 'Error', + 'MemTxAttrs', + 'MemoryRegion', 'ObjectClass', 'VMStateDescription', + 'device_endian', ] foreach type: blocked_type _qemu_api_bindgen_args +=3D ['--blocklist-type', type] @@ -54,7 +56,6 @@ _qemu_api_rs =3D static_library( 'src/lib.rs', 'src/bindings.rs', 'src/irq.rs', - 'src/memory.rs', 'src/prelude.rs', 'src/qdev.rs', 'src/sysbus.rs', @@ -64,7 +65,7 @@ _qemu_api_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _qemu_api_cfg, - dependencies: [anyhow_rs, common_rs, chardev_rs, foreign_rs, libc_rs, qe= mu_api_macros, qemuutil_rs, util_rs, migration_rs, bql_rs, qom_rs, + dependencies: [anyhow_rs, common_rs, chardev_rs, foreign_rs, libc_rs, qe= mu_api_macros, qemuutil_rs, util_rs, migration_rs, bql_rs, qom_rs, system_r= s, qom, hwcore, chardev, migration], ) =20 diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs index 526bcf8e31..63b805c76e 100644 --- a/rust/qemu-api/src/bindings.rs +++ b/rust/qemu-api/src/bindings.rs @@ -24,6 +24,7 @@ use common::Zeroable; use migration::bindings::VMStateDescription; use qom::bindings::ObjectClass; +use system::bindings::{device_endian, MemTxAttrs, MemoryRegion}; use util::bindings::Error; =20 #[cfg(MESON)] @@ -32,15 +33,6 @@ #[cfg(not(MESON))] include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); =20 -// SAFETY: this is a pure data struct -unsafe impl Send for CoalescedMemoryRange {} -unsafe impl Sync for CoalescedMemoryRange {} - -// SAFETY: these are constants and vtables; the Send and Sync requirements -// are deferred to the unsafe callbacks that they contain -unsafe impl Send for MemoryRegionOps {} -unsafe impl Sync for MemoryRegionOps {} - unsafe impl Send for Property {} unsafe impl Sync for Property {} =20 @@ -49,7 +41,3 @@ unsafe impl Sync for TypeInfo {} =20 unsafe impl Zeroable for crate::bindings::Property__bindgen_ty_1 {} unsafe impl Zeroable for crate::bindings::Property {} -unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_1 {} -unsafe impl Zeroable for crate::bindings::MemoryRegionOps__bindgen_ty_2 {} -unsafe impl Zeroable for crate::bindings::MemoryRegionOps {} -unsafe impl Zeroable for crate::bindings::MemTxAttrs {} diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 712116b585..38ff102b86 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -14,6 +14,5 @@ pub mod prelude; =20 pub mod irq; -pub mod memory; pub mod qdev; pub mod sysbus; diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs index 016e57935a..66b618c705 100644 --- a/rust/qemu-api/src/sysbus.rs +++ b/rust/qemu-api/src/sysbus.rs @@ -9,11 +9,11 @@ pub use bindings::SysBusDeviceClass; use common::Opaque; use qom::{IsA, Object, ObjectCast, ObjectDeref, ObjectType, Owned}; +use system::MemoryRegion; =20 use crate::{ bindings, irq::{IRQState, InterruptSource}, - memory::MemoryRegion, qdev::{DeviceClassExt, DeviceImpl, DeviceState}, }; =20 diff --git a/rust/system/Cargo.toml b/rust/system/Cargo.toml new file mode 100644 index 0000000000..6803895e08 --- /dev/null +++ b/rust/system/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name =3D "system" +version =3D "0.1.0" +description =3D "Rust bindings for QEMU/system" +resolver =3D "2" +publish =3D false + +authors.workspace =3D true +edition.workspace =3D true +homepage.workspace =3D true +license.workspace =3D true +repository.workspace =3D true +rust-version.workspace =3D true + +[dependencies] +common =3D { path =3D "../common" } +qom =3D { path =3D "../qom" } +util =3D { path =3D "../util" } +qemu_api_macros =3D { path =3D "../qemu-api-macros" } + +[lints] +workspace =3D true diff --git a/rust/system/build.rs b/rust/system/build.rs new file mode 100644 index 0000000000..34ba641373 --- /dev/null +++ b/rust/system/build.rs @@ -0,0 +1,43 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis +// SPDX-License-Identifier: GPL-2.0-or-later + +#[cfg(unix)] +use std::os::unix::fs::symlink as symlink_file; +#[cfg(windows)] +use std::os::windows::fs::symlink_file; +use std::{env, fs::remove_file, io::Result, path::Path}; + +fn main() -> Result<()> { + let file =3D if let Ok(root) =3D env::var("MESON_BUILD_ROOT") { + format!("{root}/rust/system/bindings.inc.rs") + } else { + // Placing bindings.inc.rs in the source directory is supported + // but not documented or encouraged. + format!("{}/src/bindings.inc.rs", env!("CARGO_MANIFEST_DIR")) + }; + + let file =3D Path::new(&file); + if !Path::new(&file).exists() { + panic!(concat!( + "\n", + " No generated C bindings found! Maybe you wanted one of\n", + " `make clippy`, `make rustfmt`, `make rustdoc`?\n", + "\n", + " For other uses of `cargo`, start a subshell with\n", + " `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n= ", + " the top of the build tree." + )); + } + + let out_dir =3D env::var("OUT_DIR").unwrap(); + let dest_path =3D format!("{out_dir}/bindings.inc.rs"); + let dest_path =3D Path::new(&dest_path); + if dest_path.symlink_metadata().is_ok() { + remove_file(dest_path)?; + } + symlink_file(file, dest_path)?; + + println!("cargo:rerun-if-changed=3Dbuild.rs"); + Ok(()) +} diff --git a/rust/system/meson.build b/rust/system/meson.build new file mode 100644 index 0000000000..cbd3eb4717 --- /dev/null +++ b/rust/system/meson.build @@ -0,0 +1,57 @@ +_system_cfg =3D run_command(rustc_args, + '--config-headers', config_host_h, '--features', files('Cargo.toml'), + capture: true, check: true).stdout().strip().splitlines() + +c_enums =3D [ + 'device_endian', +] +_system_bindgen_args =3D [] +foreach enum : c_enums + _system_bindgen_args +=3D ['--rustified-enum', enum] +endforeach + +# TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. +# +# Rust bindings generation with `bindgen` might fail in some cases where t= he +# 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 +_system_bindings_inc_rs =3D rust.bindgen( + input: 'wrapper.h', + dependencies: common_ss.all_dependencies(), + output: 'bindings.inc.rs', + include_directories: bindings_incdir, + bindgen_version: ['>=3D0.60.0'], + args: bindgen_args_common + _system_bindgen_args, +) + +_system_rs =3D static_library( + 'system', + structured_sources( + [ + 'src/lib.rs', + 'src/bindings.rs', + 'src/memory.rs', + ], + {'.': _system_bindings_inc_rs} + ), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_abi: 'rust', + rust_args: _system_cfg, + dependencies: [qemuutil_rs, common_rs, bql_rs, migration_rs, qemu_api_ma= cros, qom_rs, util_rs, + hwcore], +) + +system_rs =3D declare_dependency(link_with: [_system_rs], + dependencies: [qemu_api_macros, hwcore]) + +# Doctests are essentially integration tests, so they need the same depend= encies. +# Note that running them requires the object files for C code, so place th= em +# in a separate suite that is run by the "build" CI jobs rather than "chec= k". +rust.doctest('rust-system-rs-doctests', + _system_rs, + protocol: 'rust', + dependencies: system_rs, + suite: ['doc', 'rust']) + diff --git a/rust/system/src/bindings.rs b/rust/system/src/bindings.rs new file mode 100644 index 0000000000..43edd98807 --- /dev/null +++ b/rust/system/src/bindings.rs @@ -0,0 +1,41 @@ +// 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 +)] + +use common::Zeroable; + +#[cfg(MESON)] +include!("bindings.inc.rs"); + +#[cfg(not(MESON))] +include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); + +// SAFETY: these are constants and vtables; the Send and Sync requirements +// are deferred to the unsafe callbacks that they contain +unsafe impl Send for MemoryRegionOps {} +unsafe impl Sync for MemoryRegionOps {} + +// SAFETY: this is a pure data struct +unsafe impl Send for CoalescedMemoryRange {} +unsafe impl Sync for CoalescedMemoryRange {} + +unsafe impl Zeroable for MemoryRegionOps__bindgen_ty_1 {} +unsafe impl Zeroable for MemoryRegionOps__bindgen_ty_2 {} +unsafe impl Zeroable for MemoryRegionOps {} +unsafe impl Zeroable for MemTxAttrs {} diff --git a/rust/system/src/lib.rs b/rust/system/src/lib.rs new file mode 100644 index 0000000000..dfb68d3ea0 --- /dev/null +++ b/rust/system/src/lib.rs @@ -0,0 +1,4 @@ +pub mod bindings; + +mod memory; +pub use memory::*; diff --git a/rust/qemu-api/src/memory.rs b/rust/system/src/memory.rs similarity index 99% rename from rust/qemu-api/src/memory.rs rename to rust/system/src/memory.rs index 480cc6b0c5..af69fb30bf 100644 --- a/rust/qemu-api/src/memory.rs +++ b/rust/system/src/memory.rs @@ -9,11 +9,11 @@ marker::PhantomData, }; =20 -pub use bindings::{hwaddr, MemTxAttrs}; use common::{callbacks::FnCall, uninit::MaybeUninitField, zeroable::Zeroab= le, Opaque}; use qom::{IsA, Object, ObjectType}; =20 use crate::bindings::{self, device_endian, memory_region_init_io}; +pub use crate::bindings::{hwaddr, MemTxAttrs}; =20 pub struct MemoryRegionOps( bindings::MemoryRegionOps, --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217685; cv=none; d=zohomail.com; s=zohoarc; b=TFEuFkZjg2Ebj4S5KjoQVQ2uRkI8vn6su9TdE07ifVuBm035qGPaQNcFbWKl5lQFxheYTrl13aSfK9627o3D1HznaoBw+HpCrc6MKugIljo6pPpxnJ3X6Rdo5++pQKMZ3YXcBbdMYIN7GxXqteoAzLYHLuUgGjIW5OjIzGJBGdA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217685; h=Content-Type: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=XvwCIrS0tHQ0/SPChJSCGSmNkNVeeZOxW+qU6kX3a0g=; b=YANL/t0N6A6lWEzJ1lsc01wZXVNMSTzDFMR6gDwDNeOfvXNTGShu5nws+2j3EUtap/As39So0sRSxsEOSsPIJnD3aoPG2dGjBYU+LZ2yJ+4tiwqUHos56aFXAl3f2e+X8T5Y125W0VQVYHMcTbm/DoIHwzZGhtXYC+1k10T4pNU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217685318606.2749480680583; Tue, 26 Aug 2025 07:14:45 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJt-0006QU-TS; Tue, 26 Aug 2025 10:06:42 -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 1uquJq-0006Px-F4 for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:38 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquJh-0007A4-9W for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:38 -0400 Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-479-XURCNVWuNMqroGeKeYQe3g-1; Tue, 26 Aug 2025 10:06:17 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2A63619560B6; Tue, 26 Aug 2025 14:06:09 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DA41A19560AD; Tue, 26 Aug 2025 14:06:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217182; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XvwCIrS0tHQ0/SPChJSCGSmNkNVeeZOxW+qU6kX3a0g=; b=IaD3Gm+QAx8mHkQgfp/rblrUkol2dhCwOGcAsjQLfJcxsU+sUFap8C4zc6nP9GXdxo+tYA +2Xr1EQO4ZZFtihWhpvCmq2tGTVRo2E4Cru2E4Oz2JHrBgjBkS29VCgtr3X4GtdyqmOISE +KsCjrEdS+QfKQzLkzqaWi3JF9IgCCA= X-MC-Unique: XURCNVWuNMqroGeKeYQe3g-1 X-Mimecast-MFC-AGG-ID: XURCNVWuNMqroGeKeYQe3g_1756217169 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 13/18] rust: split "hwcore" crate Date: Tue, 26 Aug 2025 18:04:41 +0400 Message-ID: <20250826140449.4190022-14-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 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=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, T_SPF_TEMPERROR=0.01 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1756217687006116600 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau --- MAINTAINERS | 1 + rust/hw/core/wrapper.h | 32 ++++++++ rust/qemu-api/wrapper.h | 6 -- rust/Cargo.lock | 17 ++++ rust/Cargo.toml | 1 + rust/hw/char/pl011/Cargo.toml | 1 + rust/hw/char/pl011/meson.build | 1 + rust/hw/char/pl011/src/device.rs | 20 +++-- rust/hw/core/Cargo.toml | 26 +++++++ rust/hw/core/build.rs | 43 +++++++++++ rust/hw/core/meson.build | 94 +++++++++++++++++++++++ rust/hw/core/src/bindings.rs | 41 ++++++++++ rust/{qemu-api =3D> hw/core}/src/irq.rs | 0 rust/hw/core/src/lib.rs | 12 +++ rust/{qemu-api =3D> hw/core}/src/qdev.rs | 6 +- rust/{qemu-api =3D> hw/core}/src/sysbus.rs | 0 rust/{qemu-api =3D> hw/core}/tests/tests.rs | 20 ++--- rust/hw/timer/hpet/Cargo.toml | 1 + rust/hw/timer/hpet/meson.build | 1 + rust/hw/timer/hpet/src/device.rs | 22 +++--- rust/meson.build | 1 + rust/qemu-api/Cargo.toml | 1 + rust/qemu-api/meson.build | 17 +--- rust/qemu-api/src/bindings.rs | 10 --- rust/qemu-api/src/lib.rs | 4 - rust/qemu-api/src/prelude.rs | 4 - 26 files changed, 305 insertions(+), 77 deletions(-) create mode 100644 rust/hw/core/wrapper.h create mode 100644 rust/hw/core/Cargo.toml create mode 100644 rust/hw/core/build.rs create mode 100644 rust/hw/core/meson.build create mode 100644 rust/hw/core/src/bindings.rs rename rust/{qemu-api =3D> hw/core}/src/irq.rs (100%) create mode 100644 rust/hw/core/src/lib.rs rename rust/{qemu-api =3D> hw/core}/src/qdev.rs (98%) rename rust/{qemu-api =3D> hw/core}/src/sysbus.rs (100%) rename rust/{qemu-api =3D> hw/core}/tests/tests.rs (89%) diff --git a/MAINTAINERS b/MAINTAINERS index ce8bb3c076..3f40a80240 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3513,6 +3513,7 @@ S: Maintained F: rust/bql/ F: rust/chardev/ F: rust/common/ +F: rust/hw/core/ F: rust/migration/ F: rust/qemu-api F: rust/qemu-api-macros diff --git a/rust/hw/core/wrapper.h b/rust/hw/core/wrapper.h new file mode 100644 index 0000000000..3bdbd1249e --- /dev/null +++ b/rust/hw/core/wrapper.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * This header file is meant to be used as input to the `bindgen` applicat= ion + * 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 sym= bols + * 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 "hw/sysbus.h" +#include "hw/clock.h" +#include "hw/qdev-clock.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "hw/irq.h" diff --git a/rust/qemu-api/wrapper.h b/rust/qemu-api/wrapper.h index 564733b903..7c9c20b14f 100644 --- a/rust/qemu-api/wrapper.h +++ b/rust/qemu-api/wrapper.h @@ -49,11 +49,5 @@ typedef enum memory_order { =20 #include "qemu/osdep.h" #include "qemu-io.h" -#include "hw/sysbus.h" -#include "hw/clock.h" -#include "hw/qdev-clock.h" -#include "hw/qdev-properties.h" -#include "hw/qdev-properties-system.h" -#include "hw/irq.h" #include "exec/memattrs.h" #include "hw/char/pl011.h" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index e4946549c0..7ed22ca687 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -88,6 +88,7 @@ version =3D "0.1.0" dependencies =3D [ "bql", "common", + "hwcore", "migration", "qemu_api", "qemu_api_macros", @@ -96,6 +97,20 @@ dependencies =3D [ "util", ] =20 +[[package]] +name =3D "hwcore" +version =3D "0.1.0" +dependencies =3D [ + "bql", + "chardev", + "common", + "migration", + "qemu_api_macros", + "qom", + "system", + "util", +] + [[package]] name =3D "itertools" version =3D "0.11.0" @@ -130,6 +145,7 @@ dependencies =3D [ "bql", "chardev", "common", + "hwcore", "migration", "qemu_api", "qemu_api_macros", @@ -179,6 +195,7 @@ dependencies =3D [ "chardev", "common", "foreign", + "hwcore", "libc", "migration", "qemu_api_macros", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 1c18e69660..ca94d2cf40 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -9,6 +9,7 @@ members =3D [ "qemu-api", "qom", "system", + "hw/core", "hw/char/pl011", "hw/timer/hpet", "util", diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml index e4b1c3f1eb..830d88586b 100644 --- a/rust/hw/char/pl011/Cargo.toml +++ b/rust/hw/char/pl011/Cargo.toml @@ -23,6 +23,7 @@ migration =3D { path =3D "../../../migration" } qom =3D { path =3D "../../../qom" } chardev =3D { path =3D "../../../chardev" } system =3D { path =3D "../../../system" } +hwcore =3D { path =3D "../../../hw/core" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } =20 diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build index 06ebaf7ab9..83030476de 100644 --- a/rust/hw/char/pl011/meson.build +++ b/rust/hw/char/pl011/meson.build @@ -16,6 +16,7 @@ _libpl011_rs =3D static_library( qom_rs, chardev_rs, system_rs, + hwcore_rs, ], ) =20 diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index 5307ac480b..e0d89db28d 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -11,18 +11,16 @@ use bql::BqlRefCell; use chardev::{CharBackend, Chardev, Event}; use common::{static_assert, uninit_field_mut, Zeroable}; +use hwcore::{ + bindings::{qdev_prop_bool, qdev_prop_chr}, + declare_properties, define_property, vmstate_clock, Clock, ClockEvent,= DeviceImpl, + DeviceMethods, DeviceState, IRQState, InterruptSource, Property, Reset= Type, + ResettablePhasesImpl, SysBusDevice, SysBusDeviceImpl, SysBusDeviceMeth= ods, +}; use migration::{ impl_vmstate_forward, vmstate_fields, vmstate_of, vmstate_struct, vmst= ate_subsections, vmstate_unused, VMStateDescription, }; -use qemu_api::{ - bindings::{qdev_prop_bool, qdev_prop_chr}, - irq::{IRQState, InterruptSource}, - prelude::*, - qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType= , ResettablePhasesImpl}, - sysbus::{SysBusDevice, SysBusDeviceImpl}, - vmstate_clock, -}; use qom::{ qom_isa, IsA, Object, ObjectClassMethods, ObjectDeref, ObjectImpl, Obj= ectMethods, ObjectType, Owned, ParentField, ParentInit, @@ -786,16 +784,16 @@ extern "C" fn pl011_post_load(opaque: *mut c_void, ve= rsion_id: c_int) -> c_int { ..Zeroable::ZERO }; =20 -qemu_api::declare_properties! { +declare_properties! { PL011_PROPERTIES, - qemu_api::define_property!( + define_property!( c"chardev", PL011State, char_backend, unsafe { &qdev_prop_chr }, CharBackend ), - qemu_api::define_property!( + define_property!( c"migrate-clk", PL011State, migrate_clock, diff --git a/rust/hw/core/Cargo.toml b/rust/hw/core/Cargo.toml new file mode 100644 index 0000000000..0b35380264 --- /dev/null +++ b/rust/hw/core/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name =3D "hwcore" +version =3D "0.1.0" +description =3D "Rust bindings for QEMU/hwcore" +resolver =3D "2" +publish =3D false + +authors.workspace =3D true +edition.workspace =3D true +homepage.workspace =3D true +license.workspace =3D true +repository.workspace =3D true +rust-version.workspace =3D true + +[dependencies] +common =3D { path =3D "../../common" } +bql =3D { path =3D "../../bql" } +qom =3D { path =3D "../../qom" } +chardev =3D { path =3D "../../chardev" } +migration =3D { path =3D "../../migration" } +system =3D { path =3D "../../system" } +util =3D { path =3D "../../util" } +qemu_api_macros =3D { path =3D "../../qemu-api-macros" } + +[lints] +workspace =3D true diff --git a/rust/hw/core/build.rs b/rust/hw/core/build.rs new file mode 100644 index 0000000000..3f8e1bff89 --- /dev/null +++ b/rust/hw/core/build.rs @@ -0,0 +1,43 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis +// SPDX-License-Identifier: GPL-2.0-or-later + +#[cfg(unix)] +use std::os::unix::fs::symlink as symlink_file; +#[cfg(windows)] +use std::os::windows::fs::symlink_file; +use std::{env, fs::remove_file, io::Result, path::Path}; + +fn main() -> Result<()> { + let file =3D if let Ok(root) =3D env::var("MESON_BUILD_ROOT") { + format!("{root}/rust/hw/core/bindings.inc.rs") + } else { + // Placing bindings.inc.rs in the source directory is supported + // but not documented or encouraged. + format!("{}/src/bindings.inc.rs", env!("CARGO_MANIFEST_DIR")) + }; + + let file =3D Path::new(&file); + if !Path::new(&file).exists() { + panic!(concat!( + "\n", + " No generated C bindings found! Maybe you wanted one of\n", + " `make clippy`, `make rustfmt`, `make rustdoc`?\n", + "\n", + " For other uses of `cargo`, start a subshell with\n", + " `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n= ", + " the top of the build tree." + )); + } + + let out_dir =3D env::var("OUT_DIR").unwrap(); + let dest_path =3D format!("{out_dir}/bindings.inc.rs"); + let dest_path =3D Path::new(&dest_path); + if dest_path.symlink_metadata().is_ok() { + remove_file(dest_path)?; + } + symlink_file(file, dest_path)?; + + println!("cargo:rerun-if-changed=3Dbuild.rs"); + Ok(()) +} diff --git a/rust/hw/core/meson.build b/rust/hw/core/meson.build new file mode 100644 index 0000000000..d390f2d665 --- /dev/null +++ b/rust/hw/core/meson.build @@ -0,0 +1,94 @@ +_hwcore_cfg =3D run_command(rustc_args, + '--config-headers', config_host_h, '--features', files('Cargo.toml'), + capture: true, check: true).stdout().strip().splitlines() + +_hwcore_bindgen_args =3D [] +c_enums =3D [ + 'DeviceCategory', + 'GpioPolarity', + 'MachineInitPhase', + 'ResetType', +] +foreach enum : c_enums + _hwcore_bindgen_args +=3D ['--rustified-enum', enum] +endforeach + +blocked_type =3D [ + 'Chardev', + 'Error', + 'ObjectClass', + 'MemoryRegion', + 'VMStateDescription', +] +foreach type: blocked_type + _hwcore_bindgen_args +=3D ['--blocklist-type', type] +endforeach + +c_bitfields =3D [ + 'ClockEvent', +] +foreach enum : c_bitfields + _hwcore_bindgen_args +=3D ['--bitfield-enum', enum] +endforeach + +# TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. +# +# Rust bindings generation with `bindgen` might fail in some cases where t= he +# 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 +_hwcore_bindings_inc_rs =3D rust.bindgen( + input: 'wrapper.h', + dependencies: common_ss.all_dependencies(), + output: 'bindings.inc.rs', + include_directories: bindings_incdir, + bindgen_version: ['>=3D0.60.0'], + args: bindgen_args_common + _hwcore_bindgen_args, +) + +_hwcore_rs =3D static_library( + 'hwcore', + structured_sources( + [ + 'src/lib.rs', + 'src/bindings.rs', + 'src/irq.rs', + 'src/qdev.rs', + 'src/sysbus.rs', + ], + {'.': _hwcore_bindings_inc_rs} + ), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_abi: 'rust', + rust_args: _hwcore_cfg, + dependencies: [qemu_api_macros, common_rs, bql_rs, chardev_rs, migration= _rs, qemuutil_rs, qom_rs, system_rs, util_rs, + qom, hwcore, chardev, migration], +) + +hwcore_rs =3D declare_dependency(link_with: [_hwcore_rs], + dependencies: [qom_rs, hwcore]) + +# Doctests are essentially integration tests, so they need the same depend= encies. +# Note that running them requires the object files for C code, so place th= em +# in a separate suite that is run by the "build" CI jobs rather than "chec= k". +rust.doctest('rust-hwcore-rs-doctests', + _hwcore_rs, + protocol: 'rust', + dependencies: hwcore_rs, + suite: ['doc', 'rust']) + +test('rust-hwcore-rs-integration', + executable( + 'rust-hwcore-rs-integration', + files('tests/tests.rs'), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_args: ['--test'], + install: false, + dependencies: [common_rs, hwcore_rs, bql_rs, migration_rs, qemu_ap= i_macros, util_rs]), + args: [ + '--test', '--test-threads', '1', + '--format', 'pretty', + ], + protocol: 'rust', + suite: ['unit', 'rust']) diff --git a/rust/hw/core/src/bindings.rs b/rust/hw/core/src/bindings.rs new file mode 100644 index 0000000000..919c02b56a --- /dev/null +++ b/rust/hw/core/src/bindings.rs @@ -0,0 +1,41 @@ +// 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 +)] + +use chardev::bindings::Chardev; +use common::Zeroable; +use migration::bindings::VMStateDescription; +use qom::bindings::ObjectClass; +use system::bindings::MemoryRegion; +use util::bindings::Error; + +#[cfg(MESON)] +include!("bindings.inc.rs"); + +#[cfg(not(MESON))] +include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); + +unsafe impl Send for Property {} +unsafe impl Sync for Property {} + +unsafe impl Send for TypeInfo {} +unsafe impl Sync for TypeInfo {} + +unsafe impl Zeroable for Property__bindgen_ty_1 {} +unsafe impl Zeroable for Property {} diff --git a/rust/qemu-api/src/irq.rs b/rust/hw/core/src/irq.rs similarity index 100% rename from rust/qemu-api/src/irq.rs rename to rust/hw/core/src/irq.rs diff --git a/rust/hw/core/src/lib.rs b/rust/hw/core/src/lib.rs new file mode 100644 index 0000000000..c5c33f3dec --- /dev/null +++ b/rust/hw/core/src/lib.rs @@ -0,0 +1,12 @@ +pub use qom; + +pub mod bindings; + +mod irq; +pub use irq::*; + +mod qdev; +pub use qdev::*; + +mod sysbus; +pub use sysbus::*; diff --git a/rust/qemu-api/src/qdev.rs b/rust/hw/core/src/qdev.rs similarity index 98% rename from rust/qemu-api/src/qdev.rs rename to rust/hw/core/src/qdev.rs index 98d8593ca5..16a4769758 100644 --- a/rust/qemu-api/src/qdev.rs +++ b/rust/hw/core/src/qdev.rs @@ -9,7 +9,6 @@ ptr::NonNull, }; =20 -pub use bindings::{ClockEvent, DeviceClass, Property, ResetType}; use chardev::Chardev; use common::{callbacks::FnCall, Opaque}; use migration::vmstate::VMStateDescription; @@ -19,6 +18,7 @@ }; pub use util::{Error, Result}; =20 +pub use crate::bindings::{ClockEvent, DeviceClass, Property, ResetType}; use crate::{ bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, ResettableClas= s}, irq::InterruptSource, @@ -428,11 +428,11 @@ macro_rules! vmstate_clock { ::common::assert_field_type!( $struct_name, $field_name, - ::qom::Owned<$crate::qdev::Clock> $(, num =3D $num)? + ::qom::Owned<$crate::Clock> $(, num =3D $num)? ); ::std::mem::offset_of!($struct_name, $field_name) }, - size: ::core::mem::size_of::<*const $crate::qdev::Clock>(), + size: ::core::mem::size_of::<*const $crate::Clock>(), flags: ::migration::VMStateFlags( ::migration::VMStateFlags::VMS_STRUCT.0 | ::migration::VMStateFlags::VMS_POINTER.0, diff --git a/rust/qemu-api/src/sysbus.rs b/rust/hw/core/src/sysbus.rs similarity index 100% rename from rust/qemu-api/src/sysbus.rs rename to rust/hw/core/src/sysbus.rs diff --git a/rust/qemu-api/tests/tests.rs b/rust/hw/core/tests/tests.rs similarity index 89% rename from rust/qemu-api/tests/tests.rs rename to rust/hw/core/tests/tests.rs index 821aabe831..f11c15ac62 100644 --- a/rust/qemu-api/tests/tests.rs +++ b/rust/hw/core/tests/tests.rs @@ -6,21 +6,17 @@ =20 use bql::BqlCell; use common::Zeroable; -use migration::VMStateDescription; -use qemu_api::{ - bindings::qdev_prop_bool, - declare_properties, define_property, - qdev::{DeviceClassExt, DeviceImpl, DeviceState, Property, ResettablePh= asesImpl}, - sysbus::SysBusDevice, +use hwcore::{ + bindings::qdev_prop_bool, declare_properties, define_property, DeviceC= lassExt, DeviceImpl, + DeviceState, Property, ResettablePhasesImpl, SysBusDevice, }; +use migration::vmstate::VMStateDescription; use qom::{ - Object, ObjectCast, ObjectClassMethods, ObjectDeref, ObjectImpl, Objec= tMethods, ObjectType, - ParentField, + qom_isa, Object, ObjectCast, ObjectClassMethods, ObjectDeref, ObjectIm= pl, ObjectMethods, + ObjectType, ParentField, }; use util::bindings::{module_call_init, module_init_type}; =20 -mod vmstate_tests; - // Test that macros can compile. pub static VMSTATE: VMStateDescription =3D VMStateDescription { name: c"name".as_ptr(), @@ -35,7 +31,7 @@ pub struct DummyState { migrate_clock: bool, } =20 -qom::qom_isa!(DummyState: Object, DeviceState); +qom_isa!(DummyState: Object, DeviceState); =20 pub struct DummyClass { parent_class: ::Class, @@ -86,7 +82,7 @@ pub struct DummyChildState { parent: ParentField, } =20 -qom::qom_isa!(DummyChildState: Object, DeviceState, DummyState); +qom_isa!(DummyChildState: Object, DeviceState, DummyState); =20 pub struct DummyChildClass { parent_class: ::Class, diff --git a/rust/hw/timer/hpet/Cargo.toml b/rust/hw/timer/hpet/Cargo.toml index a95b1271c6..e28d66f645 100644 --- a/rust/hw/timer/hpet/Cargo.toml +++ b/rust/hw/timer/hpet/Cargo.toml @@ -19,6 +19,7 @@ qom =3D { path =3D "../../../qom" } system =3D { path =3D "../../../system" } qemu_api =3D { path =3D "../../../qemu-api" } qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } +hwcore =3D { path =3D "../../../hw/core" } =20 [lints] workspace =3D true diff --git a/rust/hw/timer/hpet/meson.build b/rust/hw/timer/hpet/meson.build index 74cbe27df8..d65306c169 100644 --- a/rust/hw/timer/hpet/meson.build +++ b/rust/hw/timer/hpet/meson.build @@ -12,6 +12,7 @@ _libhpet_rs =3D static_library( qemu_api_macros, qom_rs, system_rs, + hwcore_rs, ], ) =20 diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index f5cc4ee0ad..2ea101bb7f 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -12,17 +12,15 @@ =20 use bql::{BqlCell, BqlRefCell}; use common::{bitops::IntegerExt, uninit_field_mut, Zeroable}; +use hwcore::{ + bindings::{qdev_prop_bit, qdev_prop_bool, qdev_prop_uint32, qdev_prop_= usize}, + declare_properties, define_property, DeviceImpl, DeviceMethods, Device= State, InterruptSource, + Property, ResetType, ResettablePhasesImpl, SysBusDevice, SysBusDeviceI= mpl, SysBusDeviceMethods, +}; use migration::{ vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmsta= te_validate, VMStateDescription, VMStateFieldHelper, }; -use qemu_api::{ - bindings::{qdev_prop_bit, qdev_prop_bool, qdev_prop_uint32, qdev_prop_= usize}, - irq::InterruptSource, - prelude::*, - qdev::{DeviceImpl, DeviceState, Property, ResetType, ResettablePhasesI= mpl}, - sysbus::{SysBusDevice, SysBusDeviceImpl}, -}; use qom::{qom_isa, Object, ObjectImpl, ObjectType, ParentField, ParentInit= }; use system::{ bindings::{address_space_memory, address_space_stl_le, hwaddr}, @@ -900,9 +898,9 @@ impl ObjectImpl for HPETState { } =20 // TODO: Make these properties user-configurable! -qemu_api::declare_properties! { +declare_properties! { HPET_PROPERTIES, - qemu_api::define_property!( + define_property!( c"timers", HPETState, num_timers, @@ -910,7 +908,7 @@ impl ObjectImpl for HPETState { u8, default =3D HPET_MIN_TIMERS ), - qemu_api::define_property!( + define_property!( c"msi", HPETState, flags, @@ -919,7 +917,7 @@ impl ObjectImpl for HPETState { bit =3D HPET_FLAG_MSI_SUPPORT_SHIFT as u8, default =3D false, ), - qemu_api::define_property!( + define_property!( c"hpet-intcap", HPETState, int_route_cap, @@ -927,7 +925,7 @@ impl ObjectImpl for HPETState { u32, default =3D 0 ), - qemu_api::define_property!( + define_property!( c"hpet-offset-saved", HPETState, hpet_offset_saved, diff --git a/rust/meson.build b/rust/meson.build index d8b71f5506..041b0a473e 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -31,6 +31,7 @@ subdir('bql') subdir('qom') subdir('system') subdir('chardev') +subdir('hw/core') subdir('qemu-api') =20 subdir('hw') diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index 2429c4eb9f..9f216e45a6 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -16,6 +16,7 @@ rust-version.workspace =3D true [dependencies] common =3D { path =3D "../common" } chardev =3D { path =3D "../chardev" } +hwcore =3D { path =3D "../hw/core" } migration =3D { path =3D "../migration" } util =3D { path =3D "../util" } bql =3D { path =3D "../bql" } diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index 644ca44573..a4c90b2bf7 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -3,22 +3,12 @@ _qemu_api_cfg =3D run_command(rustc_args, capture: true, check: true).stdout().strip().splitlines() =20 c_enums =3D [ - 'DeviceCategory', - 'GpioPolarity', - 'MachineInitPhase', 'MemoryDeviceInfoKind', - 'ResetType', ] _qemu_api_bindgen_args =3D [] foreach enum : c_enums _qemu_api_bindgen_args +=3D ['--rustified-enum', enum] endforeach -c_bitfields =3D [ - 'ClockEvent', -] -foreach enum : c_bitfields - _qemu_api_bindgen_args +=3D ['--bitfield-enum', enum] -endforeach =20 blocked_type =3D [ 'Chardev', @@ -55,17 +45,14 @@ _qemu_api_rs =3D static_library( [ 'src/lib.rs', 'src/bindings.rs', - 'src/irq.rs', 'src/prelude.rs', - 'src/qdev.rs', - 'src/sysbus.rs', ], {'.' : _qemu_api_bindings_inc_rs}, ), override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _qemu_api_cfg, - dependencies: [anyhow_rs, common_rs, chardev_rs, foreign_rs, libc_rs, qe= mu_api_macros, qemuutil_rs, util_rs, migration_rs, bql_rs, qom_rs, system_r= s, + dependencies: [anyhow_rs, common_rs, chardev_rs, foreign_rs, libc_rs, qe= mu_api_macros, qemuutil_rs, util_rs, migration_rs, bql_rs, qom_rs, system_r= s, hwcore_rs, qom, hwcore, chardev, migration], ) =20 @@ -87,7 +74,7 @@ rust.doctest('rust-qemu-api-doctests', test('rust-qemu-api-integration', executable( 'rust-qemu-api-integration', - files('tests/tests.rs', 'tests/vmstate_tests.rs'), + files('tests/vmstate_tests.rs'), override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_args: ['--test'], install: false, diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs index 63b805c76e..9c863e9b5b 100644 --- a/rust/qemu-api/src/bindings.rs +++ b/rust/qemu-api/src/bindings.rs @@ -21,7 +21,6 @@ //! `bindgen`-generated declarations. =20 use chardev::bindings::Chardev; -use common::Zeroable; use migration::bindings::VMStateDescription; use qom::bindings::ObjectClass; use system::bindings::{device_endian, MemTxAttrs, MemoryRegion}; @@ -32,12 +31,3 @@ =20 #[cfg(not(MESON))] include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); - -unsafe impl Send for Property {} -unsafe impl Sync for Property {} - -unsafe impl Send for TypeInfo {} -unsafe impl Sync for TypeInfo {} - -unsafe impl Zeroable for crate::bindings::Property__bindgen_ty_1 {} -unsafe impl Zeroable for crate::bindings::Property {} diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs index 38ff102b86..50fb2fa99d 100644 --- a/rust/qemu-api/src/lib.rs +++ b/rust/qemu-api/src/lib.rs @@ -12,7 +12,3 @@ // for prelude-like modules #[rustfmt::skip] pub mod prelude; - -pub mod irq; -pub mod qdev; -pub mod sysbus; diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs index 9e9d1c8247..8db56f9f81 100644 --- a/rust/qemu-api/src/prelude.rs +++ b/rust/qemu-api/src/prelude.rs @@ -3,7 +3,3 @@ // SPDX-License-Identifier: GPL-2.0-or-later =20 //! Commonly used traits and types for QEMU. - -pub use crate::qdev::DeviceMethods; - -pub use crate::sysbus::SysBusDeviceMethods; --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217572; cv=none; d=zohomail.com; s=zohoarc; b=jjOCi6TGTUk5UtjOGasezHReoLwuLAJQ8JKWSGkrdC0Aspudc9uqu0QZkI1RSYBHqnuNgLPyAHc6bqVpNQESkt6Iq5xFqjUtNH2o9Rm5PEL8+f8Z7tC07LGjUMCcdxhmcvJTa91e1RpkCS4UfyKT0b9t8ysCdPxCoUKB1B6K+oQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217572; h=Content-Type: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=LQmIIYLUzh097n/O5nyO2lTxEH1GUsu0mM4g6N8iGa4=; b=HjoIA4YCHj/rGM5817KIeSNnk96Dao58o57PWCjT4ypNg6OEh8Vs6U9pKdViwDM5FJV/UjNMe9m9VMQCA6++cI18VN8lwEZqXYPtZjVT3FrcRrJae2X2f5Jb0xfxVQjW6X/4S2lxJtwWIhjxYJHRTb4Pios9vtSXzsFpkTZGSEY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217572364161.20987217112065; Tue, 26 Aug 2025 07:12:52 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJp-0006PZ-Mv; Tue, 26 Aug 2025 10:06:37 -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 1uquJn-0006OS-N1 for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:35 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquJh-0007A9-3D for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:35 -0400 Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-102-qux9eUsQOEeC6s1dVvRnAA-1; Tue, 26 Aug 2025 10:06:19 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C058B19541B0; Tue, 26 Aug 2025 14:06:14 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 652D719560AB; Tue, 26 Aug 2025 14:06:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217183; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LQmIIYLUzh097n/O5nyO2lTxEH1GUsu0mM4g6N8iGa4=; b=HFm3H9XYLlC1MoMWQhM2buvwEc/CzOTM8BCjuHBF/X7kY4Q80hMc2Cd7zg/+QQoYYThb6v Sn8YpbKukEQlmxvdTHV6BiwfpkcWF2CvbyJhrKA+sO1Bui+gwF1EAjAfzxHQodfME9ZSmG 7w5b7EzWMX3la9uLEq5f1bvEOdP75t0= X-MC-Unique: qux9eUsQOEeC6s1dVvRnAA-1 X-Mimecast-MFC-AGG-ID: qux9eUsQOEeC6s1dVvRnAA_1756217174 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 14/18] rust: rename qemu_api_macros -> qemu_macros Date: Tue, 26 Aug 2025 18:04:42 +0400 Message-ID: <20250826140449.4190022-15-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 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=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-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 @redhat.com) X-ZM-MESSAGEID: 1756217573195116600 From: Marc-Andr=C3=A9 Lureau Since "qemu_api" is no longer the unique crate to provide APIs. Signed-off-by: Marc-Andr=C3=A9 Lureau --- MAINTAINERS | 2 +- rust/Cargo.lock | 22 +++++++++---------- rust/Cargo.toml | 2 +- rust/bits/Cargo.toml | 2 +- rust/bits/meson.build | 2 +- rust/bits/src/lib.rs | 4 ++-- rust/chardev/Cargo.toml | 2 +- rust/chardev/meson.build | 4 ++-- rust/chardev/src/chardev.rs | 2 +- rust/common/src/opaque.rs | 4 ++-- rust/hw/char/pl011/Cargo.toml | 2 +- rust/hw/char/pl011/meson.build | 4 ++-- rust/hw/char/pl011/src/device.rs | 4 ++-- rust/hw/char/pl011/src/registers.rs | 2 +- rust/hw/core/Cargo.toml | 2 +- rust/hw/core/meson.build | 4 ++-- rust/hw/core/src/irq.rs | 2 +- rust/hw/core/src/qdev.rs | 4 ++-- rust/hw/core/src/sysbus.rs | 2 +- rust/hw/core/tests/tests.rs | 4 ++-- rust/hw/timer/hpet/Cargo.toml | 2 +- rust/hw/timer/hpet/meson.build | 4 ++-- rust/hw/timer/hpet/src/device.rs | 6 ++--- rust/meson.build | 2 +- rust/migration/Cargo.toml | 2 +- rust/qemu-api/Cargo.toml | 2 +- rust/qemu-api/meson.build | 4 ++-- .../Cargo.toml | 2 +- .../meson.build | 10 ++++----- .../src/bits.rs | 0 .../src/lib.rs | 0 .../src/tests.rs | 0 rust/qom/Cargo.toml | 2 +- rust/qom/meson.build | 4 ++-- rust/qom/src/qom.rs | 4 ++-- rust/qom/tests/tests.rs | 2 +- rust/system/Cargo.toml | 2 +- rust/system/meson.build | 4 ++-- rust/system/src/memory.rs | 2 +- rust/util/Cargo.toml | 2 +- rust/util/meson.build | 2 +- rust/util/src/timer.rs | 4 ++-- 42 files changed, 69 insertions(+), 69 deletions(-) rename rust/{qemu-api-macros =3D> qemu-macros}/Cargo.toml (94%) rename rust/{qemu-api-macros =3D> qemu-macros}/meson.build (63%) rename rust/{qemu-api-macros =3D> qemu-macros}/src/bits.rs (100%) rename rust/{qemu-api-macros =3D> qemu-macros}/src/lib.rs (100%) rename rust/{qemu-api-macros =3D> qemu-macros}/src/tests.rs (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 3f40a80240..62790c7b5d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3516,7 +3516,7 @@ F: rust/common/ F: rust/hw/core/ F: rust/migration/ F: rust/qemu-api -F: rust/qemu-api-macros +F: rust/qemu-macros/ F: rust/qom/ F: rust/rustfmt.toml F: rust/system/ diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 7ed22ca687..9bb2ab5bf6 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -41,7 +41,7 @@ dependencies =3D [ name =3D "bits" version =3D "0.1.0" dependencies =3D [ - "qemu_api_macros", + "qemu_macros", ] =20 [[package]] @@ -58,7 +58,7 @@ dependencies =3D [ "bql", "common", "migration", - "qemu_api_macros", + "qemu_macros", "qom", "util", ] @@ -91,7 +91,7 @@ dependencies =3D [ "hwcore", "migration", "qemu_api", - "qemu_api_macros", + "qemu_macros", "qom", "system", "util", @@ -105,7 +105,7 @@ dependencies =3D [ "chardev", "common", "migration", - "qemu_api_macros", + "qemu_macros", "qom", "system", "util", @@ -131,7 +131,7 @@ name =3D "migration" version =3D "0.1.0" dependencies =3D [ "common", - "qemu_api_macros", + "qemu_macros", "util", ] =20 @@ -148,7 +148,7 @@ dependencies =3D [ "hwcore", "migration", "qemu_api", - "qemu_api_macros", + "qemu_macros", "qom", "system", "util", @@ -198,14 +198,14 @@ dependencies =3D [ "hwcore", "libc", "migration", - "qemu_api_macros", + "qemu_macros", "qom", "system", "util", ] =20 [[package]] -name =3D "qemu_api_macros" +name =3D "qemu_macros" version =3D "0.1.0" dependencies =3D [ "proc-macro2", @@ -220,7 +220,7 @@ dependencies =3D [ "bql", "common", "migration", - "qemu_api_macros", + "qemu_macros", "util", ] =20 @@ -249,7 +249,7 @@ name =3D "system" version =3D "0.1.0" dependencies =3D [ "common", - "qemu_api_macros", + "qemu_macros", "qom", "util", ] @@ -268,7 +268,7 @@ dependencies =3D [ "common", "foreign", "libc", - "qemu_api_macros", + "qemu_macros", ] =20 [[package]] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index ca94d2cf40..1acee9e7cb 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -5,7 +5,7 @@ members =3D [ "bql", "common", "migration", - "qemu-api-macros", + "qemu-macros", "qemu-api", "qom", "system", diff --git a/rust/bits/Cargo.toml b/rust/bits/Cargo.toml index 1ff38a4117..7fce972b27 100644 --- a/rust/bits/Cargo.toml +++ b/rust/bits/Cargo.toml @@ -13,7 +13,7 @@ repository.workspace =3D true rust-version.workspace =3D true =20 [dependencies] -qemu_api_macros =3D { path =3D "../qemu-api-macros" } +qemu_macros =3D { path =3D "../qemu-macros" } =20 [lints] workspace =3D true diff --git a/rust/bits/meson.build b/rust/bits/meson.build index 2a41e138c5..359ca86f15 100644 --- a/rust/bits/meson.build +++ b/rust/bits/meson.build @@ -3,7 +3,7 @@ _bits_rs =3D static_library( 'src/lib.rs', override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', - dependencies: [qemu_api_macros], + dependencies: [qemu_macros], ) =20 bits_rs =3D declare_dependency(link_with: _bits_rs) diff --git a/rust/bits/src/lib.rs b/rust/bits/src/lib.rs index d485d6bd11..4e091aebbd 100644 --- a/rust/bits/src/lib.rs +++ b/rust/bits/src/lib.rs @@ -380,11 +380,11 @@ fn from(x: $type) -> Self { }; =20 { $type:ty: $expr:expr } =3D> { - ::qemu_api_macros::bits_const_internal! { $type @ ($expr) } + ::qemu_macros::bits_const_internal! { $type @ ($expr) } }; =20 { $type:ty as $int_type:ty: $expr:expr } =3D> { - (::qemu_api_macros::bits_const_internal! { $type @ ($expr) }.into_= bits()) as $int_type + (::qemu_macros::bits_const_internal! { $type @ ($expr) }.into_bits= ()) as $int_type }; } =20 diff --git a/rust/chardev/Cargo.toml b/rust/chardev/Cargo.toml index 7df9c677fc..c139177307 100644 --- a/rust/chardev/Cargo.toml +++ b/rust/chardev/Cargo.toml @@ -18,7 +18,7 @@ bql =3D { path =3D "../bql" } migration =3D { path =3D "../migration" } qom =3D { path =3D "../qom" } util =3D { path =3D "../util" } -qemu_api_macros =3D { path =3D "../qemu-api-macros" } +qemu_macros =3D { path =3D "../qemu-macros" } =20 [lints] workspace =3D true diff --git a/rust/chardev/meson.build b/rust/chardev/meson.build index 918e0a5224..487f36e27d 100644 --- a/rust/chardev/meson.build +++ b/rust/chardev/meson.build @@ -39,10 +39,10 @@ _chardev_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _chardev_cfg, - dependencies: [qemuutil_rs, common_rs, bql_rs, migration_rs, qemu_api_ma= cros, qom_rs, util_rs, chardev], + dependencies: [qemuutil_rs, common_rs, bql_rs, migration_rs, qemu_macros= , qom_rs, util_rs, chardev], ) =20 -chardev_rs =3D declare_dependency(link_with: [_chardev_rs], dependencies: = [qemu_api_macros, chardev]) +chardev_rs =3D declare_dependency(link_with: [_chardev_rs], dependencies: = [qemu_macros, chardev]) =20 # Doctests are essentially integration tests, so they need the same depend= encies. # Note that running them requires the object files for C code, so place th= em diff --git a/rust/chardev/src/chardev.rs b/rust/chardev/src/chardev.rs index 1a6795a938..fe90126b84 100644 --- a/rust/chardev/src/chardev.rs +++ b/rust/chardev/src/chardev.rs @@ -26,7 +26,7 @@ =20 /// A safe wrapper around [`bindings::Chardev`]. #[repr(transparent)] -#[derive(qemu_api_macros::Wrapper)] +#[derive(qemu_macros::Wrapper)] pub struct Chardev(Opaque); =20 pub type ChardevClass =3D bindings::ChardevClass; diff --git a/rust/common/src/opaque.rs b/rust/common/src/opaque.rs index e076964634..06f6b8cd29 100644 --- a/rust/common/src/opaque.rs +++ b/rust/common/src/opaque.rs @@ -194,7 +194,7 @@ pub unsafe fn new() -> Self { =20 /// Annotates [`Self`] as a transparent wrapper for another type. /// -/// Usually defined via the [`qemu_api_macros::Wrapper`] derive macro. +/// Usually defined via the [`qemu_macros::Wrapper`] derive macro. /// /// # Examples /// @@ -230,7 +230,7 @@ pub unsafe fn new() -> Self { /// /// They are not defined here to allow them to be `const`. /// -/// [`qemu_api_macros::Wrapper`]: ../../qemu_api_macros/derive.Wrapper.html +/// [`qemu_macros::Wrapper`]: ../../qemu_macros/derive.Wrapper.html pub unsafe trait Wrapper { type Wrapped; } diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml index 830d88586b..9e451fc0aa 100644 --- a/rust/hw/char/pl011/Cargo.toml +++ b/rust/hw/char/pl011/Cargo.toml @@ -25,7 +25,7 @@ chardev =3D { path =3D "../../../chardev" } system =3D { path =3D "../../../system" } hwcore =3D { path =3D "../../../hw/core" } qemu_api =3D { path =3D "../../../qemu-api" } -qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } +qemu_macros =3D { path =3D "../../../qemu-macros" } =20 [lints] workspace =3D true diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build index 83030476de..7d90f2aad6 100644 --- a/rust/hw/char/pl011/meson.build +++ b/rust/hw/char/pl011/meson.build @@ -12,7 +12,7 @@ _libpl011_rs =3D static_library( migration_rs, bql_rs, qemu_api, - qemu_api_macros, + qemu_macros, qom_rs, chardev_rs, system_rs, @@ -24,6 +24,6 @@ rust_devices_ss.add(when: 'CONFIG_X_PL011_RUST', if_true:= [declare_dependency( link_whole: [_libpl011_rs], # Putting proc macro crates in `dependencies` is necessary for Meson to = find # them when compiling the root per-target static rust lib. - dependencies: [bilge_impl_rs, qemu_api_macros], + dependencies: [bilge_impl_rs, qemu_macros], variables: {'crate': 'pl011'}, )]) diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index e0d89db28d..caaa05c04c 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -106,7 +106,7 @@ pub struct PL011Registers { } =20 #[repr(C)] -#[derive(qemu_api_macros::Object)] +#[derive(qemu_macros::Object)] /// PL011 Device Model in QEMU pub struct PL011State { pub parent_obj: ParentField, @@ -691,7 +691,7 @@ pub fn post_load(&self, _version_id: u32) -> Result<(),= ()> { } =20 #[repr(C)] -#[derive(qemu_api_macros::Object)] +#[derive(qemu_macros::Object)] /// PL011 Luminary device model. pub struct PL011Luminary { parent_obj: ParentField, diff --git a/rust/hw/char/pl011/src/registers.rs b/rust/hw/char/pl011/src/r= egisters.rs index 2bfbd81095..a1c41347ed 100644 --- a/rust/hw/char/pl011/src/registers.rs +++ b/rust/hw/char/pl011/src/registers.rs @@ -16,7 +16,7 @@ #[doc(alias =3D "offset")] #[allow(non_camel_case_types)] #[repr(u64)] -#[derive(Debug, Eq, PartialEq, qemu_api_macros::TryInto)] +#[derive(Debug, Eq, PartialEq, qemu_macros::TryInto)] pub enum RegisterOffset { /// Data Register /// diff --git a/rust/hw/core/Cargo.toml b/rust/hw/core/Cargo.toml index 0b35380264..0eb9ffee26 100644 --- a/rust/hw/core/Cargo.toml +++ b/rust/hw/core/Cargo.toml @@ -20,7 +20,7 @@ chardev =3D { path =3D "../../chardev" } migration =3D { path =3D "../../migration" } system =3D { path =3D "../../system" } util =3D { path =3D "../../util" } -qemu_api_macros =3D { path =3D "../../qemu-api-macros" } +qemu_macros =3D { path =3D "../../qemu-macros" } =20 [lints] workspace =3D true diff --git a/rust/hw/core/meson.build b/rust/hw/core/meson.build index d390f2d665..692c4b8e0f 100644 --- a/rust/hw/core/meson.build +++ b/rust/hw/core/meson.build @@ -62,7 +62,7 @@ _hwcore_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _hwcore_cfg, - dependencies: [qemu_api_macros, common_rs, bql_rs, chardev_rs, migration= _rs, qemuutil_rs, qom_rs, system_rs, util_rs, + dependencies: [qemu_macros, common_rs, bql_rs, chardev_rs, migration_rs,= qemuutil_rs, qom_rs, system_rs, util_rs, qom, hwcore, chardev, migration], ) =20 @@ -85,7 +85,7 @@ test('rust-hwcore-rs-integration', override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_args: ['--test'], install: false, - dependencies: [common_rs, hwcore_rs, bql_rs, migration_rs, qemu_ap= i_macros, util_rs]), + dependencies: [common_rs, hwcore_rs, bql_rs, migration_rs, qemu_ma= cros, util_rs]), args: [ '--test', '--test-threads', '1', '--format', 'pretty', diff --git a/rust/hw/core/src/irq.rs b/rust/hw/core/src/irq.rs index 5a380923fe..828e6cb28f 100644 --- a/rust/hw/core/src/irq.rs +++ b/rust/hw/core/src/irq.rs @@ -18,7 +18,7 @@ =20 /// An opaque wrapper around [`bindings::IRQState`]. #[repr(transparent)] -#[derive(Debug, qemu_api_macros::Wrapper)] +#[derive(Debug, qemu_macros::Wrapper)] pub struct IRQState(Opaque); =20 /// Interrupt sources are used by devices to pass changes to a value (typi= cally diff --git a/rust/hw/core/src/qdev.rs b/rust/hw/core/src/qdev.rs index 16a4769758..62f518a11a 100644 --- a/rust/hw/core/src/qdev.rs +++ b/rust/hw/core/src/qdev.rs @@ -26,7 +26,7 @@ =20 /// A safe wrapper around [`bindings::Clock`]. #[repr(transparent)] -#[derive(Debug, qemu_api_macros::Wrapper)] +#[derive(Debug, qemu_macros::Wrapper)] pub struct Clock(Opaque); =20 unsafe impl Send for Clock {} @@ -34,7 +34,7 @@ unsafe impl Sync for Clock {} =20 /// A safe wrapper around [`bindings::DeviceState`]. #[repr(transparent)] -#[derive(Debug, qemu_api_macros::Wrapper)] +#[derive(Debug, qemu_macros::Wrapper)] pub struct DeviceState(Opaque); =20 unsafe impl Send for DeviceState {} diff --git a/rust/hw/core/src/sysbus.rs b/rust/hw/core/src/sysbus.rs index 66b618c705..51631cd237 100644 --- a/rust/hw/core/src/sysbus.rs +++ b/rust/hw/core/src/sysbus.rs @@ -19,7 +19,7 @@ =20 /// A safe wrapper around [`bindings::SysBusDevice`]. #[repr(transparent)] -#[derive(Debug, qemu_api_macros::Wrapper)] +#[derive(Debug, qemu_macros::Wrapper)] pub struct SysBusDevice(Opaque); =20 unsafe impl Send for SysBusDevice {} diff --git a/rust/hw/core/tests/tests.rs b/rust/hw/core/tests/tests.rs index f11c15ac62..2898844baf 100644 --- a/rust/hw/core/tests/tests.rs +++ b/rust/hw/core/tests/tests.rs @@ -25,7 +25,7 @@ }; =20 #[repr(C)] -#[derive(qemu_api_macros::Object)] +#[derive(qemu_macros::Object)] pub struct DummyState { parent: ParentField, migrate_clock: bool, @@ -77,7 +77,7 @@ fn vmsd() -> Option<&'static VMStateDescription> { } =20 #[repr(C)] -#[derive(qemu_api_macros::Object)] +#[derive(qemu_macros::Object)] pub struct DummyChildState { parent: ParentField, } diff --git a/rust/hw/timer/hpet/Cargo.toml b/rust/hw/timer/hpet/Cargo.toml index e28d66f645..68e8187bb8 100644 --- a/rust/hw/timer/hpet/Cargo.toml +++ b/rust/hw/timer/hpet/Cargo.toml @@ -18,7 +18,7 @@ bql =3D { path =3D "../../../bql" } qom =3D { path =3D "../../../qom" } system =3D { path =3D "../../../system" } qemu_api =3D { path =3D "../../../qemu-api" } -qemu_api_macros =3D { path =3D "../../../qemu-api-macros" } +qemu_macros =3D { path =3D "../../../qemu-macros" } hwcore =3D { path =3D "../../../hw/core" } =20 [lints] diff --git a/rust/hw/timer/hpet/meson.build b/rust/hw/timer/hpet/meson.build index d65306c169..b2eee01faf 100644 --- a/rust/hw/timer/hpet/meson.build +++ b/rust/hw/timer/hpet/meson.build @@ -9,7 +9,7 @@ _libhpet_rs =3D static_library( migration_rs, bql_rs, qemu_api, - qemu_api_macros, + qemu_macros, qom_rs, system_rs, hwcore_rs, @@ -20,6 +20,6 @@ rust_devices_ss.add(when: 'CONFIG_X_HPET_RUST', if_true: = [declare_dependency( link_whole: [_libhpet_rs], # Putting proc macro crates in `dependencies` is necessary for Meson to = find # them when compiling the root per-target static rust lib. - dependencies: [qemu_api_macros], + dependencies: [qemu_macros], variables: {'crate': 'hpet'}, )]) diff --git a/rust/hw/timer/hpet/src/device.rs b/rust/hw/timer/hpet/src/devi= ce.rs index 2ea101bb7f..b883d56a9a 100644 --- a/rust/hw/timer/hpet/src/device.rs +++ b/rust/hw/timer/hpet/src/device.rs @@ -97,7 +97,7 @@ /// Timer N Interrupt Routing Capability (bits 32:63) const HPET_TN_CFG_INT_ROUTE_CAP_SHIFT: usize =3D 32; =20 -#[derive(qemu_api_macros::TryInto)] +#[derive(qemu_macros::TryInto)] #[repr(u64)] #[allow(non_camel_case_types)] /// Timer registers, masked by 0x18 @@ -110,7 +110,7 @@ enum TimerRegister { ROUTE =3D 16, } =20 -#[derive(qemu_api_macros::TryInto)] +#[derive(qemu_macros::TryInto)] #[repr(u64)] #[allow(non_camel_case_types)] /// Global registers @@ -516,7 +516,7 @@ fn write(&mut self, reg: TimerRegister, value: u64, shi= ft: u32, len: u32) { =20 /// HPET Event Timer Block Abstraction #[repr(C)] -#[derive(qemu_api_macros::Object)] +#[derive(qemu_macros::Object)] pub struct HPETState { parent_obj: ParentField, iomem: MemoryRegion, diff --git a/rust/meson.build b/rust/meson.build index 041b0a473e..9f6a0b161d 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -23,7 +23,7 @@ qemuutil_rs =3D qemuutil.partial_dependency(link_args: tr= ue, links: true) genrs =3D [] =20 subdir('common') -subdir('qemu-api-macros') +subdir('qemu-macros') subdir('bits') subdir('util') subdir('migration') diff --git a/rust/migration/Cargo.toml b/rust/migration/Cargo.toml index 98e6df2109..66af81e0a3 100644 --- a/rust/migration/Cargo.toml +++ b/rust/migration/Cargo.toml @@ -15,7 +15,7 @@ rust-version.workspace =3D true [dependencies] common =3D { path =3D "../common" } util =3D { path =3D "../util" } -qemu_api_macros =3D { path =3D "../qemu-api-macros" } +qemu_macros =3D { path =3D "../qemu-macros" } =20 [lints] workspace =3D true diff --git a/rust/qemu-api/Cargo.toml b/rust/qemu-api/Cargo.toml index 9f216e45a6..b6744f0286 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/qemu-api/Cargo.toml @@ -20,7 +20,7 @@ hwcore =3D { path =3D "../hw/core" } migration =3D { path =3D "../migration" } util =3D { path =3D "../util" } bql =3D { path =3D "../bql" } -qemu_api_macros =3D { path =3D "../qemu-api-macros" } +qemu_macros =3D { path =3D "../qemu-macros" } qom =3D { path =3D "../qom" } system =3D { path =3D "../system" } anyhow =3D "~1.0" diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build index a4c90b2bf7..02318950ff 100644 --- a/rust/qemu-api/meson.build +++ b/rust/qemu-api/meson.build @@ -52,7 +52,7 @@ _qemu_api_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _qemu_api_cfg, - dependencies: [anyhow_rs, common_rs, chardev_rs, foreign_rs, libc_rs, qe= mu_api_macros, qemuutil_rs, util_rs, migration_rs, bql_rs, qom_rs, system_r= s, hwcore_rs, + dependencies: [anyhow_rs, common_rs, chardev_rs, foreign_rs, libc_rs, qe= mu_macros, qemuutil_rs, util_rs, migration_rs, bql_rs, qom_rs, system_rs, h= wcore_rs, qom, hwcore, chardev, migration], ) =20 @@ -60,7 +60,7 @@ rust.test('rust-qemu-api-tests', _qemu_api_rs, suite: ['unit', 'rust']) =20 qemu_api =3D declare_dependency(link_with: [_qemu_api_rs], - dependencies: [qemu_api_macros, qom, hwcore, chardev, migration]) + dependencies: [qemu_macros, qom, hwcore, chardev, migration]) =20 # Doctests are essentially integration tests, so they need the same depend= encies. # Note that running them requires the object files for C code, so place th= em diff --git a/rust/qemu-api-macros/Cargo.toml b/rust/qemu-macros/Cargo.toml similarity index 94% rename from rust/qemu-api-macros/Cargo.toml rename to rust/qemu-macros/Cargo.toml index 0cd40c8e16..3b6f1d337f 100644 --- a/rust/qemu-api-macros/Cargo.toml +++ b/rust/qemu-macros/Cargo.toml @@ -1,5 +1,5 @@ [package] -name =3D "qemu_api_macros" +name =3D "qemu_macros" version =3D "0.1.0" authors =3D ["Manos Pitsidianakis "] description =3D "Rust bindings for QEMU - Utility macros" diff --git a/rust/qemu-api-macros/meson.build b/rust/qemu-macros/meson.build similarity index 63% rename from rust/qemu-api-macros/meson.build rename to rust/qemu-macros/meson.build index 2152bcb99b..d0b2992e20 100644 --- a/rust/qemu-api-macros/meson.build +++ b/rust/qemu-macros/meson.build @@ -1,5 +1,5 @@ -_qemu_api_macros_rs =3D rust.proc_macro( - 'qemu_api_macros', +_qemu_macros_rs =3D rust.proc_macro( + 'qemu_macros', files('src/lib.rs'), override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_args: [ @@ -14,9 +14,9 @@ _qemu_api_macros_rs =3D rust.proc_macro( ], ) =20 -qemu_api_macros =3D declare_dependency( - link_with: _qemu_api_macros_rs, +qemu_macros =3D declare_dependency( + link_with: _qemu_macros_rs, ) =20 -rust.test('rust-qemu-api-macros-tests', _qemu_api_macros_rs, +rust.test('rust-qemu-macros-tests', _qemu_macros_rs, suite: ['unit', 'rust']) diff --git a/rust/qemu-api-macros/src/bits.rs b/rust/qemu-macros/src/bits.rs similarity index 100% rename from rust/qemu-api-macros/src/bits.rs rename to rust/qemu-macros/src/bits.rs diff --git a/rust/qemu-api-macros/src/lib.rs b/rust/qemu-macros/src/lib.rs similarity index 100% rename from rust/qemu-api-macros/src/lib.rs rename to rust/qemu-macros/src/lib.rs diff --git a/rust/qemu-api-macros/src/tests.rs b/rust/qemu-macros/src/tests= .rs similarity index 100% rename from rust/qemu-api-macros/src/tests.rs rename to rust/qemu-macros/src/tests.rs diff --git a/rust/qom/Cargo.toml b/rust/qom/Cargo.toml index 46bbf7c7fe..060ad2ec34 100644 --- a/rust/qom/Cargo.toml +++ b/rust/qom/Cargo.toml @@ -16,7 +16,7 @@ rust-version.workspace =3D true common =3D { path =3D "../common" } bql =3D { path =3D "../bql" } migration =3D { path =3D "../migration" } -qemu_api_macros =3D { path =3D "../qemu-api-macros" } +qemu_macros =3D { path =3D "../qemu-macros" } util =3D { path =3D "../util" } =20 [lints] diff --git a/rust/qom/meson.build b/rust/qom/meson.build index 6e95d75fa0..40a2bf9ae0 100644 --- a/rust/qom/meson.build +++ b/rust/qom/meson.build @@ -31,10 +31,10 @@ _qom_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _qom_cfg, - dependencies: [qemuutil_rs, bql_rs, common_rs, migration_rs, qemu_api_ma= cros, qom], + dependencies: [qemuutil_rs, bql_rs, common_rs, migration_rs, qemu_macros= , qom], ) =20 -qom_rs =3D declare_dependency(link_with: [_qom_rs], dependencies: [qemu_ap= i_macros, qom]) +qom_rs =3D declare_dependency(link_with: [_qom_rs], dependencies: [qemu_ma= cros, qom]) =20 # Doctests are essentially integration tests, so they need the same depend= encies. # Note that running them requires the object files for C code, so place th= em diff --git a/rust/qom/src/qom.rs b/rust/qom/src/qom.rs index a632ec43f2..880bef6c47 100644 --- a/rust/qom/src/qom.rs +++ b/rust/qom/src/qom.rs @@ -112,7 +112,7 @@ =20 /// A safe wrapper around [`bindings::Object`]. #[repr(transparent)] -#[derive(Debug, qemu_api_macros::Wrapper)] +#[derive(Debug, qemu_macros::Wrapper)] pub struct Object(Opaque); =20 unsafe impl Send for Object {} @@ -173,7 +173,7 @@ fn as_ref(&self) -> &$parent { /// /// ```ignore /// #[repr(C)] -/// #[derive(qemu_api_macros::Object)] +/// #[derive(qemu_macros::Object)] /// pub struct MyDevice { /// parent: ParentField, /// ... diff --git a/rust/qom/tests/tests.rs b/rust/qom/tests/tests.rs index 49f1cbecf5..4d710f96a6 100644 --- a/rust/qom/tests/tests.rs +++ b/rust/qom/tests/tests.rs @@ -4,7 +4,7 @@ use util::bindings::{module_call_init, module_init_type}; =20 #[repr(C)] -#[derive(qemu_api_macros::Object)] +#[derive(qemu_macros::Object)] pub struct DummyObject { parent: ParentField, } diff --git a/rust/system/Cargo.toml b/rust/system/Cargo.toml index 6803895e08..d8338c8348 100644 --- a/rust/system/Cargo.toml +++ b/rust/system/Cargo.toml @@ -16,7 +16,7 @@ rust-version.workspace =3D true common =3D { path =3D "../common" } qom =3D { path =3D "../qom" } util =3D { path =3D "../util" } -qemu_api_macros =3D { path =3D "../qemu-api-macros" } +qemu_macros =3D { path =3D "../qemu-macros" } =20 [lints] workspace =3D true diff --git a/rust/system/meson.build b/rust/system/meson.build index cbd3eb4717..710462376d 100644 --- a/rust/system/meson.build +++ b/rust/system/meson.build @@ -39,12 +39,12 @@ _system_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _system_cfg, - dependencies: [qemuutil_rs, common_rs, bql_rs, migration_rs, qemu_api_ma= cros, qom_rs, util_rs, + dependencies: [qemuutil_rs, common_rs, bql_rs, migration_rs, qemu_macros= , qom_rs, util_rs, hwcore], ) =20 system_rs =3D declare_dependency(link_with: [_system_rs], - dependencies: [qemu_api_macros, hwcore]) + dependencies: [qemu_macros, hwcore]) =20 # Doctests are essentially integration tests, so they need the same depend= encies. # Note that running them requires the object files for C code, so place th= em diff --git a/rust/system/src/memory.rs b/rust/system/src/memory.rs index af69fb30bf..898401c33b 100644 --- a/rust/system/src/memory.rs +++ b/rust/system/src/memory.rs @@ -129,7 +129,7 @@ fn default() -> Self { =20 /// A safe wrapper around [`bindings::MemoryRegion`]. #[repr(transparent)] -#[derive(qemu_api_macros::Wrapper)] +#[derive(qemu_macros::Wrapper)] pub struct MemoryRegion(Opaque); =20 unsafe impl Send for MemoryRegion {} diff --git a/rust/util/Cargo.toml b/rust/util/Cargo.toml index aa10f03384..c5d1adb8fe 100644 --- a/rust/util/Cargo.toml +++ b/rust/util/Cargo.toml @@ -17,7 +17,7 @@ anyhow =3D "~1.0" libc =3D "0.2.162" foreign =3D "~0.3.1" common =3D { path =3D "../common" } -qemu_api_macros =3D { path =3D "../qemu-api-macros" } +qemu_macros =3D { path =3D "../qemu-macros" } =20 [lints] workspace =3D true diff --git a/rust/util/meson.build b/rust/util/meson.build index 3fe8e3975f..1e449b8dc7 100644 --- a/rust/util/meson.build +++ b/rust/util/meson.build @@ -45,7 +45,7 @@ _util_rs =3D static_library( override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', rust_args: _util_cfg, - dependencies: [anyhow_rs, libc_rs, foreign_rs, qemuutil_rs, common_rs, q= emu_api_macros], + dependencies: [anyhow_rs, libc_rs, foreign_rs, qemuutil_rs, common_rs, q= emu_macros], ) =20 util_rs =3D declare_dependency(link_with: [_util_rs], dependencies: [qemuu= til_rs, qom]) diff --git a/rust/util/src/timer.rs b/rust/util/src/timer.rs index 441072a949..42096cef0d 100644 --- a/rust/util/src/timer.rs +++ b/rust/util/src/timer.rs @@ -15,14 +15,14 @@ =20 /// A safe wrapper around [`bindings::QEMUTimer`]. #[repr(transparent)] -#[derive(Debug, qemu_api_macros::Wrapper)] +#[derive(Debug, qemu_macros::Wrapper)] pub struct Timer(Opaque); =20 unsafe impl Send for Timer {} unsafe impl Sync for Timer {} =20 #[repr(transparent)] -#[derive(qemu_api_macros::Wrapper)] +#[derive(qemu_macros::Wrapper)] pub struct TimerListGroup(Opaque); =20 unsafe impl Send for TimerListGroup {} --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217471; cv=none; d=zohomail.com; s=zohoarc; b=aEdgRNdY0GEDql22hyKvfm1jha0UMHYHe+5ne2ObXPdCGZD9BtBP/0BYu4SEqId5XNH6wfghR2IoDMVt/cCsiSE5apUAi66iHf+IPpUXB7hNuOXHC9qa8N1yPrm9jgr2S3oksYNQD1ynBVNghHh92SqQS17CI8TM4QJBaxn6ueE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217471; h=Content-Type: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=R6hnCxqYGdbqpp00PVtBQuxaZm1k6/PBX1O47wISIPk=; b=RMAU4vljDBO12hLI5pTQLiBcxhpGu5IdVDep0dLrgDzru/uwj+9Ai8fKPm32Nd4nnSdMrKbBZHdw94zORxY6b31mi8G6ZqwkdC9Ejkp593c1wQRLpIs8+VVOGHZj3HAY2bdvnR3qCFrVwi2VcdTf12rqNBOCp/nEbocAG2oTHjM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217471343758.7950219946035; Tue, 26 Aug 2025 07:11:11 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJy-0006So-Hl; Tue, 26 Aug 2025 10:06:47 -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 1uquJu-0006RE-CK for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:42 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquJl-0007BC-Gg for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:41 -0400 Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-594-0p2FxN_dPAm-K9pJKz0A3g-1; Tue, 26 Aug 2025 10:06:24 -0400 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DCC5718002C8; Tue, 26 Aug 2025 14:06:19 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9EAF219560AB; Tue, 26 Aug 2025 14:06:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217188; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=R6hnCxqYGdbqpp00PVtBQuxaZm1k6/PBX1O47wISIPk=; b=Q3IgdPV6eqeT4bgfRlkFuqrcEW/KdfMe82iCBNhcH410sMPBpXSzysa2FssgR+/L10P5Lt bfHMQBmY+Ws+rPa7fTkvd2qWEbS5rStm1JJcJHqS5xrjzJSQWJozsPZkep96S79ZT3v5UC timqlbPd57ExFuNFV/3ijoG888NFOvQ= X-MC-Unique: 0p2FxN_dPAm-K9pJKz0A3g-1 X-Mimecast-MFC-AGG-ID: 0p2FxN_dPAm-K9pJKz0A3g_1756217180 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 15/18] rust/hpet: drop now unneeded qemu_api dep Date: Tue, 26 Aug 2025 18:04:43 +0400 Message-ID: <20250826140449.4190022-16-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 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=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-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 @redhat.com) X-ZM-MESSAGEID: 1756217473490124100 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau --- rust/hw/timer/hpet/Cargo.toml | 1 - rust/hw/timer/hpet/meson.build | 1 - 2 files changed, 2 deletions(-) diff --git a/rust/hw/timer/hpet/Cargo.toml b/rust/hw/timer/hpet/Cargo.toml index 68e8187bb8..08bf97af55 100644 --- a/rust/hw/timer/hpet/Cargo.toml +++ b/rust/hw/timer/hpet/Cargo.toml @@ -17,7 +17,6 @@ migration =3D { path =3D "../../../migration" } bql =3D { path =3D "../../../bql" } qom =3D { path =3D "../../../qom" } system =3D { path =3D "../../../system" } -qemu_api =3D { path =3D "../../../qemu-api" } qemu_macros =3D { path =3D "../../../qemu-macros" } hwcore =3D { path =3D "../../../hw/core" } =20 diff --git a/rust/hw/timer/hpet/meson.build b/rust/hw/timer/hpet/meson.build index b2eee01faf..8ab26630d9 100644 --- a/rust/hw/timer/hpet/meson.build +++ b/rust/hw/timer/hpet/meson.build @@ -8,7 +8,6 @@ _libhpet_rs =3D static_library( util_rs, migration_rs, bql_rs, - qemu_api, qemu_macros, qom_rs, system_rs, --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217584; cv=none; d=zohomail.com; s=zohoarc; b=cMFExeKJ3od4/2u9lLFTgmAuE8bwZ8cepWYwy4ol98jtF3vSRjR3Kkyc1FZhiADCbhpPuL7OuDokaX4P4w16N6ivB3goDFYo37kE8DCMQC6ry5ngqjMuecJQMfrRfYDTaALo/iul/hIgyrWN3JJP9lFJR8kA/QqatDMcjN8PhwU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217584; h=Content-Type: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=+OV0h791og2qoAD0Epr7sODfDivVo0B6Xd6wCrSVJks=; b=lPYhLBZqlTYN0wJ6UFwqMzRhOhUog9UmskmwtgEwbiG2qwkOOEQ/2KWWNeJEFEl+7nqeXsVE1eUSwEVCfKTlLaCZ16MR5nrEHEiRYicBLnpYkSNYCrymW8azqpcQkh4/w3Mh9FsPLaCmtVYJSJfEBPOjHrIDdIWxDUuWwauUsv4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217584205535.1736871426036; Tue, 26 Aug 2025 07:13:04 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquJu-0006R4-5z; Tue, 26 Aug 2025 10:06:42 -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 1uquJr-0006Q9-T3 for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:40 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquJn-0007Bs-Hd for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:39 -0400 Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-502-w9XgFepQM0u4WVtWuU66cw-1; Tue, 26 Aug 2025 10:06:26 -0400 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5003E180029D; Tue, 26 Aug 2025 14:06:25 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 13C081977686; Tue, 26 Aug 2025 14:06:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217192; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+OV0h791og2qoAD0Epr7sODfDivVo0B6Xd6wCrSVJks=; b=eObdXm57cxlzoEFzxtwK7kNqyoViFfAR3vfMd3P6hMRIkzyP+I4j7Nd1HvRZwAsSpYaRBk HMk82dduTEcEdm4MngIy2nAbC9o4wDRgjMXyKyQ4s9LYy2v8IDRWH6CyBjsKjOjIIqFfUX iTZVynZ/aFqXc/sx/eTDytUfnXkHIKE= X-MC-Unique: w9XgFepQM0u4WVtWuU66cw-1 X-Mimecast-MFC-AGG-ID: w9XgFepQM0u4WVtWuU66cw_1756217185 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 16/18] rust/pl011: drop dependency on qemu_api Date: Tue, 26 Aug 2025 18:04:44 +0400 Message-ID: <20250826140449.4190022-17-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 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=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-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 @redhat.com) X-ZM-MESSAGEID: 1756217585696116600 From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau --- rust/hw/char/pl011/wrapper.h | 51 ++++++++++++++++++++++++++++++ rust/Cargo.lock | 2 -- rust/hw/char/pl011/Cargo.toml | 1 - rust/hw/char/pl011/build.rs | 43 +++++++++++++++++++++++++ rust/hw/char/pl011/meson.build | 27 ++++++++++++++-- rust/hw/char/pl011/src/bindings.rs | 27 ++++++++++++++++ rust/hw/char/pl011/src/device.rs | 2 +- rust/hw/char/pl011/src/lib.rs | 1 + 8 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 rust/hw/char/pl011/wrapper.h create mode 100644 rust/hw/char/pl011/build.rs create mode 100644 rust/hw/char/pl011/src/bindings.rs diff --git a/rust/hw/char/pl011/wrapper.h b/rust/hw/char/pl011/wrapper.h new file mode 100644 index 0000000000..87a5a589c8 --- /dev/null +++ b/rust/hw/char/pl011/wrapper.h @@ -0,0 +1,51 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2024 Linaro Ltd. + * + * Authors: Manos Pitsidianakis + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * 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 OT= HER + * 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` applicat= ion + * 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 sym= bols + * 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 "hw/char/pl011.h" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 9bb2ab5bf6..1a9a36ecec 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -90,7 +90,6 @@ dependencies =3D [ "common", "hwcore", "migration", - "qemu_api", "qemu_macros", "qom", "system", @@ -147,7 +146,6 @@ dependencies =3D [ "common", "hwcore", "migration", - "qemu_api", "qemu_macros", "qom", "system", diff --git a/rust/hw/char/pl011/Cargo.toml b/rust/hw/char/pl011/Cargo.toml index 9e451fc0aa..285d25c217 100644 --- a/rust/hw/char/pl011/Cargo.toml +++ b/rust/hw/char/pl011/Cargo.toml @@ -24,7 +24,6 @@ qom =3D { path =3D "../../../qom" } chardev =3D { path =3D "../../../chardev" } system =3D { path =3D "../../../system" } hwcore =3D { path =3D "../../../hw/core" } -qemu_api =3D { path =3D "../../../qemu-api" } qemu_macros =3D { path =3D "../../../qemu-macros" } =20 [lints] diff --git a/rust/hw/char/pl011/build.rs b/rust/hw/char/pl011/build.rs new file mode 100644 index 0000000000..721bf2c457 --- /dev/null +++ b/rust/hw/char/pl011/build.rs @@ -0,0 +1,43 @@ +// Copyright 2024, Linaro Limited +// Author(s): Manos Pitsidianakis +// SPDX-License-Identifier: GPL-2.0-or-later + +#[cfg(unix)] +use std::os::unix::fs::symlink as symlink_file; +#[cfg(windows)] +use std::os::windows::fs::symlink_file; +use std::{env, fs::remove_file, io::Result, path::Path}; + +fn main() -> Result<()> { + let file =3D if let Ok(root) =3D env::var("MESON_BUILD_ROOT") { + format!("{root}/rust/hw/char/pl011/bindings.inc.rs") + } else { + // Placing bindings.inc.rs in the source directory is supported + // but not documented or encouraged. + format!("{}/src/bindings.inc.rs", env!("CARGO_MANIFEST_DIR")) + }; + + let file =3D Path::new(&file); + if !Path::new(&file).exists() { + panic!(concat!( + "\n", + " No generated C bindings found! Maybe you wanted one of\n", + " `make clippy`, `make rustfmt`, `make rustdoc`?\n", + "\n", + " For other uses of `cargo`, start a subshell with\n", + " `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n= ", + " the top of the build tree." + )); + } + + let out_dir =3D env::var("OUT_DIR").unwrap(); + let dest_path =3D format!("{out_dir}/bindings.inc.rs"); + let dest_path =3D Path::new(&dest_path); + if dest_path.symlink_metadata().is_ok() { + remove_file(dest_path)?; + } + symlink_file(file, dest_path)?; + + println!("cargo:rerun-if-changed=3Dbuild.rs"); + Ok(()) +} diff --git a/rust/hw/char/pl011/meson.build b/rust/hw/char/pl011/meson.build index 7d90f2aad6..a14993f692 100644 --- a/rust/hw/char/pl011/meson.build +++ b/rust/hw/char/pl011/meson.build @@ -1,6 +1,30 @@ +# TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. +# +# Rust bindings generation with `bindgen` might fail in some cases where t= he +# 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 +_libpl011_bindings_inc_rs =3D rust.bindgen( + input: 'wrapper.h', + dependencies: common_ss.all_dependencies(), + output: 'bindings.inc.rs', + include_directories: bindings_incdir, + bindgen_version: ['>=3D0.60.0'], + args: bindgen_args_common, +) + _libpl011_rs =3D static_library( 'pl011', - files('src/lib.rs'), + structured_sources( + [ + 'src/lib.rs', + 'src/bindings.rs', + 'src/device.rs', + 'src/registers.rs', + ], + {'.' : _libpl011_bindings_inc_rs}, + ), override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], rust_abi: 'rust', dependencies: [ @@ -11,7 +35,6 @@ _libpl011_rs =3D static_library( util_rs, migration_rs, bql_rs, - qemu_api, qemu_macros, qom_rs, chardev_rs, diff --git a/rust/hw/char/pl011/src/bindings.rs b/rust/hw/char/pl011/src/bi= ndings.rs new file mode 100644 index 0000000000..bd5ea840cb --- /dev/null +++ b/rust/hw/char/pl011/src/bindings.rs @@ -0,0 +1,27 @@ +// 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. + +#[cfg(MESON)] +include!("bindings.inc.rs"); + +#[cfg(not(MESON))] +include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs")); diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/devi= ce.rs index caaa05c04c..c9f6087540 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -137,7 +137,7 @@ pub struct PL011State { // structs, so the size of the Rust version must not be any larger // than the size of the C one. If this assert triggers you need to // expand the padding_for_rust[] array in the C PL011State struct. -static_assert!(size_of::() <=3D size_of::()); +static_assert!(size_of::() <=3D size_of::()); =20 qom_isa!(PL011State : SysBusDevice, DeviceState, Object); =20 diff --git a/rust/hw/char/pl011/src/lib.rs b/rust/hw/char/pl011/src/lib.rs index 2b70d2ff56..0c19b708c0 100644 --- a/rust/hw/char/pl011/src/lib.rs +++ b/rust/hw/char/pl011/src/lib.rs @@ -12,6 +12,7 @@ //! See [`PL011State`](crate::device::PL011State) for the device model typ= e and //! the [`registers`] module for register types. =20 +mod bindings; mod device; mod registers; =20 --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217402; cv=none; d=zohomail.com; s=zohoarc; b=jFqo1t7kJBrgMQgwxV7FNVme0XG2Y8UAnB+1IUbu/UCiRkvrZXBVbG38wPzcmRRhh0CsQsbs202H314u7K7rEgZ5Kh5okq0i9vUhNcDG/EufWC0FYlQe/q10MsUqjU/0SjC6l8puorQbZgSdkB7TfNYIVhvtAQeaDmVPdMlLCgQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217402; h=Content-Type: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=oNrvI+p3McY8X111OSDm1+EW8OQspelVbYQV6KmwaGo=; b=bnKJ5xXWQzBaE2Zrd4uU3gNCYk4aZHudMccRwL3Izj2DgwnUnzbtfsF7Tnc+BhXeGghc/8rasAqErmq/FZ38pvcIFJcR6TEG2aO28o/SrxwLQp3+VWteXvz7YxEdIle+N5pi9FGjjBNkvp0op4M0JnqDNxQGiezOY0Sm87YrbvE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217402592661.125628835257; Tue, 26 Aug 2025 07:10:02 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquKo-00073D-10; Tue, 26 Aug 2025 10:07:38 -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 1uquKR-0006mg-FP for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:07:18 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquJy-0007DA-S0 for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:56 -0400 Received: from mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-59-Av252KL6PkOBzuxOqVH2Aw-1; Tue, 26 Aug 2025 10:06:32 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 730291955F26; Tue, 26 Aug 2025 14:06:31 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 94CDE1800446; Tue, 26 Aug 2025 14:06:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217199; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oNrvI+p3McY8X111OSDm1+EW8OQspelVbYQV6KmwaGo=; b=LbZ9OcqAHBT7dAxeHH3ytoag4FoCZFKortnWmgCCIA3vx3fa7MSnMmFX583sio5ICgA4ov LtEhe4caCvMM92de4/iH2e6LpfQ02qFmWtJrbwiFbLwMwC+w5nNhxeyGrNYYerwFwFX8ir epzfaDvBVMM28MZsV0yZHRSZuk2VIWg= X-MC-Unique: Av252KL6PkOBzuxOqVH2Aw-1 X-Mimecast-MFC-AGG-ID: Av252KL6PkOBzuxOqVH2Aw_1756217191 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 17/18] rust: repurpose qemu_api -> tests Date: Tue, 26 Aug 2025 18:04:45 +0400 Message-ID: <20250826140449.4190022-18-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 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=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_PASS=-0.001, T_SPF_TEMPERROR=0.01 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1756217404908124100 From: Marc-Andr=C3=A9 Lureau The crate purpose is only to provide integration tests at this point, that can't easily be moved to a specific crate. It's also often a good practice to have a single integration test crate (see for ex https://github.com/rust-lang/cargo/issues/4867) Drop README.md, use docs/devel/rust.rst instead. Signed-off-by: Marc-Andr=C3=A9 Lureau --- MAINTAINERS | 2 +- rust/qemu-api/wrapper.h | 53 ----------- rust/Cargo.lock | 36 ++++---- rust/Cargo.toml | 2 +- rust/meson.build | 2 +- rust/qemu-api/.gitignore | 2 - rust/qemu-api/README.md | 19 ---- rust/qemu-api/build.rs | 43 --------- rust/qemu-api/meson.build | 87 ------------------- rust/qemu-api/src/bindings.rs | 33 ------- rust/qemu-api/src/lib.rs | 14 --- rust/qemu-api/src/prelude.rs | 5 -- rust/{qemu-api =3D> tests}/Cargo.toml | 11 +-- rust/tests/meson.build | 14 +++ .../tests/vmstate_tests.rs | 0 15 files changed, 38 insertions(+), 285 deletions(-) delete mode 100644 rust/qemu-api/wrapper.h delete mode 100644 rust/qemu-api/.gitignore delete mode 100644 rust/qemu-api/README.md delete mode 100644 rust/qemu-api/build.rs delete mode 100644 rust/qemu-api/meson.build delete mode 100644 rust/qemu-api/src/bindings.rs delete mode 100644 rust/qemu-api/src/lib.rs delete mode 100644 rust/qemu-api/src/prelude.rs rename rust/{qemu-api =3D> tests}/Cargo.toml (74%) create mode 100644 rust/tests/meson.build rename rust/{qemu-api =3D> tests}/tests/vmstate_tests.rs (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 62790c7b5d..d978e41e08 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3515,11 +3515,11 @@ F: rust/chardev/ F: rust/common/ F: rust/hw/core/ F: rust/migration/ -F: rust/qemu-api F: rust/qemu-macros/ F: rust/qom/ F: rust/rustfmt.toml F: rust/system/ +F: rust/tests/ F: rust/util/ F: scripts/get-wraps-from-cargo-registry.py =20 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 - * - * Permission is hereby granted, free of charge, to any person obtaining a= copy - * of this software and associated documentation files (the "Software"), t= o deal - * in the Software without restriction, including without limitation the r= ights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll - * 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 OT= HER - * 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` applicat= ion - * 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 sym= bols - * 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" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 1a9a36ecec..4c15579d1a 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -184,24 +184,6 @@ dependencies =3D [ "unicode-ident", ] =20 -[[package]] -name =3D "qemu_api" -version =3D "0.1.0" -dependencies =3D [ - "anyhow", - "bql", - "chardev", - "common", - "foreign", - "hwcore", - "libc", - "migration", - "qemu_macros", - "qom", - "system", - "util", -] - [[package]] name =3D "qemu_macros" version =3D "0.1.0" @@ -252,6 +234,24 @@ dependencies =3D [ "util", ] =20 +[[package]] +name =3D "tests" +version =3D "0.1.0" +dependencies =3D [ + "anyhow", + "bql", + "chardev", + "common", + "foreign", + "hwcore", + "libc", + "migration", + "qemu_macros", + "qom", + "system", + "util", +] + [[package]] name =3D "unicode-ident" version =3D "1.0.12" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 1acee9e7cb..c253c0e2df 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -6,13 +6,13 @@ members =3D [ "common", "migration", "qemu-macros", - "qemu-api", "qom", "system", "hw/core", "hw/char/pl011", "hw/timer/hpet", "util", + "tests", ] =20 [workspace.package] diff --git a/rust/meson.build b/rust/meson.build index 9f6a0b161d..32d569f871 100644 --- a/rust/meson.build +++ b/rust/meson.build @@ -32,7 +32,7 @@ subdir('qom') subdir('system') subdir('chardev') subdir('hw/core') -subdir('qemu-api') +subdir('tests') =20 subdir('hw') =20 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/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 100644 index 29d0945625..0000000000 --- a/rust/qemu-api/build.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2024, Linaro Limited -// Author(s): Manos Pitsidianakis -// SPDX-License-Identifier: GPL-2.0-or-later - -#[cfg(unix)] -use std::os::unix::fs::symlink as symlink_file; -#[cfg(windows)] -use std::os::windows::fs::symlink_file; -use std::{env, fs::remove_file, io::Result, path::Path}; - -fn main() -> Result<()> { - let file =3D if let Ok(root) =3D env::var("MESON_BUILD_ROOT") { - format!("{root}/rust/qemu-api/bindings.inc.rs") - } else { - // Placing bindings.inc.rs in the source directory is supported - // but not documented or encouraged. - format!("{}/src/bindings.inc.rs", env!("CARGO_MANIFEST_DIR")) - }; - - let file =3D Path::new(&file); - if !Path::new(&file).exists() { - panic!(concat!( - "\n", - " No generated C bindings found! Maybe you wanted one of\n", - " `make clippy`, `make rustfmt`, `make rustdoc`?\n", - "\n", - " For other uses of `cargo`, start a subshell with\n", - " `pyvenv/bin/meson devenv`, or point MESON_BUILD_ROOT to\n= ", - " the top of the build tree." - )); - } - - let out_dir =3D env::var("OUT_DIR").unwrap(); - let dest_path =3D format!("{out_dir}/bindings.inc.rs"); - let dest_path =3D Path::new(&dest_path); - if dest_path.symlink_metadata().is_ok() { - remove_file(dest_path)?; - } - symlink_file(file, dest_path)?; - - println!("cargo:rerun-if-changed=3Dbuild.rs"); - Ok(()) -} diff --git a/rust/qemu-api/meson.build b/rust/qemu-api/meson.build deleted file mode 100644 index 02318950ff..0000000000 --- a/rust/qemu-api/meson.build +++ /dev/null @@ -1,87 +0,0 @@ -_qemu_api_cfg =3D run_command(rustc_args, - '--config-headers', config_host_h, '--features', files('Cargo.toml'), - capture: true, check: true).stdout().strip().splitlines() - -c_enums =3D [ - 'MemoryDeviceInfoKind', -] -_qemu_api_bindgen_args =3D [] -foreach enum : c_enums - _qemu_api_bindgen_args +=3D ['--rustified-enum', enum] -endforeach - -blocked_type =3D [ - 'Chardev', - 'Error', - 'MemTxAttrs', - 'MemoryRegion', - 'ObjectClass', - 'VMStateDescription', - 'device_endian', -] -foreach type: blocked_type - _qemu_api_bindgen_args +=3D ['--blocklist-type', type] -endforeach - -# TODO: Remove this comment when the clang/libclang mismatch issue is solv= ed. -# -# Rust bindings generation with `bindgen` might fail in some cases where t= he -# 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 =3D rust.bindgen( - input: 'wrapper.h', - dependencies: common_ss.all_dependencies(), - output: 'bindings.inc.rs', - include_directories: bindings_incdir, - bindgen_version: ['>=3D0.60.0'], - args: bindgen_args_common + _qemu_api_bindgen_args, - ) - -_qemu_api_rs =3D static_library( - 'qemu_api', - structured_sources( - [ - 'src/lib.rs', - 'src/bindings.rs', - 'src/prelude.rs', - ], - {'.' : _qemu_api_bindings_inc_rs}, - ), - override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], - rust_abi: 'rust', - rust_args: _qemu_api_cfg, - dependencies: [anyhow_rs, common_rs, chardev_rs, foreign_rs, libc_rs, qe= mu_macros, qemuutil_rs, util_rs, migration_rs, bql_rs, qom_rs, system_rs, h= wcore_rs, - qom, hwcore, chardev, migration], -) - -rust.test('rust-qemu-api-tests', _qemu_api_rs, - suite: ['unit', 'rust']) - -qemu_api =3D declare_dependency(link_with: [_qemu_api_rs], - dependencies: [qemu_macros, qom, hwcore, chardev, migration]) - -# Doctests are essentially integration tests, so they need the same depend= encies. -# Note that running them requires the object files for C code, so place th= em -# in a separate suite that is run by the "build" CI jobs rather than "chec= k". -rust.doctest('rust-qemu-api-doctests', - _qemu_api_rs, - protocol: 'rust', - dependencies: qemu_api, - suite: ['doc', 'rust']) - -test('rust-qemu-api-integration', - executable( - 'rust-qemu-api-integration', - files('tests/vmstate_tests.rs'), - override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], - rust_args: ['--test'], - install: false, - dependencies: [bql_rs, common_rs, util_rs, migration_rs, qom_rs, q= emu_api]), - 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 50fb2fa99d..0000000000 --- a/rust/qemu-api/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2024, Linaro Limited -// Author(s): Manos Pitsidianakis -// SPDX-License-Identifier: GPL-2.0-or-later - -#![cfg_attr(not(MESON), doc =3D 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; 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 -// SPDX-License-Identifier: GPL-2.0-or-later - -//! Commonly used traits and types for QEMU. diff --git a/rust/qemu-api/Cargo.toml b/rust/tests/Cargo.toml similarity index 74% rename from rust/qemu-api/Cargo.toml rename to rust/tests/Cargo.toml index b6744f0286..104e7868cb 100644 --- a/rust/qemu-api/Cargo.toml +++ b/rust/tests/Cargo.toml @@ -1,12 +1,11 @@ [package] -name =3D "qemu_api" +name =3D "tests" version =3D "0.1.0" -authors =3D ["Manos Pitsidianakis "] -description =3D "Rust bindings for QEMU" -readme =3D "README.md" +description =3D "Rust integration tests for QEMU" resolver =3D "2" publish =3D false =20 +authors.workspace =3D true edition.workspace =3D true homepage.workspace =3D true license.workspace =3D true @@ -27,9 +26,5 @@ anyhow =3D "~1.0" libc =3D "0.2.162" foreign =3D "~0.3.1" =20 -[features] -default =3D ["debug_cell"] -debug_cell =3D [] - [lints] workspace =3D true diff --git a/rust/tests/meson.build b/rust/tests/meson.build new file mode 100644 index 0000000000..00688c66fb --- /dev/null +++ b/rust/tests/meson.build @@ -0,0 +1,14 @@ +test('rust-integration', + executable( + 'rust-integration', + files('tests/vmstate_tests.rs'), + override_options: ['rust_std=3D2021', 'build.rust_std=3D2021'], + rust_args: ['--test'], + install: false, + dependencies: [bql_rs, common_rs, util_rs, migration_rs, qom_rs]), + args: [ + '--test', '--test-threads', '1', + '--format', 'pretty', + ], + protocol: 'rust', + suite: ['unit', 'rust']) diff --git a/rust/qemu-api/tests/vmstate_tests.rs b/rust/tests/tests/vmstat= e_tests.rs similarity index 100% rename from rust/qemu-api/tests/vmstate_tests.rs rename to rust/tests/tests/vmstate_tests.rs --=20 2.50.1 From nobody Sun Sep 28 15:28:18 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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=quarantine dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1756217513; cv=none; d=zohomail.com; s=zohoarc; b=Kdbn0oB/W3EV3sdrRX4Z+F4hPTieDPZas4gD8pZURAm4U00GZM5EuDCupTKh0mtl0E/l4IDeNav9KNAV9SimCFaAKNawESL9ADyg/VGGXcGPOJnRO2i02UOm58lr76b1gx+ZAteQiQeJsDKVdWrT9/XSNCpTeUai989Xv/LfiE0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756217513; h=Content-Type: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=wTw9sLe7ru4Kf+wSu6PiTS6mpdXGTr9mFOwfKJLy9zs=; b=ba3gDWZevUNt1dQZagJve7I3LklW2WM/Mg5DYfN9GI1NZ2DO6gJZOMpu62DiQPlnmm7ZKI2OiYCvLVg0fua4iBQqi0sLZ5rw5/dvo2vHtGqLwT6isVt3VNE/5CMidnWfLeUiQEjveeNTZ9WTz5QptLCP0N9tMlbjJhQm60mRLko= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756217513703575.1761433409248; Tue, 26 Aug 2025 07:11:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uquKs-0007DD-DK; Tue, 26 Aug 2025 10:07:42 -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 1uquKW-0006uP-Bw for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:07:20 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uquJx-0007DC-3A for qemu-devel@nongnu.org; Tue, 26 Aug 2025 10:06:58 -0400 Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-288-Q_dOJmA2PEyYIBMiU_3_4g-1; Tue, 26 Aug 2025 10:06:38 -0400 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0072019560A2; Tue, 26 Aug 2025 14:06:37 +0000 (UTC) Received: from localhost (unknown [10.45.242.16]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9F14A1800447; Tue, 26 Aug 2025 14:06:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1756217199; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wTw9sLe7ru4Kf+wSu6PiTS6mpdXGTr9mFOwfKJLy9zs=; b=gkcyX9Zbi91AIX4AqIqJpx+kyX3qW9us1UqZh5F3h5oig226JZ1wlE2wD7g2nV7g+iPKH4 vszYZMsa8NbyS5L/LZddlavoY5zWc58B36rRsVMKmGpwg0c0fFOS5zA1o1SuPvRZYGPctM QQL6Pn5rHktPnx4Qr9Cj2hsjpCvLSHc= X-MC-Unique: Q_dOJmA2PEyYIBMiU_3_4g-1 X-Mimecast-MFC-AGG-ID: Q_dOJmA2PEyYIBMiU_3_4g_1756217197 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , qemu-rust@nongnu.org, =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Manos Pitsidianakis Subject: [RFC 18/18] docs: update rust.rst Date: Tue, 26 Aug 2025 18:04:46 +0400 Message-ID: <20250826140449.4190022-19-marcandre.lureau@redhat.com> In-Reply-To: <20250826140449.4190022-1-marcandre.lureau@redhat.com> References: <20250826140449.4190022-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 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=170.10.133.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, T_SPF_HELO_TEMPERROR=0.01, T_SPF_TEMPERROR=0.01 autolearn=unavailable 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 @redhat.com) X-ZM-MESSAGEID: 1756217518049124100 From: Marc-Andr=C3=A9 Lureau --- docs/devel/rust.rst | 51 ++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/docs/devel/rust.rst b/docs/devel/rust.rst index b6737536c6..e7967ff7be 100644 --- a/docs/devel/rust.rst +++ b/docs/devel/rust.rst @@ -115,11 +115,14 @@ anymore. Writing Rust code in QEMU ------------------------- =20 -QEMU includes four crates: +QEMU includes several crates: =20 -* ``qemu_api`` for bindings to C code and useful functionality +* ``common`` provides Rust-only utilities =20 -* ``qemu_api_macros`` defines several procedural macros that are useful wh= en +* ``bql``, ``chardev``, ``hw/core``, ``migration``, ``qom``, ``system``, + ``util`` for bindings to respective QEMU C library APIs + +* ``qemu_macros`` defines several procedural macros that are useful when writing C code =20 * ``pl011`` (under ``rust/hw/char/pl011``) and ``hpet`` (under ``rust/hw/t= imer/hpet``) @@ -136,7 +139,7 @@ This section explains how to work with them. Status '''''' =20 -Modules of ``qemu_api`` can be defined as: +The stability of the modules can be defined as: =20 - *complete*: ready for use in new devices; if applicable, the API support= s the full functionality available in C @@ -152,26 +155,26 @@ Modules of ``qemu_api`` can be defined as: =20 The status of the modules is as follows: =20 -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D -module status -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D -``assertions`` stable -``bitops`` complete -``callbacks`` complete -``cell`` stable -``errno`` complete -``error`` stable -``irq`` complete -``log`` proof of concept -``memory`` stable -``module`` complete -``qdev`` stable -``qom`` stable -``sysbus`` stable -``timer`` stable -``vmstate`` proof of concept -``zeroable`` stable -=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +module status +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +``bql::cell`` stable +``common::assertions`` stable +``common::bitops`` complete +``common::callbacks`` complete +``common::zeroable`` stable +``hwcore::irq`` complete +``hwcore::qdev`` stable +``hwcore::sysbus`` stable +``migration::vmstate`` proof of concept +``qom`` stable +``system::memory`` stable +``util::errno`` complete +``util::error`` stable +``util::log`` proof of concept +``util::module`` complete +``util::timer`` stable +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 .. note:: API stability is not a promise, if anything because the C APIs are not a= stable --=20 2.50.1