or a macro) where it can be documented and tested. If needed, include
toy versions of the code in the documentation.
+FFI Binding Generation
+''''''''''''''''''''''
+
+QEMU's Rust integration uses multiple ``*-sys`` crates that contain raw FFI
+bindings to different QEMU subsystems. These crates mirror the dependency
+structure that meson.build uses for C code, and which is reflected in
+``static_library()`` declarations. For example:
+
+* util-sys: Basic utilities (no dependencies)
+* qom-sys: QEMU Object Model (depends on util-sys)
+* chardev-sys: Character devices (depends on qom-sys, util-sys)
+* hwcore-sys: Hardware core (depends on qom-sys, util-sys)
+* migration-sys: Migration (depends on util-sys)
+* system-sys: System-level APIs (depends on all others)
+
+Having multiple crates avoids massive rebuilds of all Rust code when C headers
+are changed. On the other hand, bindgen is not aware of how headers are split
+across crates, and therefore it would generate declarations for dependencies
+again. These duplicate declarations are not only large, they create distinct
+types and therefore they are incompatible with each other.
+
+Bindgen Configuration
+~~~~~~~~~~~~~~~~~~~~~
+
+Bindgen options such as symbol blocklists or how to configure enums can be
+defined in each crate's ``Cargo.toml`` via a ``[package.metadata.bindgen]`` section.
+For example::
+
+ [package.metadata.bindgen]
+ header = "wrapper.h" # Main header file for this crate
+ rustified-enum = ["QEMUClockType"] # Enums to generate as Rust enums
+ bitfield-enum = ["VMStateFlags"] # Enums to treat as bitfields
+ blocklist-function = [ # Functions to exclude
+ "vmstate_register_ram",
+ "vmstate_unregister_ram"
+ ]
+ additional-files = [ # Extra files to allowlist
+ "include/system/memory_ldst.*"
+ ]
+
+All bindgen options are supported in the metadata section. The complete list
+can be found in ``rust/bindings/generate_bindgen_args.py``.
+
+Dependency Management
+~~~~~~~~~~~~~~~~~~~~~
+
+By examining the dependency chain before bindgen creates the code for
+the ``*-sys`` crates, the build system ensures that header files included in
+one crate are blocked from appearing in dependent crates, thus avoiding
+duplicate definitions. Dependent crates can import the definition via
+"use" statements.
+
+This dependency-aware binding generation is handled automatically by
+``rust/bindings/generate_bindgen_args.py``, which processes the Cargo.toml
+files in dependency order and generates appropriate ``--allowlist-file`` and
+``--blocklist-file`` arguments for bindgen.
+
Writing procedural macros
'''''''''''''''''''''''''
'--with-derive-default',
'--no-layout-tests',
'--no-prepend-enum-name',
- '--allowlist-file', meson.project_source_root() + '/include/.*',
- '--allowlist-file', meson.project_build_root() + '/.*',
'--blocklist-file', glib_pc.get_variable('includedir') + '/glib-2.0/.*',
+ '--blocklist-file', meson.project_source_root() + '/include/qemu/typedefs.h',
'--blocklist-type', '.*_([a-z]*autoptr)$',
]
if not rustfmt.found()
version = "0.1.0"
dependencies = [
"glib-sys",
+ "util-sys",
]
[[package]]
version = "0.1.0"
dependencies = [
"bql",
+ "chardev-sys",
"common",
"glib-sys",
"migration",
"util",
]
+[[package]]
+name = "chardev-sys"
+version = "0.1.0"
+dependencies = [
+ "common",
+ "glib-sys",
+ "qom-sys",
+ "util-sys",
+]
+
[[package]]
name = "common"
version = "0.1.0"
"chardev",
"common",
"glib-sys",
+ "hwcore-sys",
"migration",
"qemu_macros",
"qom",
"util",
]
+[[package]]
+name = "hwcore-sys"
+version = "0.1.0"
+dependencies = [
+ "chardev-sys",
+ "common",
+ "glib-sys",
+ "migration-sys",
+ "qom-sys",
+ "system-sys",
+ "util-sys",
+]
+
[[package]]
name = "indexmap"
version = "2.11.4"
"bql",
"common",
"glib-sys",
+ "migration-sys",
"qemu_macros",
"util",
]
+[[package]]
+name = "migration-sys"
+version = "0.1.0"
+dependencies = [
+ "common",
+ "glib-sys",
+ "util-sys",
+]
+
[[package]]
name = "pkg-config"
version = "0.3.32"
"glib-sys",
"migration",
"qemu_macros",
+ "qom-sys",
"util",
]
+[[package]]
+name = "qom-sys"
+version = "0.1.0"
+dependencies = [
+ "glib-sys",
+ "util-sys",
+]
+
[[package]]
name = "quote"
version = "1.0.36"
checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd"
dependencies = [
"serde_core",
+ "serde_derive",
]
[[package]]
name = "system"
version = "0.1.0"
dependencies = [
+ "bql",
"common",
"glib-sys",
+ "migration",
"qom",
+ "system-sys",
"util",
]
"version-compare",
]
+[[package]]
+name = "system-sys"
+version = "0.1.0"
+dependencies = [
+ "common",
+ "glib-sys",
+ "migration-sys",
+ "qom-sys",
+ "util-sys",
+]
+
[[package]]
name = "target-lexicon"
version = "0.13.2"
"foreign",
"glib-sys",
"libc",
+ "util-sys",
+]
+
+[[package]]
+name = "util-sys"
+version = "0.1.0"
+dependencies = [
+ "glib-sys",
]
[[package]]
fn main() -> Result<()> {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
- let file = if let Ok(root) = env::var("MESON_BUILD_ROOT") {
- let sub = get_rust_subdir(manifest_dir).unwrap();
- format!("{root}/{sub}/bindings.inc.rs")
- } else {
- // Placing bindings.inc.rs in the source directory is supported
- // but not documented or encouraged.
- format!("{manifest_dir}/src/bindings.inc.rs")
- };
+ let root = env::var("MESON_BUILD_ROOT").expect(concat!(
+ "\n",
+ " MESON_BUILD_ROOT not 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 sub = get_rust_subdir(manifest_dir).unwrap();
+ let file = format!("{root}/{sub}/bindings.inc.rs");
let file = Path::new(&file);
- if !Path::new(&file).exists() {
+
+ if !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."
+ " No generated C bindings found! Run `make` first; or maybe you\n",
+ " wanted one of `make clippy`, `make rustfmt`, `make rustdoc`?\n",
));
}
--- /dev/null
+[package]
+name = "chardev-sys"
+version = "0.1.0"
+description = "Rust sys bindings for QEMU/chardev"
+publish = false
+
+authors.workspace = true
+edition.workspace = true
+homepage.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+glib-sys = { workspace = true }
+common = { path = "../../common" }
+qom-sys = { path = "../qom-sys" }
+util-sys = { path = "../util-sys" }
+
+[lints]
+workspace = true
+
+[package.metadata.bindgen]
+header = "wrapper.h"
+rustified-enum = ["QEMUChrEvent"]
--- /dev/null
+../build.rs
\ No newline at end of file
)]
use common::Zeroable;
-use glib_sys::{
- gboolean, guint, GArray, GHashTable, GHashTableIter, GIOCondition, GMainContext, GPollFD,
- GPtrArray, GSList, GSource, GSourceFunc,
-};
+use glib_sys::{gboolean, guint, GIOCondition, GMainContext, GSource, GSourceFunc};
+use qom_sys::{Object, ObjectClass};
+use util_sys::{Error, IOCanReadHandler, IOReadHandler, QemuOpts};
#[cfg(MESON)]
include!("bindings.inc.rs");
--- /dev/null
+_bindgen_chardev_rs = rust.bindgen(
+ args: bindgen_args_common + bindgen_args_data['chardev-sys'].split(),
+ kwargs: bindgen_kwargs)
+_chardev_sys_rs = static_library(
+ 'chardev_sys',
+ structured_sources(['lib.rs', _bindgen_chardev_rs]),
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ dependencies: [glib_sys_rs, common_rs, qom_sys_rs, util_sys_rs],
+)
+
+chardev_sys_rs = declare_dependency(link_with: [_chardev_sys_rs])
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * This header file is meant to be used as input to the `bindgen` application
+ * in order to generate C FFI compatible Rust bindings.
+ */
+
+#include "qemu/osdep.h"
+
+#include "chardev/char.h"
+#include "chardev/char-fe.h"
+#include "chardev/char-serial.h"
--- /dev/null
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+"""
+Generate bindgen arguments from Cargo.toml metadata for QEMU's Rust FFI bindings.
+
+Author: Paolo Bonzini <pbonzini@redhat.com>
+
+Copyright (C) 2025 Red Hat, Inc.
+
+This script processes Cargo.toml file for QEMU's bindings crates (util-sys,
+chardev-sys, qom-sys, etc.); it generates bindgen command lines that allow
+easy customization and that export the right headers in each bindings crate.
+
+For detailed information, see docs/devel/rust.rst.
+"""
+
+import os
+import re
+import sys
+import argparse
+from pathlib import Path
+from dataclasses import dataclass
+from typing import Iterable, List, Dict, Any
+
+try:
+ import tomllib
+except ImportError:
+ import tomli as tomllib # type: ignore
+
+INCLUDE_RE = re.compile(r'^#include\s+"([^"]+)"')
+OPTIONS = [
+ "bitfield-enum",
+ "newtype-enum",
+ "newtype-global-enum",
+ "rustified-enum",
+ "rustified-non-exhaustive-enum",
+ "constified-enum",
+ "constified-enum-module",
+ "normal-alias",
+ "new-type-alias",
+ "new-type-alias-deref",
+ "bindgen-wrapper-union",
+ "manually-drop-union",
+ "blocklist-type",
+ "blocklist-function",
+ "blocklist-item",
+ "blocklist-file",
+ "blocklist-var",
+ "opaque-type",
+ "no-partialeq",
+ "no-copy",
+ "no-debug",
+ "no-default",
+ "no-hash",
+ "must-use-type",
+ "with-derive-custom",
+ "with-derive-custom-struct",
+ "with-derive-custom-enum",
+ "with-derive-custom-union",
+ "with-attribute-custom",
+ "with-attribute-custom-struct",
+ "with-attribute-custom-enum",
+ "with-attribute-custom-union",
+]
+
+
+@dataclass
+class BindgenInfo:
+ cmd_args: List[str]
+ inputs: List[str]
+
+
+def extract_includes(lines: Iterable[str]) -> List[str]:
+ """Extract #include directives from a file."""
+ includes: List[str] = []
+ for line in lines:
+ match = INCLUDE_RE.match(line.strip())
+ if match:
+ includes.append(match.group(1))
+ return includes
+
+
+def build_bindgen_args(metadata: Dict[str, Any]) -> List[str]:
+ """Build command line arguments from [package.metadata.bindgen]."""
+ args: List[str] = []
+ for key, values in metadata.items():
+ if key in OPTIONS:
+ flag = f"--{key}"
+ assert isinstance(values, list)
+ for value in values:
+ args.append(flag)
+ args.append(value)
+
+ return args
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(
+ description="Generate bindgen arguments from Cargo.toml metadata"
+ )
+ parser.add_argument(
+ "directories", nargs="+", help="Directories containing Cargo.toml files"
+ )
+ parser.add_argument(
+ "-I",
+ "--include-root",
+ default=None,
+ help="Base path for --allowlist-file/--blocklist-file",
+ )
+ parser.add_argument("--source-dir", default=os.getcwd(), help="Source directory")
+ parser.add_argument("-o", "--output", required=True, help="Output file")
+ parser.add_argument("--dep-file", help="Dependency file to write")
+ args = parser.parse_args()
+
+ prev_allowlist_files: Dict[str, object] = {}
+ bindgen_infos: Dict[str, BindgenInfo] = {}
+
+ os.chdir(args.source_dir)
+ include_root = args.include_root or args.source_dir
+ for directory in args.directories:
+ cargo_path = Path(directory) / "Cargo.toml"
+ inputs = [str(Path(args.source_dir) / cargo_path)]
+
+ with open(cargo_path, "rb") as f:
+ cargo_toml = tomllib.load(f)
+
+ metadata = cargo_toml.get("package", {}).get("metadata", {}).get("bindgen", {})
+ input_file = Path(directory) / metadata["header"]
+ inputs.append(str(Path(args.source_dir) / input_file))
+
+ cmd_args = build_bindgen_args(metadata)
+
+ # Each include file is allowed for this file and blocked in the
+ # next ones
+ for blocklist_path in prev_allowlist_files:
+ cmd_args.extend(["--blocklist-file", blocklist_path])
+ with open(input_file, "r", encoding="utf-8", errors="ignore") as f:
+ includes = extract_includes(f)
+ for allowlist_file in includes + metadata.get("additional-files", []):
+ allowlist_path = Path(include_root) / allowlist_file
+ cmd_args.extend(["--allowlist-file", str(allowlist_path)])
+ prev_allowlist_files.setdefault(str(allowlist_path), True)
+
+ bindgen_infos[directory] = BindgenInfo(cmd_args=cmd_args, inputs=inputs)
+
+ # now write the output
+ with open(args.output, "w") as f:
+ for directory, info in bindgen_infos.items():
+ args_sh = " ".join(info.cmd_args)
+ f.write(f"{directory}={args_sh}\n")
+
+ if args.dep_file:
+ with open(args.dep_file, "w") as f:
+ deps: List[str] = []
+ for info in bindgen_infos.values():
+ deps += info.inputs
+ f.write(f"{os.path.basename(args.output)}: {' '.join(deps)}\n")
+
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main())
--- /dev/null
+[package]
+name = "hwcore-sys"
+version = "0.1.0"
+description = "Rust sys bindings for QEMU/hwcore"
+publish = false
+
+authors.workspace = true
+edition.workspace = true
+homepage.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+glib-sys = { workspace = true }
+common = { path = "../../common" }
+chardev-sys = { path = "../chardev-sys" }
+qom-sys = { path = "../qom-sys" }
+migration-sys = { path = "../migration-sys" }
+util-sys = { path = "../util-sys" }
+system-sys = { path = "../system-sys" }
+
+[lints]
+workspace = true
+
+[package.metadata.bindgen]
+header = "wrapper.h"
+rustified-enum = ["DeviceCategory", "GpioPolarity", "MachineInitPhase", "ResetType"]
+bitfield-enum = ["ClockEvent"]
--- /dev/null
+../build.rs
\ No newline at end of file
clippy::too_many_arguments
)]
-use chardev::bindings::Chardev;
+use chardev_sys::Chardev;
use common::Zeroable;
-use glib_sys::{GHashTable, GHashTableIter, GList, GPtrArray, GSList};
-use migration::bindings::VMStateDescription;
-use qom::bindings::ObjectClass;
-use system::bindings::MemoryRegion;
-use util::bindings::Error;
+use glib_sys::GSList;
+use migration_sys::VMStateDescription;
+use qom_sys::{
+ InterfaceClass, Object, ObjectClass, ObjectProperty, ObjectPropertyAccessor,
+ ObjectPropertyRelease,
+};
+use util_sys::{Error, QDict, QList};
#[cfg(MESON)]
include!("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 {}
--- /dev/null
+_bindgen_hwcore_rs = rust.bindgen(
+ args: bindgen_args_common + bindgen_args_data['hwcore-sys'].split(),
+ kwargs: bindgen_kwargs)
+_hwcore_sys_rs = static_library(
+ 'hwcore_sys',
+ structured_sources(['lib.rs', _bindgen_hwcore_rs]),
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ dependencies: [common_rs, glib_sys_rs, qom_sys_rs, util_sys_rs, migration_sys_rs, chardev_sys_rs],
+)
+
+hwcore_sys_rs = declare_dependency(link_with: [_hwcore_sys_rs])
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * This header file is meant to be used as input to the `bindgen` application
+ * in order to generate C FFI compatible Rust bindings.
+ */
+
+/*
+ * We block include/qemu/typedefs.h from bindgen, add here symbols
+ * that are needed as opaque types by other functions.
+ */
+typedef struct Clock Clock;
+typedef struct DeviceState DeviceState;
+typedef struct IRQState *qemu_irq;
+typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
+
+/* Once bindings exist, these could move to a different *-sys crate. */
+typedef struct BlockBackend BlockBackend;
+typedef struct Monitor Monitor;
+typedef struct NetClientState NetClientState;
+
+#include "qemu/osdep.h"
+
+#include "hw/core/clock.h"
+#include "hw/core/irq.h"
+#include "hw/core/qdev-clock.h"
+#include "hw/core/qdev.h"
+#include "hw/core/qdev-properties-system.h"
+#include "hw/core/qdev-properties.h"
+#include "hw/core/resettable.h"
--- /dev/null
+# Generate bindgen arguments from Cargo.toml metadata
+# Sort these in dependency order, same as the subdir()
+# invocations below.
+bindgen_dirs = [
+ 'util-sys',
+ 'migration-sys',
+ 'qom-sys',
+ 'chardev-sys',
+ 'hwcore-sys',
+ 'system-sys',
+]
+bindgen_args_file = configure_file(
+ command: [files('generate_bindgen_args.py'),
+ '-I', meson.project_source_root() / 'include',
+ '--source-dir', meson.current_source_dir(),
+ '-o', '@OUTPUT@', '--dep-file', '@DEPFILE@'] + bindgen_dirs,
+ output: 'bindgen_args.mak',
+ depfile: 'bindgen_args.d'
+)
+
+# now generate all bindgen files
+bindgen_args_data = keyval.load(bindgen_args_file)
+bindgen_kwargs = {
+ 'input': 'wrapper.h',
+ 'dependencies': common_ss.all_dependencies(),
+ 'output': 'bindings.inc.rs',
+ 'include_directories': bindings_incdir,
+ 'bindgen_version': ['>=0.60.0'],
+ 'c_args': bindgen_c_args,
+}
+
+subdir('util-sys')
+subdir('migration-sys')
+subdir('qom-sys')
+subdir('chardev-sys')
+subdir('hwcore-sys')
+subdir('system-sys')
--- /dev/null
+[package]
+name = "migration-sys"
+version = "0.1.0"
+description = "Rust sys bindings for QEMU/migration"
+publish = false
+
+authors.workspace = true
+edition.workspace = true
+homepage.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+glib-sys = { workspace = true }
+common = { path = "../../common" }
+util-sys = { path = "../util-sys" }
+
+[lints]
+workspace = true
+
+[package.metadata.bindgen]
+header = "wrapper.h"
+bitfield-enum = ["MigrationPolicy", "MigrationPriority", "VMStateFlags"]
+blocklist-function = ["vmstate_register_ram", "vmstate_register_ram_global", "vmstate_unregister_ram"]
--- /dev/null
+../build.rs
\ No newline at end of file
--- /dev/null
+// 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;
+use util_sys::{Error, JSONWriter, QEMUFile};
+
+#[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 {}
+
+// The following higher-level helpers could be in "migration"
+// crate when Rust has const trait impl.
+
+pub trait VMStateFlagsExt {
+ const VMS_VARRAY_FLAGS: VMStateFlags;
+}
+
+impl VMStateFlagsExt for VMStateFlags {
+ const VMS_VARRAY_FLAGS: VMStateFlags = VMStateFlags(
+ VMStateFlags::VMS_VARRAY_INT32.0
+ | VMStateFlags::VMS_VARRAY_UINT8.0
+ | VMStateFlags::VMS_VARRAY_UINT16.0
+ | VMStateFlags::VMS_VARRAY_UINT32.0,
+ );
+}
+
+// Add a couple builder-style methods to VMStateField, allowing
+// easy derivation of VMStateField constants from other types.
+impl VMStateField {
+ #[must_use]
+ pub const fn with_version_id(mut self, version_id: i32) -> Self {
+ assert!(version_id >= 0);
+ self.version_id = version_id;
+ self
+ }
+
+ #[must_use]
+ pub const fn with_array_flag(mut self, num: usize) -> Self {
+ assert!(num <= 0x7FFF_FFFFusize);
+ assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) == 0);
+ assert!((self.flags.0 & VMStateFlags::VMS_VARRAY_FLAGS.0) == 0);
+ if (self.flags.0 & VMStateFlags::VMS_POINTER.0) != 0 {
+ self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_POINTER.0);
+ self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0);
+ // VMS_ARRAY_OF_POINTER flag stores the size of pointer.
+ // FIXME: *const, *mut, NonNull and Box<> have the same size as usize.
+ // Resize if more smart pointers are supported.
+ self.size = std::mem::size_of::<usize>();
+ }
+ self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_SINGLE.0);
+ self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY.0);
+ self.num = num as i32;
+ self
+ }
+
+ #[must_use]
+ pub const fn with_pointer_flag(mut self) -> Self {
+ assert!((self.flags.0 & VMStateFlags::VMS_POINTER.0) == 0);
+ self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_POINTER.0);
+ self
+ }
+
+ #[must_use]
+ pub const fn with_varray_flag_unchecked(mut self, flag: VMStateFlags) -> Self {
+ self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_ARRAY.0);
+ self.flags = VMStateFlags(self.flags.0 | flag.0);
+ self.num = 0; // varray uses num_offset instead of num.
+ self
+ }
+
+ #[must_use]
+ #[allow(unused_mut)]
+ pub const fn with_varray_flag(mut self, flag: VMStateFlags) -> Self {
+ assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) != 0);
+ self.with_varray_flag_unchecked(flag)
+ }
+
+ #[must_use]
+ pub const fn with_varray_multiply(mut self, num: u32) -> Self {
+ assert!(num <= 0x7FFF_FFFFu32);
+ self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0);
+ self.num = num as i32;
+ self
+ }
+}
--- /dev/null
+_bindgen_migration_rs = rust.bindgen(
+ args: bindgen_args_common + bindgen_args_data['migration-sys'].split(),
+ kwargs: bindgen_kwargs)
+_migration_sys_rs = static_library(
+ 'migration_sys',
+ structured_sources(['lib.rs', _bindgen_migration_rs]),
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ dependencies: [glib_sys_rs, common_rs, util_sys_rs],
+)
+
+migration_sys_rs = declare_dependency(link_with: [_migration_sys_rs])
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * This header file is meant to be used as input to the `bindgen` application
+ * in order to generate C FFI compatible Rust bindings.
+ */
+
+#include "qemu/osdep.h"
+
+#include "migration/vmstate.h"
--- /dev/null
+[package]
+name = "qom-sys"
+version = "0.1.0"
+description = "Rust sys bindings for QEMU/qom"
+publish = false
+
+authors.workspace = true
+edition.workspace = true
+homepage.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+glib-sys = { workspace = true }
+util-sys = { path = "../util-sys" }
+
+[lints]
+workspace = true
+
+[package.metadata.bindgen]
+header = "wrapper.h"
--- /dev/null
+../build.rs
\ No newline at end of file
)]
use glib_sys::{GHashTable, GHashTableIter, GPtrArray, GSList};
+use util_sys::{Error, QDict, QObject, Visitor};
#[cfg(MESON)]
include!("bindings.inc.rs");
#[cfg(not(MESON))]
include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs"));
+
+unsafe impl Send for TypeInfo {}
+unsafe impl Sync for TypeInfo {}
--- /dev/null
+_bindgen_qom_rs = rust.bindgen(
+ args: bindgen_args_common + bindgen_args_data['qom-sys'].split(),
+ kwargs: bindgen_kwargs)
+_qom_sys_rs = static_library(
+ 'qom_sys',
+ structured_sources(['lib.rs', _bindgen_qom_rs]),
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ dependencies: [glib_sys_rs, util_sys_rs],
+)
+
+qom_sys_rs = declare_dependency(link_with: [_qom_sys_rs])
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * This header file is meant to be used as input to the `bindgen` application
+ * in order to generate C FFI compatible Rust bindings.
+ */
+
+/*
+ * We block include/qemu/typedefs.h from bindgen, add here symbols
+ * that are needed as opaque types by other functions.
+ */
+typedef struct Object Object;
+typedef struct ObjectClass ObjectClass;
+
+#include "qemu/osdep.h"
+
+#include "qom/object.h"
--- /dev/null
+[package]
+name = "system-sys"
+version = "0.1.0"
+description = "Rust sys bindings for QEMU/system"
+publish = false
+
+authors.workspace = true
+edition.workspace = true
+homepage.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+glib-sys = { workspace = true }
+common = { path = "../../common" }
+migration-sys = { path = "../migration-sys" }
+util-sys = { path = "../util-sys" }
+qom-sys = { path = "../qom-sys" }
+
+[lints]
+workspace = true
+
+[package.metadata.bindgen]
+header = "wrapper.h"
+rustified-enum = ["device_endian"]
+additional-files = ["system/memory.*"]
--- /dev/null
+../build.rs
\ No newline at end of file
)]
use common::Zeroable;
-use glib_sys::{guint, GHashTable, GHashTableIter, GList, GPollFD, GPtrArray, GSList};
+use hwcore_sys::{qemu_irq, DeviceClass, DeviceState};
+use qom_sys::{InterfaceClass, Object, ObjectClass};
+use util_sys::{Error, EventNotifier, QEMUBH};
#[cfg(MESON)]
include!("bindings.inc.rs");
--- /dev/null
+_bindgen_system_rs = rust.bindgen(
+ args: bindgen_args_common + bindgen_args_data['system-sys'].split(),
+ kwargs: bindgen_kwargs)
+_system_sys_rs = static_library(
+ 'system_sys',
+ structured_sources(['lib.rs', _bindgen_system_rs]),
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ dependencies: [common_rs, glib_sys_rs, hwcore_sys_rs, migration_sys_rs, qom_sys_rs, util_sys_rs],
+)
+
+system_sys_rs = declare_dependency(link_with: [_system_sys_rs])
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * This header file is meant to be used as input to the `bindgen` application
+ * in order to generate C FFI compatible Rust bindings.
+ */
+
+/*
+ * We block include/qemu/typedefs.h from bindgen, add here symbols
+ * that are needed as opaque types by other functions.
+ */
+typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot;
+typedef struct MemoryRegion MemoryRegion;
+typedef struct RAMBlock RAMBlock;
+
+#include "qemu/osdep.h"
+
+#include "exec/hwaddr.h"
+#include "system/address-spaces.h"
+#include "system/memory.h"
+#include "hw/core/sysbus.h"
--- /dev/null
+[package]
+name = "util-sys"
+version = "0.1.0"
+description = "Rust sys bindings for QEMU/util"
+publish = false
+
+authors.workspace = true
+edition.workspace = true
+homepage.workspace = true
+license.workspace = true
+repository.workspace = true
+rust-version.workspace = true
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+glib-sys = { workspace = true }
+
+[lints]
+workspace = true
+
+[package.metadata.bindgen]
+header = "wrapper.h"
+rustified-enum = ["module_init_type", "QEMUClockType"]
--- /dev/null
+../build.rs
\ No newline at end of file
clippy::too_many_arguments
)]
-use glib_sys::{guint, GPollFD, GString};
+use glib_sys::{guint, GArray, GHashTable, GPollFD, GSList, GSource, GString};
#[cfg(MESON)]
include!("bindings.inc.rs");
--- /dev/null
+_bindgen_util_rs = rust.bindgen(
+ args: bindgen_args_common + bindgen_args_data['util-sys'].split(),
+ kwargs: bindgen_kwargs)
+_util_sys_rs = static_library(
+ 'util_sys',
+ structured_sources(['lib.rs', _bindgen_util_rs]),
+ override_options: ['rust_std=2021', 'build.rust_std=2021'],
+ rust_abi: 'rust',
+ dependencies: [glib_sys_rs],
+)
+
+util_sys_rs = declare_dependency(link_with: [_util_sys_rs])
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/*
+ * This header file is meant to be used as input to the `bindgen` application
+ * in order to generate C FFI compatible Rust bindings.
+ */
+
+/*
+ * We block include/qemu/typedefs.h from bindgen, add here symbols
+ * that are needed as opaque types by other functions.
+ */
+typedef struct QEMUBH QEMUBH;
+typedef struct QEMUFile QEMUFile;
+typedef struct QemuOpts QemuOpts;
+typedef struct JSONWriter JSONWriter;
+typedef struct Visitor Visitor;
+
+#include "qemu/osdep.h"
+
+#include "qapi/error.h"
+#include "qapi/error-internal.h"
+#include "qemu/event_notifier.h"
+#include "qemu/main-loop.h"
+#include "qemu/aio.h"
+#include "qemu/log-for-trace.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/option.h"
+#include "qemu/timer.h"
+#include "qapi/visitor.h"
+#include "qobject/qbool.h"
+#include "qobject/qdict.h"
+#include "qobject/qjson.h"
+#include "qobject/qlist.h"
+#include "qobject/qnull.h"
+#include "qobject/qnum.h"
+#include "qobject/qobject.h"
+#include "qobject/qstring.h"
+#include "qobject/json-writer.h"
[dependencies]
glib-sys.workspace = true
+util-sys = { path = "../bindings/util-sys" }
[features]
default = ["debug_cell"]
+++ /dev/null
-../util/build.rs
\ No newline at end of file
_bql_cfg += ['--cfg', 'feature="debug_cell"']
endif
-#
-# TODO: Remove this comment when the clang/libclang mismatch issue is solved.
-#
-# Rust bindings generation with `bindgen` might fail in some cases where the
-# detected `libclang` does not match the expected `clang` version/target. In
-# this case you must pass the path to `clang` and `libclang` to your build
-# command invocation using the environment variables CLANG_PATH and
-# LIBCLANG_PATH
-_bql_bindings_inc_rs = rust.bindgen(
- input: 'wrapper.h',
- dependencies: common_ss.all_dependencies(),
- output: 'bindings.inc.rs',
- include_directories: bindings_incdir,
- bindgen_version: ['>=0.60.0'],
- args: bindgen_args_common,
- c_args: bindgen_c_args,
-)
-
_bql_rs = static_library(
'bql',
- structured_sources(
- [
- 'src/lib.rs',
- 'src/bindings.rs',
- 'src/cell.rs',
- 'src/prelude.rs',
- ],
- {'.': _bql_bindings_inc_rs}
- ),
+ 'src/lib.rs',
rust_args: _bql_cfg,
- dependencies: [glib_sys_rs],
+ dependencies: [glib_sys_rs, util_sys_rs],
)
bql_rs = declare_dependency(link_with: [_bql_rs],
+++ /dev/null
-// 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 glib_sys::{guint, GArray, GHashTable, GHashTableIter, GPollFD, GPtrArray, GSList, GSource};
-
-#[cfg(MESON)]
-include!("bindings.inc.rs");
-
-#[cfg(not(MESON))]
-include!(concat!(env!("OUT_DIR"), "/bindings.inc.rs"));
// SPDX-License-Identifier: GPL-2.0-or-later
-mod bindings;
-use bindings::{bql_block_unlock, bql_locked, rust_bql_mock_lock};
+use util_sys::{bql_block_unlock, bql_locked, rust_bql_mock_lock};
mod cell;
pub use cell::*;
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/*
- * This header file is meant to be used as input to the `bindgen` application
- * in order to generate C FFI compatible Rust bindings.
- */
-
-#ifndef __CLANG_STDATOMIC_H
-#define __CLANG_STDATOMIC_H
-/*
- * Fix potential missing stdatomic.h error in case bindgen does not insert the
- * correct libclang header paths on its own. We do not use stdatomic.h symbols
- * in QEMU code, so it's fine to declare dummy types instead.
- */
-typedef enum memory_order {
- memory_order_relaxed,
- memory_order_consume,
- memory_order_acquire,
- memory_order_release,
- memory_order_acq_rel,
- memory_order_seq_cst,
-} memory_order;
-#endif /* __CLANG_STDATOMIC_H */
-
-#include "qemu/osdep.h"
-
-#include "qemu/main-loop.h"
[dependencies]
glib-sys = { workspace = true }
+chardev-sys = { path = "../bindings/chardev-sys" }
common = { path = "../common" }
bql = { path = "../bql" }
migration = { path = "../migration" }
+++ /dev/null
-../util/build.rs
\ No newline at end of file
-c_enums = [
- 'QEMUChrEvent',
-]
-_chardev_bindgen_args = []
-foreach enum : c_enums
- _chardev_bindgen_args += ['--rustified-enum', enum]
-endforeach
-
-# TODO: Remove this comment when the clang/libclang mismatch issue is solved.
-#
-# Rust bindings generation with `bindgen` might fail in some cases where the
-# detected `libclang` does not match the expected `clang` version/target. In
-# this case you must pass the path to `clang` and `libclang` to your build
-# command invocation using the environment variables CLANG_PATH and
-# LIBCLANG_PATH
-_chardev_bindings_inc_rs = rust.bindgen(
- input: 'wrapper.h',
- dependencies: common_ss.all_dependencies(),
- output: 'bindings.inc.rs',
- include_directories: bindings_incdir,
- bindgen_version: ['>=0.60.0'],
- args: bindgen_args_common + _chardev_bindgen_args,
- c_args: bindgen_c_args,
-)
-
_chardev_rs = static_library(
'chardev',
- structured_sources(
- [
- 'src/lib.rs',
- 'src/bindings.rs',
- 'src/chardev.rs',
- 'src/prelude.rs',
- ],
- {'.': _chardev_bindings_inc_rs}
- ),
+ 'src/lib.rs',
link_with: [_bql_rs, _migration_rs, _qom_rs, _util_rs],
- dependencies: [glib_sys_rs, common_rs, qemu_macros],
+ dependencies: [glib_sys_rs, common_rs, qemu_macros, chardev_sys_rs],
)
chardev_rs = declare_dependency(link_with: [_chardev_rs], dependencies: [chardev, qemuutil])
// SPDX-License-Identifier: GPL-2.0-or-later
-pub mod bindings;
+pub use chardev_sys as bindings;
mod chardev;
pub use chardev::*;
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/*
- * This header file is meant to be used as input to the `bindgen` application
- * in order to generate C FFI compatible Rust bindings.
- */
-
-#ifndef __CLANG_STDATOMIC_H
-#define __CLANG_STDATOMIC_H
-/*
- * Fix potential missing stdatomic.h error in case bindgen does not insert the
- * correct libclang header paths on its own. We do not use stdatomic.h symbols
- * in QEMU code, so it's fine to declare dummy types instead.
- */
-typedef enum memory_order {
- memory_order_relaxed,
- memory_order_consume,
- memory_order_acquire,
- memory_order_release,
- memory_order_acq_rel,
- memory_order_seq_cst,
-} memory_order;
-#endif /* __CLANG_STDATOMIC_H */
-
-#include "qemu/osdep.h"
-
-#include "chardev/char-fe.h"
-#include "chardev/char-serial.h"
-../../../util/build.rs
\ No newline at end of file
+../../../bindings/build.rs
\ No newline at end of file
-# TODO: Remove this comment when the clang/libclang mismatch issue is solved.
-#
-# Rust bindings generation with `bindgen` might fail in some cases where the
-# detected `libclang` does not match the expected `clang` version/target. In
-# this case you must pass the path to `clang` and `libclang` to your build
-# command invocation using the environment variables CLANG_PATH and
-# LIBCLANG_PATH
_libpl011_bindings_inc_rs = rust.bindgen(
- input: 'wrapper.h',
- dependencies: common_ss.all_dependencies(),
- output: 'bindings.inc.rs',
- include_directories: bindings_incdir,
- bindgen_version: ['>=0.60.0'],
- args: bindgen_args_common,
- c_args: bindgen_c_args,
+ args: bindgen_args_common + [
+ '--allowlist-file', meson.project_source_root() / 'include/hw/char/pl011.h',
+ '--blocklist-file',
+ meson.project_source_root() /
+ 'include/(block\|chardev/|exec/|hw/core/|qemu/|qom/|system/).*',
+ ],
+ kwargs: bindgen_kwargs,
)
_libpl011_rs = static_library(
//! `bindgen`-generated declarations.
-use glib_sys::{
- gboolean, guint, GArray, GHashTable, GHashTableIter, GIOCondition, GList, GMainContext,
- GPollFD, GPtrArray, GSList, GSource, GSourceFunc,
-};
+use chardev::bindings::{CharFrontend, Chardev};
+use hwcore::bindings::{qemu_irq, Clock, DeviceState};
+use system::bindings::{hwaddr, MemoryRegion, SysBusDevice};
#[cfg(MESON)]
include!("bindings.inc.rs");
[dependencies]
glib-sys.workspace = true
+hwcore-sys = { path = "../../bindings/hwcore-sys" }
qemu_macros = { path = "../../qemu-macros" }
common = { path = "../../common" }
bql = { path = "../../bql" }
+++ /dev/null
-../../util/build.rs
\ No newline at end of file
-_hwcore_bindgen_args = []
-c_enums = [
- 'DeviceCategory',
- 'GpioPolarity',
- 'MachineInitPhase',
- 'ResetType',
-]
-foreach enum : c_enums
- _hwcore_bindgen_args += ['--rustified-enum', enum]
-endforeach
-
-blocked_type = [
- 'Chardev',
- 'Error',
- 'ObjectClass',
- 'MemoryRegion',
- 'VMStateDescription',
-]
-foreach type: blocked_type
- _hwcore_bindgen_args += ['--blocklist-type', type]
-endforeach
-
-c_bitfields = [
- 'ClockEvent',
-]
-foreach enum : c_bitfields
- _hwcore_bindgen_args += ['--bitfield-enum', enum]
-endforeach
-
-# TODO: Remove this comment when the clang/libclang mismatch issue is solved.
-#
-# Rust bindings generation with `bindgen` might fail in some cases where the
-# detected `libclang` does not match the expected `clang` version/target. In
-# this case you must pass the path to `clang` and `libclang` to your build
-# command invocation using the environment variables CLANG_PATH and
-# LIBCLANG_PATH
-_hwcore_bindings_inc_rs = rust.bindgen(
- input: 'wrapper.h',
- dependencies: common_ss.all_dependencies(),
- output: 'bindings.inc.rs',
- include_directories: bindings_incdir,
- bindgen_version: ['>=0.60.0'],
- args: bindgen_args_common + _hwcore_bindgen_args,
- c_args: bindgen_c_args,
-)
-
_hwcore_rs = static_library(
'hwcore',
- structured_sources(
- [
- 'src/lib.rs',
- 'src/bindings.rs',
- 'src/irq.rs',
- 'src/prelude.rs',
- 'src/qdev.rs',
- 'src/sysbus.rs',
- ],
- {'.': _hwcore_bindings_inc_rs}
- ),
+ 'src/lib.rs',
override_options: ['rust_std=2021', 'build.rust_std=2021'],
rust_abi: 'rust',
link_with: [_bql_rs, _chardev_rs, _migration_rs, _qom_rs, _system_rs, _util_rs],
- dependencies: [glib_sys_rs, qemu_macros, common_rs],
+ dependencies: [glib_sys_rs, qemu_macros, common_rs, hwcore_sys_rs],
)
hwcore_rs = declare_dependency(link_with: [_hwcore_rs],
// SPDX-License-Identifier: GPL-2.0-or-later
+pub use hwcore_sys as bindings;
pub use qemu_macros::Device;
pub use qom;
-pub mod bindings;
-
mod irq;
pub use irq::*;
/// can be downcasted to type `T`. We also expect the device is
/// readable/writeable from one thread at any time.
unsafe extern "C" fn rust_resettable_enter_fn<T: ResettablePhasesImpl>(
- obj: *mut bindings::Object,
+ obj: *mut qom::bindings::Object,
typ: ResetType,
) {
let state = NonNull::new(obj).unwrap().cast::<T>();
/// can be downcasted to type `T`. We also expect the device is
/// readable/writeable from one thread at any time.
unsafe extern "C" fn rust_resettable_hold_fn<T: ResettablePhasesImpl>(
- obj: *mut bindings::Object,
+ obj: *mut qom::bindings::Object,
typ: ResetType,
) {
let state = NonNull::new(obj).unwrap().cast::<T>();
/// can be downcasted to type `T`. We also expect the device is
/// readable/writeable from one thread at any time.
unsafe extern "C" fn rust_resettable_exit_fn<T: ResettablePhasesImpl>(
- obj: *mut bindings::Object,
+ obj: *mut qom::bindings::Object,
typ: ResetType,
) {
let state = NonNull::new(obj).unwrap().cast::<T>();
use std::ffi::CStr;
-pub use bindings::SysBusDeviceClass;
use common::Opaque;
use qom::prelude::*;
use system::MemoryRegion;
+pub use system_sys::SysBusDeviceClass;
use util::{Error, Result};
use crate::{
- bindings,
irq::{IRQState, InterruptSource},
qdev::{DeviceClassExt, DeviceImpl, DeviceState},
};
-/// A safe wrapper around [`bindings::SysBusDevice`].
+/// A safe wrapper around [`system_sys::SysBusDevice`].
#[repr(transparent)]
#[derive(Debug, common::Wrapper)]
-pub struct SysBusDevice(Opaque<bindings::SysBusDevice>);
+pub struct SysBusDevice(Opaque<system_sys::SysBusDevice>);
unsafe impl Send for SysBusDevice {}
unsafe impl Sync for SysBusDevice {}
unsafe impl ObjectType for SysBusDevice {
type Class = SysBusDeviceClass;
const TYPE_NAME: &'static CStr =
- unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_SYS_BUS_DEVICE) };
+ unsafe { CStr::from_bytes_with_nul_unchecked(system_sys::TYPE_SYS_BUS_DEVICE) };
}
qom_isa!(SysBusDevice: DeviceState, Object);
fn init_mmio(&self, iomem: &MemoryRegion) {
assert!(bql::is_locked());
unsafe {
- bindings::sysbus_init_mmio(self.upcast().as_mut_ptr(), iomem.as_mut_ptr());
+ system_sys::sysbus_init_mmio(self.upcast().as_mut_ptr(), iomem.as_mut_ptr());
}
}
fn init_irq(&self, irq: &InterruptSource) {
assert!(bql::is_locked());
unsafe {
- bindings::sysbus_init_irq(self.upcast().as_mut_ptr(), irq.as_ptr());
+ system_sys::sysbus_init_irq(self.upcast().as_mut_ptr(), irq.as_ptr());
}
}
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<SysBusDevice>.
- let sbd = unsafe { &*self.upcast().as_ptr() };
+ let sbd = unsafe { &*self.upcast().as_mut_ptr() };
let id: usize = id.try_into().unwrap();
if sbd.mmio[id].memory.is_null() {
None
assert!(bql::is_locked());
let id: i32 = id.try_into().unwrap();
unsafe {
- bindings::sysbus_mmio_map(self.upcast().as_mut_ptr(), id, addr);
+ system_sys::sysbus_mmio_map(self.upcast().as_mut_ptr(), id, addr);
}
}
let id: i32 = id.try_into().unwrap();
let irq: &IRQState = irq;
unsafe {
- bindings::sysbus_connect_irq(self.upcast().as_mut_ptr(), id, irq.as_mut_ptr());
+ system_sys::sysbus_connect_irq(self.upcast().as_mut_ptr(), id, irq.as_mut_ptr());
}
}
assert!(bql::is_locked());
unsafe {
Error::with_errp(|errp| {
- bindings::sysbus_realize(self.upcast().as_mut_ptr(), errp);
+ system_sys::sysbus_realize(self.upcast().as_mut_ptr(), errp);
})
}
}
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/*
- * This header file is meant to be used as input to the `bindgen` application
- * in order to generate C FFI compatible Rust bindings.
- */
-
-#ifndef __CLANG_STDATOMIC_H
-#define __CLANG_STDATOMIC_H
-/*
- * Fix potential missing stdatomic.h error in case bindgen does not insert the
- * correct libclang header paths on its own. We do not use stdatomic.h symbols
- * in QEMU code, so it's fine to declare dummy types instead.
- */
-typedef enum memory_order {
- memory_order_relaxed,
- memory_order_consume,
- memory_order_acquire,
- memory_order_release,
- memory_order_acq_rel,
- memory_order_seq_cst,
-} memory_order;
-#endif /* __CLANG_STDATOMIC_H */
-
-#include "qemu/osdep.h"
-
-#include "hw/core/sysbus.h"
-#include "hw/core/clock.h"
-#include "hw/core/qdev-clock.h"
-#include "hw/core/qdev-properties.h"
-#include "hw/core/qdev-properties-system.h"
-#include "hw/core/irq.h"
subdir('qemu-macros')
subdir('common')
+subdir('bindings')
subdir('bits')
subdir('util')
common = { path = "../common" }
qemu_macros = { path = "../qemu-macros" }
util = { path = "../util" }
+migration-sys = { path = "../bindings/migration-sys" }
glib-sys.workspace = true
[lints]
+++ /dev/null
-../util/build.rs
\ No newline at end of file
-_migration_bindgen_args = []
-c_bitfields = [
- 'MigrationPolicy',
- 'MigrationPriority',
- 'VMStateFlags',
-]
-foreach enum : c_bitfields
- _migration_bindgen_args += ['--bitfield-enum', enum]
-endforeach
-#
-# TODO: Remove this comment when the clang/libclang mismatch issue is solved.
-#
-# Rust bindings generation with `bindgen` might fail in some cases where the
-# detected `libclang` does not match the expected `clang` version/target. In
-# this case you must pass the path to `clang` and `libclang` to your build
-# command invocation using the environment variables CLANG_PATH and
-# LIBCLANG_PATH
-_migration_bindings_inc_rs = rust.bindgen(
- input: 'wrapper.h',
- dependencies: common_ss.all_dependencies(),
- output: 'bindings.inc.rs',
- include_directories: bindings_incdir,
- bindgen_version: ['>=0.60.0'],
- args: bindgen_args_common + _migration_bindgen_args,
- c_args: bindgen_c_args,
-)
-
_migration_rs = static_library(
'migration',
- structured_sources(
- [
- 'src/lib.rs',
- 'src/bindings.rs',
- 'src/migratable.rs',
- 'src/prelude.rs',
- 'src/vmstate.rs',
- ],
- {'.' : _migration_bindings_inc_rs},
- ),
+ 'src/lib.rs',
link_with: [_util_rs, _bql_rs],
- dependencies: [common_rs, glib_sys_rs, qemu_macros],
+ dependencies: [common_rs, glib_sys_rs, qemu_macros, migration_sys_rs],
)
migration_rs = declare_dependency(link_with: [_migration_rs],
+++ /dev/null
-// 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;
-use glib_sys::{GHashTable, GHashTableIter, GPtrArray, GSList};
-
-#[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 {}
// SPDX-License-Identifier: GPL-2.0-or-later
-pub mod bindings;
-
+pub use migration_sys as bindings;
pub use qemu_macros::ToMigrationState;
pub mod migratable;
};
}
-pub trait VMStateFlagsExt {
- const VMS_VARRAY_FLAGS: VMStateFlags;
-}
-
-impl VMStateFlagsExt for VMStateFlags {
- const VMS_VARRAY_FLAGS: VMStateFlags = VMStateFlags(
- VMStateFlags::VMS_VARRAY_INT32.0
- | VMStateFlags::VMS_VARRAY_UINT8.0
- | VMStateFlags::VMS_VARRAY_UINT16.0
- | VMStateFlags::VMS_VARRAY_UINT32.0,
- );
-}
-
-// Add a couple builder-style methods to VMStateField, allowing
-// easy derivation of VMStateField constants from other types.
-impl VMStateField {
- #[must_use]
- pub const fn with_version_id(mut self, version_id: i32) -> Self {
- assert!(version_id >= 0);
- self.version_id = version_id;
- self
- }
-
- #[must_use]
- pub const fn with_array_flag(mut self, num: usize) -> Self {
- assert!(num <= 0x7FFF_FFFFusize);
- assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) == 0);
- assert!((self.flags.0 & VMStateFlags::VMS_VARRAY_FLAGS.0) == 0);
- if (self.flags.0 & VMStateFlags::VMS_POINTER.0) != 0 {
- self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_POINTER.0);
- self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY_OF_POINTER.0);
- // VMS_ARRAY_OF_POINTER flag stores the size of pointer.
- // FIXME: *const, *mut, NonNull and Box<> have the same size as usize.
- // Resize if more smart pointers are supported.
- self.size = std::mem::size_of::<usize>();
- }
- self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_SINGLE.0);
- self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_ARRAY.0);
- self.num = num as i32;
- self
- }
-
- #[must_use]
- pub const fn with_pointer_flag(mut self) -> Self {
- assert!((self.flags.0 & VMStateFlags::VMS_POINTER.0) == 0);
- self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_POINTER.0);
- self
- }
-
- #[must_use]
- pub const fn with_varray_flag_unchecked(mut self, flag: VMStateFlags) -> Self {
- self.flags = VMStateFlags(self.flags.0 & !VMStateFlags::VMS_ARRAY.0);
- self.flags = VMStateFlags(self.flags.0 | flag.0);
- self.num = 0; // varray uses num_offset instead of num.
- self
- }
-
- #[must_use]
- #[allow(unused_mut)]
- pub const fn with_varray_flag(mut self, flag: VMStateFlags) -> Self {
- assert!((self.flags.0 & VMStateFlags::VMS_ARRAY.0) != 0);
- self.with_varray_flag_unchecked(flag)
- }
-
- #[must_use]
- pub const fn with_varray_multiply(mut self, num: u32) -> Self {
- assert!(num <= 0x7FFF_FFFFu32);
- self.flags = VMStateFlags(self.flags.0 | VMStateFlags::VMS_MULTIPLY_ELEMENTS.0);
- self.num = num as i32;
- self
- }
-}
-
/// This macro can be used (by just passing it a type) to forward the `VMState`
/// trait to the first field of a tuple. This is a workaround for lack of
/// support of nested [`offset_of`](core::mem::offset_of) until Rust 1.82.0.
+++ /dev/null
-/*
- * QEMU System Emulator
- *
- * Copyright (c) 2024 Linaro Ltd.
- *
- * Authors: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-
-/*
- * This header file is meant to be used as input to the `bindgen` application
- * in order to generate C FFI compatible Rust bindings.
- */
-
-#ifndef __CLANG_STDATOMIC_H
-#define __CLANG_STDATOMIC_H
-/*
- * Fix potential missing stdatomic.h error in case bindgen does not insert the
- * correct libclang header paths on its own. We do not use stdatomic.h symbols
- * in QEMU code, so it's fine to declare dummy types instead.
- */
-typedef enum memory_order {
- memory_order_relaxed,
- memory_order_consume,
- memory_order_acquire,
- memory_order_release,
- memory_order_acq_rel,
- memory_order_seq_cst,
-} memory_order;
-#endif /* __CLANG_STDATOMIC_H */
-
-#include "qemu/osdep.h"
-#include "migration/vmstate.h"
migration = { path = "../migration" }
qemu_macros = { path = "../qemu-macros" }
util = { path = "../util" }
+qom-sys = { path = "../bindings/qom-sys" }
glib-sys.workspace = true
[lints]
+++ /dev/null
-../util/build.rs
\ No newline at end of file
-# TODO: Remove this comment when the clang/libclang mismatch issue is solved.
-#
-# Rust bindings generation with `bindgen` might fail in some cases where the
-# detected `libclang` does not match the expected `clang` version/target. In
-# this case you must pass the path to `clang` and `libclang` to your build
-# command invocation using the environment variables CLANG_PATH and
-# LIBCLANG_PATH
-_qom_bindings_inc_rs = rust.bindgen(
- input: 'wrapper.h',
- dependencies: common_ss.all_dependencies(),
- output: 'bindings.inc.rs',
- include_directories: bindings_incdir,
- bindgen_version: ['>=0.60.0'],
- args: bindgen_args_common,
- c_args: bindgen_c_args,
-)
-
_qom_rs = static_library(
'qom',
- structured_sources(
- [
- 'src/lib.rs',
- 'src/bindings.rs',
- 'src/prelude.rs',
- 'src/qom.rs',
- ],
- {'.': _qom_bindings_inc_rs}
- ),
+ 'src/lib.rs',
link_with: [_bql_rs, _migration_rs],
- dependencies: [common_rs, glib_sys_rs, qemu_macros],
+ dependencies: [common_rs, glib_sys_rs, qemu_macros, qom_sys_rs],
)
qom_rs = declare_dependency(link_with: [_qom_rs], dependencies: [qemu_macros, qom, qemuutil])
// SPDX-License-Identifier: GPL-2.0-or-later
pub use qemu_macros::Object;
-
-pub mod bindings;
+pub use qom_sys as bindings;
// preserve one-item-per-"use" syntax, it is clearer
// for prelude-like modules
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/*
- * This header file is meant to be used as input to the `bindgen` application
- * in order to generate C FFI compatible Rust bindings.
- */
-
-#ifndef __CLANG_STDATOMIC_H
-#define __CLANG_STDATOMIC_H
-/*
- * Fix potential missing stdatomic.h error in case bindgen does not insert the
- * correct libclang header paths on its own. We do not use stdatomic.h symbols
- * in QEMU code, so it's fine to declare dummy types instead.
- */
-typedef enum memory_order {
- memory_order_relaxed,
- memory_order_consume,
- memory_order_acquire,
- memory_order_release,
- memory_order_acq_rel,
- memory_order_seq_cst,
-} memory_order;
-#endif /* __CLANG_STDATOMIC_H */
-
-#include "qemu/osdep.h"
-
-#include "qom/object.h"
[dependencies]
common = { path = "../common" }
+system-sys = { path = "../bindings/system-sys" }
+bql = { path = "../bql" }
+migration = { path = "../migration" }
qom = { path = "../qom" }
util = { path = "../util" }
glib-sys.workspace = true
+++ /dev/null
-../util/build.rs
\ No newline at end of file
-c_enums = [
- 'device_endian',
-]
-_system_bindgen_args = []
-foreach enum : c_enums
- _system_bindgen_args += ['--rustified-enum', enum]
-endforeach
-
-# TODO: Remove this comment when the clang/libclang mismatch issue is solved.
-#
-# Rust bindings generation with `bindgen` might fail in some cases where the
-# detected `libclang` does not match the expected `clang` version/target. In
-# this case you must pass the path to `clang` and `libclang` to your build
-# command invocation using the environment variables CLANG_PATH and
-# LIBCLANG_PATH
-_system_bindings_inc_rs = rust.bindgen(
- input: 'wrapper.h',
- dependencies: common_ss.all_dependencies(),
- output: 'bindings.inc.rs',
- include_directories: bindings_incdir,
- bindgen_version: ['>=0.60.0'],
- args: bindgen_args_common + _system_bindgen_args,
- c_args: bindgen_c_args,
-)
-
_system_rs = static_library(
'system',
- structured_sources(
- [
- 'src/lib.rs',
- 'src/bindings.rs',
- 'src/memory.rs',
- 'src/prelude.rs',
- ],
- {'.': _system_bindings_inc_rs}
- ),
+ 'src/lib.rs',
link_with: [_bql_rs, _migration_rs, _qom_rs, _util_rs],
- dependencies: [glib_sys_rs, common_rs, qemu_macros],
+ dependencies: [glib_sys_rs, common_rs, qemu_macros, system_sys_rs],
)
system_rs = declare_dependency(link_with: [_system_rs],
// SPDX-License-Identifier: GPL-2.0-or-later
-pub mod bindings;
+pub use system_sys as bindings;
mod memory;
pub use memory::*;
impl MemoryRegion {
unsafe fn do_init_io(
slot: *mut bindings::MemoryRegion,
- owner: *mut bindings::Object,
+ owner: *mut qom::bindings::Object,
ops: &'static bindings::MemoryRegionOps,
name: &'static str,
size: u64,
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/*
- * This header file is meant to be used as input to the `bindgen` application
- * in order to generate C FFI compatible Rust bindings.
- */
-
-#ifndef __CLANG_STDATOMIC_H
-#define __CLANG_STDATOMIC_H
-/*
- * Fix potential missing stdatomic.h error in case bindgen does not insert the
- * correct libclang header paths on its own. We do not use stdatomic.h symbols
- * in QEMU code, so it's fine to declare dummy types instead.
- */
-typedef enum memory_order {
- memory_order_relaxed,
- memory_order_consume,
- memory_order_acquire,
- memory_order_release,
- memory_order_acq_rel,
- memory_order_seq_cst,
-} memory_order;
-#endif /* __CLANG_STDATOMIC_H */
-
-#include "qemu/osdep.h"
-
-#include "system/system.h"
-#include "system/memory.h"
-#include "system/address-spaces.h"
glib-sys = { workspace = true }
libc = { workspace = true }
common = { path = "../common" }
+util-sys = { path = "../bindings/util-sys" }
[lints]
workspace = true
-_util_bindgen_args = []
-c_enums = [
- 'module_init_type',
- 'QEMUClockType',
-]
-foreach enum : c_enums
- _util_bindgen_args += ['--rustified-enum', enum]
-endforeach
-
-#
-# TODO: Remove this comment when the clang/libclang mismatch issue is solved.
-#
-# Rust bindings generation with `bindgen` might fail in some cases where the
-# detected `libclang` does not match the expected `clang` version/target. In
-# this case you must pass the path to `clang` and `libclang` to your build
-# command invocation using the environment variables CLANG_PATH and
-# LIBCLANG_PATH
-_util_bindings_inc_rs = rust.bindgen(
- input: 'wrapper.h',
- dependencies: common_ss.all_dependencies(),
- output: 'bindings.inc.rs',
- include_directories: bindings_incdir,
- bindgen_version: ['>=0.60.0'],
- args: bindgen_args_common + _util_bindgen_args,
- c_args: bindgen_c_args,
-)
-
_util_rs = static_library(
'util',
- structured_sources(
- [
- 'src/lib.rs',
- 'src/bindings.rs',
- 'src/error.rs',
- 'src/log.rs',
- 'src/module.rs',
- 'src/prelude.rs',
- 'src/timer.rs',
- ],
- {'.': _util_bindings_inc_rs}
- ),
- dependencies: [anyhow_rs, libc_rs, foreign_rs, glib_sys_rs, common_rs],
+ 'src/lib.rs',
+ dependencies: [anyhow_rs, libc_rs, foreign_rs, glib_sys_rs, common_rs, util_sys_rs],
)
util_rs = declare_dependency(link_with: [_util_rs], dependencies: [qemuutil, qom])
// SPDX-License-Identifier: GPL-2.0-or-later
-pub mod bindings;
+pub use util_sys as bindings;
+
pub mod error;
pub mod log;
pub mod module;
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/*
- * This header file is meant to be used as input to the `bindgen` application
- * in order to generate C FFI compatible Rust bindings.
- */
-
-#ifndef __CLANG_STDATOMIC_H
-#define __CLANG_STDATOMIC_H
-/*
- * Fix potential missing stdatomic.h error in case bindgen does not insert the
- * correct libclang header paths on its own. We do not use stdatomic.h symbols
- * in QEMU code, so it's fine to declare dummy types instead.
- */
-typedef enum memory_order {
- memory_order_relaxed,
- memory_order_consume,
- memory_order_acquire,
- memory_order_release,
- memory_order_acq_rel,
- memory_order_seq_cst,
-} memory_order;
-#endif /* __CLANG_STDATOMIC_H */
-
-#include "qemu/osdep.h"
-
-#include "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"