aboutsummaryrefslogtreecommitdiff
path: root/rust/qemu-api/src
diff options
context:
space:
mode:
Diffstat (limited to 'rust/qemu-api/src')
-rw-r--r--rust/qemu-api/src/assertions.rs152
-rw-r--r--rust/qemu-api/src/bindings.rs55
-rw-r--r--rust/qemu-api/src/bitops.rs119
-rw-r--r--rust/qemu-api/src/callbacks.rs241
-rw-r--r--rust/qemu-api/src/cell.rs1105
-rw-r--r--rust/qemu-api/src/chardev.rs260
-rw-r--r--rust/qemu-api/src/errno.rs345
-rw-r--r--rust/qemu-api/src/irq.rs115
-rw-r--r--rust/qemu-api/src/lib.rs165
-rw-r--r--rust/qemu-api/src/memory.rs204
-rw-r--r--rust/qemu-api/src/module.rs43
-rw-r--r--rust/qemu-api/src/prelude.rs29
-rw-r--r--rust/qemu-api/src/qdev.rs395
-rw-r--r--rust/qemu-api/src/qom.rs772
-rw-r--r--rust/qemu-api/src/sysbus.rs122
-rw-r--r--rust/qemu-api/src/timer.rs125
-rw-r--r--rust/qemu-api/src/vmstate.rs604
-rw-r--r--rust/qemu-api/src/zeroable.rs37
18 files changed, 0 insertions, 4888 deletions
diff --git a/rust/qemu-api/src/assertions.rs b/rust/qemu-api/src/assertions.rs
deleted file mode 100644
index a2d38c8..0000000
--- a/rust/qemu-api/src/assertions.rs
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2024, Red Hat Inc.
-// Author(s): Paolo Bonzini <pbonzini@redhat.com>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#![doc(hidden)]
-//! This module provides macros to check the equality of types and
-//! the type of `struct` fields. This can be useful to ensure that
-//! types match the expectations of C code.
-//!
-//! Documentation is hidden because it only exposes macros, which
-//! are exported directly from `qemu_api`.
-
-// Based on https://stackoverflow.com/questions/64251852/x/70978292#70978292
-// (stackoverflow answers are released under MIT license).
-
-#[doc(hidden)]
-pub trait EqType {
- type Itself;
-}
-
-impl<T> EqType for T {
- type Itself = T;
-}
-
-/// Assert that two types are the same.
-///
-/// # Examples
-///
-/// ```
-/// # use qemu_api::assert_same_type;
-/// # use std::ops::Deref;
-/// assert_same_type!(u32, u32);
-/// assert_same_type!(<Box<u32> as Deref>::Target, u32);
-/// ```
-///
-/// Different types will cause a compile failure
-///
-/// ```compile_fail
-/// # use qemu_api::assert_same_type;
-/// assert_same_type!(&Box<u32>, &u32);
-/// ```
-#[macro_export]
-macro_rules! assert_same_type {
- ($t1:ty, $t2:ty) => {
- const _: () = {
- #[allow(unused)]
- fn assert_same_type(v: $t1) {
- fn types_must_be_equal<T, U>(_: T)
- where
- T: $crate::assertions::EqType<Itself = U>,
- {
- }
- types_must_be_equal::<_, $t2>(v);
- }
- };
- };
-}
-
-/// Assert that a field of a struct has the given type.
-///
-/// # Examples
-///
-/// ```
-/// # use qemu_api::assert_field_type;
-/// pub struct A {
-/// field1: u32,
-/// }
-///
-/// assert_field_type!(A, field1, u32);
-/// ```
-///
-/// Different types will cause a compile failure
-///
-/// ```compile_fail
-/// # use qemu_api::assert_field_type;
-/// # pub struct A { field1: u32 }
-/// assert_field_type!(A, field1, i32);
-/// ```
-#[macro_export]
-macro_rules! assert_field_type {
- (@internal $param_name:ident, $ti:ty, $t:ty, $($field:tt)*) => {
- const _: () = {
- #[allow(unused)]
- fn assert_field_type($param_name: &$t) {
- fn types_must_be_equal<T, U>(_: &T)
- where
- T: $crate::assertions::EqType<Itself = U>,
- {
- }
- types_must_be_equal::<_, $ti>(&$($field)*);
- }
- };
- };
-
- ($t:ty, $i:tt, $ti:ty) => {
- $crate::assert_field_type!(@internal v, $ti, $t, v.$i);
- };
-
- ($t:ty, $i:tt, $ti:ty, num = $num:ident) => {
- $crate::assert_field_type!(@internal v, $ti, $t, v.$i[0]);
- };
-}
-
-/// Assert that an expression matches a pattern. This can also be
-/// useful to compare enums that do not implement `Eq`.
-///
-/// # Examples
-///
-/// ```
-/// # use qemu_api::assert_match;
-/// // JoinHandle does not implement `Eq`, therefore the result
-/// // does not either.
-/// let result: Result<std::thread::JoinHandle<()>, u32> = Err(42);
-/// assert_match!(result, Err(42));
-/// ```
-#[macro_export]
-macro_rules! assert_match {
- ($a:expr, $b:pat) => {
- assert!(
- match $a {
- $b => true,
- _ => false,
- },
- "{} = {:?} does not match {}",
- stringify!($a),
- $a,
- stringify!($b)
- );
- };
-}
-
-/// Assert at compile time that an expression is true. This is similar
-/// to `const { assert!(...); }` but it works outside functions, as well as
-/// on versions of Rust before 1.79.
-///
-/// # Examples
-///
-/// ```
-/// # use qemu_api::static_assert;
-/// static_assert!("abc".len() == 3);
-/// ```
-///
-/// ```compile_fail
-/// # use qemu_api::static_assert;
-/// static_assert!("abc".len() == 2); // does not compile
-/// ```
-#[macro_export]
-macro_rules! static_assert {
- ($x:expr) => {
- const _: () = assert!($x);
- };
-}
diff --git a/rust/qemu-api/src/bindings.rs b/rust/qemu-api/src/bindings.rs
deleted file mode 100644
index 3c1d297..0000000
--- a/rust/qemu-api/src/bindings.rs
+++ /dev/null
@@ -1,55 +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,
- unsafe_op_in_unsafe_fn,
- clippy::pedantic,
- clippy::restriction,
- clippy::style,
- clippy::missing_const_for_fn,
- clippy::useless_transmute,
- clippy::missing_safety_doc
-)]
-
-//! `bindgen`-generated declarations.
-
-#[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 {}
-
-// 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 {}
-
-unsafe impl Send for TypeInfo {}
-unsafe impl Sync for TypeInfo {}
-
-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 {}
diff --git a/rust/qemu-api/src/bitops.rs b/rust/qemu-api/src/bitops.rs
deleted file mode 100644
index 023ec1a..0000000
--- a/rust/qemu-api/src/bitops.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (C) 2024 Intel Corporation.
-// Author(s): Zhao Liu <zhai1.liu@intel.com>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! This module provides bit operation extensions to integer types.
-//! It is usually included via the `qemu_api` prelude.
-
-use std::ops::{
- Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
- Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign,
-};
-
-/// Trait for extensions to integer types
-pub trait IntegerExt:
- Add<Self, Output = Self> + AddAssign<Self> +
- BitAnd<Self, Output = Self> + BitAndAssign<Self> +
- BitOr<Self, Output = Self> + BitOrAssign<Self> +
- BitXor<Self, Output = Self> + BitXorAssign<Self> +
- Copy +
- Div<Self, Output = Self> + DivAssign<Self> +
- Eq +
- Mul<Self, Output = Self> + MulAssign<Self> +
- Not<Output = Self> + Ord + PartialOrd +
- Rem<Self, Output = Self> + RemAssign<Self> +
- Shl<Self, Output = Self> + ShlAssign<Self> +
- Shl<u32, Output = Self> + ShlAssign<u32> + // add more as needed
- Shr<Self, Output = Self> + ShrAssign<Self> +
- Shr<u32, Output = Self> + ShrAssign<u32> // add more as needed
-{
- const BITS: u32;
- const MAX: Self;
- const MIN: Self;
- const ONE: Self;
- const ZERO: Self;
-
- #[inline]
- #[must_use]
- fn bit(start: u32) -> Self
- {
- debug_assert!(start < Self::BITS);
-
- Self::ONE << start
- }
-
- #[inline]
- #[must_use]
- fn mask(start: u32, length: u32) -> Self
- {
- /* FIXME: Implement a more elegant check with error handling support? */
- debug_assert!(start < Self::BITS && length > 0 && length <= Self::BITS - start);
-
- (Self::MAX >> (Self::BITS - length)) << start
- }
-
- #[inline]
- #[must_use]
- fn deposit<U: IntegerExt>(self, start: u32, length: u32,
- fieldval: U) -> Self
- where Self: From<U>
- {
- debug_assert!(length <= U::BITS);
-
- let mask = Self::mask(start, length);
- (self & !mask) | ((Self::from(fieldval) << start) & mask)
- }
-
- #[inline]
- #[must_use]
- fn extract(self, start: u32, length: u32) -> Self
- {
- let mask = Self::mask(start, length);
- (self & mask) >> start
- }
-}
-
-macro_rules! impl_num_ext {
- ($type:ty) => {
- impl IntegerExt for $type {
- const BITS: u32 = <$type>::BITS;
- const MAX: Self = <$type>::MAX;
- const MIN: Self = <$type>::MIN;
- const ONE: Self = 1;
- const ZERO: Self = 0;
- }
- };
-}
-
-impl_num_ext!(u8);
-impl_num_ext!(u16);
-impl_num_ext!(u32);
-impl_num_ext!(u64);
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_deposit() {
- assert_eq!(15u32.deposit(8, 8, 1u32), 256 + 15);
- assert_eq!(15u32.deposit(8, 1, 255u8), 256 + 15);
- }
-
- #[test]
- fn test_extract() {
- assert_eq!(15u32.extract(2, 4), 3);
- }
-
- #[test]
- fn test_bit() {
- assert_eq!(u8::bit(7), 128);
- assert_eq!(u32::bit(16), 0x10000);
- }
-
- #[test]
- fn test_mask() {
- assert_eq!(u8::mask(7, 1), 128);
- assert_eq!(u32::mask(8, 8), 0xff00);
- }
-}
diff --git a/rust/qemu-api/src/callbacks.rs b/rust/qemu-api/src/callbacks.rs
deleted file mode 100644
index 9642a16..0000000
--- a/rust/qemu-api/src/callbacks.rs
+++ /dev/null
@@ -1,241 +0,0 @@
-// SPDX-License-Identifier: MIT
-
-//! Utility functions to deal with callbacks from C to Rust.
-
-use std::{mem, ptr::NonNull};
-
-/// Trait for functions (types implementing [`Fn`]) that can be used as
-/// callbacks. These include both zero-capture closures and function pointers.
-///
-/// In Rust, calling a function through the `Fn` trait normally requires a
-/// `self` parameter, even though for zero-sized functions (including function
-/// pointers) the type itself contains all necessary information to call the
-/// function. This trait provides a `call` function that doesn't require `self`,
-/// allowing zero-sized functions to be called using only their type.
-///
-/// This enables zero-sized functions to be passed entirely through generic
-/// parameters and resolved at compile-time. A typical use is a function
-/// receiving an unused parameter of generic type `F` and calling it via
-/// `F::call` or passing it to another function via `func::<F>`.
-///
-/// QEMU uses this trick to create wrappers to C callbacks. The wrappers
-/// are needed to convert an opaque `*mut c_void` into a Rust reference,
-/// but they only have a single opaque that they can use. The `FnCall`
-/// trait makes it possible to use that opaque for `self` or any other
-/// reference:
-///
-/// ```ignore
-/// // The compiler creates a new `rust_bh_cb` wrapper for each function
-/// // passed to `qemu_bh_schedule_oneshot` below.
-/// unsafe extern "C" fn rust_bh_cb<T, F: for<'a> FnCall<(&'a T,)>>(
-/// opaque: *mut c_void,
-/// ) {
-/// // SAFETY: the opaque was passed as a reference to `T`.
-/// F::call((unsafe { &*(opaque.cast::<T>()) }, ))
-/// }
-///
-/// // The `_f` parameter is unused but it helps the compiler build the appropriate `F`.
-/// // Using a reference allows usage in const context.
-/// fn qemu_bh_schedule_oneshot<T, F: for<'a> FnCall<(&'a T,)>>(_f: &F, opaque: &T) {
-/// let cb: unsafe extern "C" fn(*mut c_void) = rust_bh_cb::<T, F>;
-/// unsafe {
-/// bindings::qemu_bh_schedule_oneshot(cb, opaque as *const T as *const c_void as *mut c_void)
-/// }
-/// }
-/// ```
-///
-/// Each wrapper is a separate instance of `rust_bh_cb` and is therefore
-/// compiled to a separate function ("monomorphization"). If you wanted
-/// to pass `self` as the opaque value, the generic parameters would be
-/// `rust_bh_cb::<Self, F>`.
-///
-/// `Args` is a tuple type whose types are the arguments of the function,
-/// while `R` is the returned type.
-///
-/// # Examples
-///
-/// ```
-/// # use qemu_api::callbacks::FnCall;
-/// fn call_it<F: for<'a> FnCall<(&'a str,), String>>(_f: &F, s: &str) -> String {
-/// F::call((s,))
-/// }
-///
-/// let s: String = call_it(&str::to_owned, "hello world");
-/// assert_eq!(s, "hello world");
-/// ```
-///
-/// Note that the compiler will produce a different version of `call_it` for
-/// each function that is passed to it. Therefore the argument is not really
-/// used, except to decide what is `F` and what `F::call` does.
-///
-/// Attempting to pass a non-zero-sized closure causes a compile-time failure:
-///
-/// ```compile_fail
-/// # use qemu_api::callbacks::FnCall;
-/// # fn call_it<'a, F: FnCall<(&'a str,), String>>(_f: &F, s: &'a str) -> String {
-/// # F::call((s,))
-/// # }
-/// let x: &'static str = "goodbye world";
-/// call_it(&move |_| String::from(x), "hello workd");
-/// ```
-///
-/// `()` can be used to indicate "no function":
-///
-/// ```
-/// # use qemu_api::callbacks::FnCall;
-/// fn optional<F: for<'a> FnCall<(&'a str,), String>>(_f: &F, s: &str) -> Option<String> {
-/// if F::IS_SOME {
-/// Some(F::call((s,)))
-/// } else {
-/// None
-/// }
-/// }
-///
-/// assert!(optional(&(), "hello world").is_none());
-/// ```
-///
-/// Invoking `F::call` will then be a run-time error.
-///
-/// ```should_panic
-/// # use qemu_api::callbacks::FnCall;
-/// # fn call_it<F: for<'a> FnCall<(&'a str,), String>>(_f: &F, s: &str) -> String {
-/// # F::call((s,))
-/// # }
-/// let s: String = call_it(&(), "hello world"); // panics
-/// ```
-///
-/// # Safety
-///
-/// Because `Self` is a zero-sized type, all instances of the type are
-/// equivalent. However, in addition to this, `Self` must have no invariants
-/// that could be violated by creating a reference to it.
-///
-/// This is always true for zero-capture closures and function pointers, as long
-/// as the code is able to name the function in the first place.
-pub unsafe trait FnCall<Args, R = ()>: 'static + Sync + Sized {
- /// Referring to this internal constant asserts that the `Self` type is
- /// zero-sized. Can be replaced by an inline const expression in
- /// Rust 1.79.0+.
- const ASSERT_ZERO_SIZED: () = { assert!(mem::size_of::<Self>() == 0) };
-
- /// Referring to this constant asserts that the `Self` type is an actual
- /// function type, which can be used to catch incorrect use of `()`
- /// at compile time.
- ///
- /// # Examples
- ///
- /// ```compile_fail
- /// # use qemu_api::callbacks::FnCall;
- /// fn call_it<F: for<'a> FnCall<(&'a str,), String>>(_f: &F, s: &str) -> String {
- /// let _: () = F::ASSERT_IS_SOME;
- /// F::call((s,))
- /// }
- ///
- /// let s: String = call_it((), "hello world"); // does not compile
- /// ```
- ///
- /// Note that this can be more simply `const { assert!(F::IS_SOME) }` in
- /// Rust 1.79.0 or newer.
- const ASSERT_IS_SOME: () = { assert!(Self::IS_SOME) };
-
- /// `true` if `Self` is an actual function type and not `()`.
- ///
- /// # Examples
- ///
- /// You can use `IS_SOME` to catch this at compile time:
- ///
- /// ```compile_fail
- /// # use qemu_api::callbacks::FnCall;
- /// fn call_it<F: for<'a> FnCall<(&'a str,), String>>(_f: &F, s: &str) -> String {
- /// const { assert!(F::IS_SOME) }
- /// F::call((s,))
- /// }
- ///
- /// let s: String = call_it((), "hello world"); // does not compile
- /// ```
- const IS_SOME: bool;
-
- /// `false` if `Self` is an actual function type, `true` if it is `()`.
- fn is_none() -> bool {
- !Self::IS_SOME
- }
-
- /// `true` if `Self` is an actual function type, `false` if it is `()`.
- fn is_some() -> bool {
- Self::IS_SOME
- }
-
- /// Call the function with the arguments in args.
- fn call(a: Args) -> R;
-}
-
-/// `()` acts as a "null" callback. Using `()` and `function` is nicer
-/// than `None` and `Some(function)`, because the compiler is unable to
-/// infer the type of just `None`. Therefore, the trait itself acts as the
-/// option type, with functions [`FnCall::is_some`] and [`FnCall::is_none`].
-unsafe impl<Args, R> FnCall<Args, R> for () {
- const IS_SOME: bool = false;
-
- /// Call the function with the arguments in args.
- fn call(_a: Args) -> R {
- panic!("callback not specified")
- }
-}
-
-macro_rules! impl_call {
- ($($args:ident,)* ) => (
- // SAFETY: because each function is treated as a separate type,
- // accessing `FnCall` is only possible in code that would be
- // allowed to call the function.
- unsafe impl<F, $($args,)* R> FnCall<($($args,)*), R> for F
- where
- F: 'static + Sync + Sized + Fn($($args, )*) -> R,
- {
- const IS_SOME: bool = true;
-
- #[inline(always)]
- fn call(a: ($($args,)*)) -> R {
- let _: () = Self::ASSERT_ZERO_SIZED;
-
- // SAFETY: the safety of this method is the condition for implementing
- // `FnCall`. As to the `NonNull` idiom to create a zero-sized type,
- // see https://github.com/rust-lang/libs-team/issues/292.
- let f: &'static F = unsafe { &*NonNull::<Self>::dangling().as_ptr() };
- let ($($args,)*) = a;
- f($($args,)*)
- }
- }
- )
-}
-
-impl_call!(_1, _2, _3, _4, _5,);
-impl_call!(_1, _2, _3, _4,);
-impl_call!(_1, _2, _3,);
-impl_call!(_1, _2,);
-impl_call!(_1,);
-impl_call!();
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- // The `_f` parameter is unused but it helps the compiler infer `F`.
- fn do_test_call<'a, F: FnCall<(&'a str,), String>>(_f: &F) -> String {
- F::call(("hello world",))
- }
-
- #[test]
- fn test_call() {
- assert_eq!(do_test_call(&str::to_owned), "hello world")
- }
-
- // The `_f` parameter is unused but it helps the compiler infer `F`.
- fn do_test_is_some<'a, F: FnCall<(&'a str,), String>>(_f: &F) {
- assert!(F::is_some());
- }
-
- #[test]
- fn test_is_some() {
- do_test_is_some(&str::to_owned);
- }
-}
diff --git a/rust/qemu-api/src/cell.rs b/rust/qemu-api/src/cell.rs
deleted file mode 100644
index 05ce09f..0000000
--- a/rust/qemu-api/src/cell.rs
+++ /dev/null
@@ -1,1105 +0,0 @@
-// SPDX-License-Identifier: MIT
-//
-// This file is based on library/core/src/cell.rs from
-// Rust 1.82.0.
-//
-// 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.
-
-//! QEMU-specific mutable containers
-//!
-//! Rust memory safety is based on this rule: Given an object `T`, it is only
-//! possible to have one of the following:
-//!
-//! - Having several immutable references (`&T`) to the object (also known as
-//! **aliasing**).
-//! - Having one mutable reference (`&mut T`) to the object (also known as
-//! **mutability**).
-//!
-//! This is enforced by the Rust compiler. However, there are situations where
-//! this rule is not flexible enough. Sometimes it is required to have multiple
-//! references to an object and yet mutate it. In particular, QEMU objects
-//! usually have their pointer shared with the "outside world very early in
-//! their lifetime", for example when they create their
-//! [`MemoryRegion`s](crate::bindings::MemoryRegion). Therefore, individual
-//! parts of a device must be made mutable in a controlled manner; this module
-//! provides the tools to do so.
-//!
-//! ## Cell types
-//!
-//! [`BqlCell<T>`] and [`BqlRefCell<T>`] allow doing this via the Big QEMU Lock.
-//! While they are essentially the same single-threaded primitives that are
-//! available in `std::cell`, the BQL allows them to be used from a
-//! multi-threaded context and to share references across threads, while
-//! maintaining Rust's safety guarantees. For this reason, unlike
-//! their `std::cell` counterparts, `BqlCell` and `BqlRefCell` implement the
-//! `Sync` trait.
-//!
-//! BQL checks are performed in debug builds but can be optimized away in
-//! release builds, providing runtime safety during development with no overhead
-//! in production.
-//!
-//! The two provide different ways of handling interior mutability.
-//! `BqlRefCell` is best suited for data that is primarily accessed by the
-//! device's own methods, where multiple reads and writes can be grouped within
-//! a single borrow and a mutable reference can be passed around. Instead,
-//! [`BqlCell`] is a better choice when sharing small pieces of data with
-//! external code (especially C code), because it provides simple get/set
-//! operations that can be used one at a time.
-//!
-//! Warning: While `BqlCell` and `BqlRefCell` are similar to their `std::cell`
-//! counterparts, they are not interchangeable. Using `std::cell` types in
-//! QEMU device implementations is usually incorrect and can lead to
-//! thread-safety issues.
-//!
-//! ### Example
-//!
-//! ```
-//! # use qemu_api::prelude::*;
-//! # use qemu_api::{cell::BqlRefCell, irq::InterruptSource, irq::IRQState};
-//! # use qemu_api::{sysbus::SysBusDevice, qom::Owned, qom::ParentField};
-//! # const N_GPIOS: usize = 8;
-//! # struct PL061Registers { /* ... */ }
-//! # unsafe impl ObjectType for PL061State {
-//! # type Class = <SysBusDevice as ObjectType>::Class;
-//! # const TYPE_NAME: &'static std::ffi::CStr = c"pl061";
-//! # }
-//! struct PL061State {
-//! parent_obj: ParentField<SysBusDevice>,
-//!
-//! // Configuration is read-only after initialization
-//! pullups: u32,
-//! pulldowns: u32,
-//!
-//! // Single values shared with C code use BqlCell, in this case via InterruptSource
-//! out: [InterruptSource; N_GPIOS],
-//! interrupt: InterruptSource,
-//!
-//! // Larger state accessed by device methods uses BqlRefCell or Mutex
-//! registers: BqlRefCell<PL061Registers>,
-//! }
-//! ```
-//!
-//! ### `BqlCell<T>`
-//!
-//! [`BqlCell<T>`] implements interior mutability by moving values in and out of
-//! the cell. That is, an `&mut T` to the inner value can never be obtained as
-//! long as the cell is shared. The value itself cannot be directly obtained
-//! without copying it, cloning it, or replacing it with something else. This
-//! type provides the following methods, all of which can be called only while
-//! the BQL is held:
-//!
-//! - For types that implement [`Copy`], the [`get`](BqlCell::get) method
-//! retrieves the current interior value by duplicating it.
-//! - For types that implement [`Default`], the [`take`](BqlCell::take) method
-//! replaces the current interior value with [`Default::default()`] and
-//! returns the replaced value.
-//! - All types have:
-//! - [`replace`](BqlCell::replace): replaces the current interior value and
-//! returns the replaced value.
-//! - [`set`](BqlCell::set): this method replaces the interior value,
-//! dropping the replaced value.
-//!
-//! ### `BqlRefCell<T>`
-//!
-//! [`BqlRefCell<T>`] uses Rust's lifetimes to implement "dynamic borrowing", a
-//! process whereby one can claim temporary, exclusive, mutable access to the
-//! inner value:
-//!
-//! ```ignore
-//! fn clear_interrupts(&self, val: u32) {
-//! // A mutable borrow gives read-write access to the registers
-//! let mut regs = self.registers.borrow_mut();
-//! let old = regs.interrupt_status();
-//! regs.update_interrupt_status(old & !val);
-//! }
-//! ```
-//!
-//! Borrows for `BqlRefCell<T>`s are tracked at _runtime_, unlike Rust's native
-//! reference types which are entirely tracked statically, at compile time.
-//! Multiple immutable borrows are allowed via [`borrow`](BqlRefCell::borrow),
-//! 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 held.
-//!
-//! ## 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 structs
-//! often start their life uninitialized and may be populated lazily.
-//!
-//! For this reason, this module provides the [`Opaque<T>`] type to opt out
-//! of Rust's usual guarantees about the wrapped type. Access to the wrapped
-//! 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 actions
-//! require `unsafe` blocks, making it clear where safety guarantees must be
-//! manually verified. For example
-//!
-//! ```ignore
-//! unsafe {
-//! let state = Opaque::<MyStruct>::uninit();
-//! qemu_struct_init(state.as_mut_ptr());
-//! }
-//! ```
-//!
-//! [`Opaque<T>`] will usually be wrapped one level further, so that
-//! bridge methods can be added to the wrapper:
-//!
-//! ```ignore
-//! pub struct MyStruct(Opaque<bindings::MyStruct>);
-//!
-//! impl MyStruct {
-//! fn new() -> Pin<Box<MyStruct>> {
-//! let result = Box::pin(unsafe { Opaque::uninit() });
-//! unsafe { qemu_struct_init(result.as_mut_ptr()) };
-//! result
-//! }
-//! }
-//! ```
-//!
-//! This pattern of wrapping bindgen-generated types in [`Opaque<T>`] provides
-//! 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 wrapper
-//! type rather than being automatically derived from the C struct's layout
-//!
-//! * Methods can be implemented in a separate crate from the bindgen-generated
-//! 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<T>`] 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<T>`] is necessary for C interop, it should be used sparingly
-//! and only at FFI boundaries. For QEMU-specific types that need interior
-//! mutability, prefer [`BqlCell`] or [`BqlRefCell`].
-
-use std::{
- cell::{Cell, UnsafeCell},
- cmp::Ordering,
- fmt,
- marker::{PhantomData, PhantomPinned},
- mem::{self, MaybeUninit},
- ops::{Deref, DerefMut},
- ptr::NonNull,
-};
-
-use crate::bindings;
-
-/// An internal function that is used by doctests.
-pub fn bql_start_test() {
- if cfg!(MESON) {
- // SAFETY: integration tests are run with --test-threads=1, 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
- !cfg!(MESON) || unsafe { bindings::bql_locked() }
-}
-
-fn bql_block_unlock(increase: bool) {
- if cfg!(MESON) {
- // 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
-///
-/// `BqlCell<T>` has the same in-memory representation as its inner type `T`.
-#[repr(transparent)]
-pub struct BqlCell<T> {
- value: UnsafeCell<T>,
-}
-
-// SAFETY: Same as for std::sync::Mutex. In the end this *is* a Mutex,
-// except it is stored out-of-line
-unsafe impl<T: Send> Send for BqlCell<T> {}
-unsafe impl<T: Send> Sync for BqlCell<T> {}
-
-impl<T: Copy> Clone for BqlCell<T> {
- #[inline]
- fn clone(&self) -> BqlCell<T> {
- BqlCell::new(self.get())
- }
-}
-
-impl<T: Default> Default for BqlCell<T> {
- /// Creates a `BqlCell<T>`, with the `Default` value for T.
- #[inline]
- fn default() -> BqlCell<T> {
- BqlCell::new(Default::default())
- }
-}
-
-impl<T: PartialEq + Copy> PartialEq for BqlCell<T> {
- #[inline]
- fn eq(&self, other: &BqlCell<T>) -> bool {
- self.get() == other.get()
- }
-}
-
-impl<T: Eq + Copy> Eq for BqlCell<T> {}
-
-impl<T: PartialOrd + Copy> PartialOrd for BqlCell<T> {
- #[inline]
- fn partial_cmp(&self, other: &BqlCell<T>) -> Option<Ordering> {
- self.get().partial_cmp(&other.get())
- }
-}
-
-impl<T: Ord + Copy> Ord for BqlCell<T> {
- #[inline]
- fn cmp(&self, other: &BqlCell<T>) -> Ordering {
- self.get().cmp(&other.get())
- }
-}
-
-impl<T> From<T> for BqlCell<T> {
- /// Creates a new `BqlCell<T>` containing the given value.
- fn from(t: T) -> BqlCell<T> {
- BqlCell::new(t)
- }
-}
-
-impl<T: fmt::Debug + Copy> fmt::Debug for BqlCell<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.get().fmt(f)
- }
-}
-
-impl<T: fmt::Display + Copy> fmt::Display for BqlCell<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.get().fmt(f)
- }
-}
-
-impl<T> BqlCell<T> {
- /// Creates a new `BqlCell` containing the given value.
- ///
- /// # Examples
- ///
- /// ```
- /// use qemu_api::cell::BqlCell;
- /// # qemu_api::cell::bql_start_test();
- ///
- /// let c = BqlCell::new(5);
- /// ```
- #[inline]
- pub const fn new(value: T) -> BqlCell<T> {
- BqlCell {
- value: UnsafeCell::new(value),
- }
- }
-
- /// Sets the contained value.
- ///
- /// # Examples
- ///
- /// ```
- /// use qemu_api::cell::BqlCell;
- /// # qemu_api::cell::bql_start_test();
- ///
- /// let c = BqlCell::new(5);
- ///
- /// c.set(10);
- /// ```
- #[inline]
- pub fn set(&self, val: T) {
- self.replace(val);
- }
-
- /// Replaces the contained value with `val`, and returns the old contained
- /// value.
- ///
- /// # Examples
- ///
- /// ```
- /// use qemu_api::cell::BqlCell;
- /// # qemu_api::cell::bql_start_test();
- ///
- /// let cell = BqlCell::new(5);
- /// assert_eq!(cell.get(), 5);
- /// assert_eq!(cell.replace(10), 5);
- /// assert_eq!(cell.get(), 10);
- /// ```
- #[inline]
- pub fn replace(&self, val: T) -> T {
- assert!(bql_locked());
- // SAFETY: This can cause data races if called from multiple threads,
- // but it won't happen as long as C code accesses the value
- // under BQL protection only.
- mem::replace(unsafe { &mut *self.value.get() }, val)
- }
-
- /// Unwraps the value, consuming the cell.
- ///
- /// # Examples
- ///
- /// ```
- /// use qemu_api::cell::BqlCell;
- /// # qemu_api::cell::bql_start_test();
- ///
- /// let c = BqlCell::new(5);
- /// let five = c.into_inner();
- ///
- /// assert_eq!(five, 5);
- /// ```
- pub fn into_inner(self) -> T {
- assert!(bql_locked());
- self.value.into_inner()
- }
-}
-
-impl<T: Copy> BqlCell<T> {
- /// Returns a copy of the contained value.
- ///
- /// # Examples
- ///
- /// ```
- /// use qemu_api::cell::BqlCell;
- /// # qemu_api::cell::bql_start_test();
- ///
- /// let c = BqlCell::new(5);
- ///
- /// let five = c.get();
- /// ```
- #[inline]
- pub fn get(&self) -> T {
- assert!(bql_locked());
- // SAFETY: This can cause data races if called from multiple threads,
- // but it won't happen as long as C code accesses the value
- // under BQL protection only.
- unsafe { *self.value.get() }
- }
-}
-
-impl<T> BqlCell<T> {
- /// Returns a raw pointer to the underlying data in this cell.
- ///
- /// # Examples
- ///
- /// ```
- /// use qemu_api::cell::BqlCell;
- /// # qemu_api::cell::bql_start_test();
- ///
- /// let c = BqlCell::new(5);
- ///
- /// let ptr = c.as_ptr();
- /// ```
- #[inline]
- pub const fn as_ptr(&self) -> *mut T {
- self.value.get()
- }
-}
-
-impl<T: Default> BqlCell<T> {
- /// Takes the value of the cell, leaving `Default::default()` in its place.
- ///
- /// # Examples
- ///
- /// ```
- /// use qemu_api::cell::BqlCell;
- /// # qemu_api::cell::bql_start_test();
- ///
- /// let c = BqlCell::new(5);
- /// let five = c.take();
- ///
- /// assert_eq!(five, 5);
- /// assert_eq!(c.into_inner(), 0);
- /// ```
- pub fn take(&self) -> T {
- self.replace(Default::default())
- }
-}
-
-/// A mutable memory location with dynamically checked borrow rules,
-/// protected by the Big QEMU Lock.
-///
-/// See the [module-level documentation](self) for more.
-///
-/// # Memory layout
-///
-/// `BqlRefCell<T>` starts with the same in-memory representation as its
-/// inner type `T`.
-#[repr(C)]
-pub struct BqlRefCell<T> {
- // It is important that this is the first field (which is not the case
- // for std::cell::BqlRefCell), so that we can use offset_of! on it.
- // UnsafeCell and repr(C) both prevent usage of niches.
- value: UnsafeCell<T>,
- borrow: Cell<BorrowFlag>,
- // Stores the location of the earliest currently active borrow.
- // This gets updated whenever we go from having zero borrows
- // to having a single borrow. When a borrow occurs, this gets included
- // in the panic message
- #[cfg(feature = "debug_cell")]
- borrowed_at: Cell<Option<&'static std::panic::Location<'static>>>,
-}
-
-// Positive values represent the number of `BqlRef` active. Negative values
-// represent the number of `BqlRefMut` active. Right now QEMU's implementation
-// does not allow to create `BqlRefMut`s that refer to distinct, nonoverlapping
-// components of a `BqlRefCell` (e.g., different ranges of a slice).
-//
-// `BqlRef` and `BqlRefMut` are both two words in size, and so there will likely
-// never be enough `BqlRef`s or `BqlRefMut`s in existence to overflow half of
-// the `usize` range. Thus, a `BorrowFlag` will probably never overflow or
-// underflow. However, this is not a guarantee, as a pathological program could
-// repeatedly create and then mem::forget `BqlRef`s or `BqlRefMut`s. Thus, all
-// code must explicitly check for overflow and underflow in order to avoid
-// unsafety, or at least behave correctly in the event that overflow or
-// underflow happens (e.g., see BorrowRef::new).
-type BorrowFlag = isize;
-const UNUSED: BorrowFlag = 0;
-
-#[inline(always)]
-const fn is_writing(x: BorrowFlag) -> bool {
- x < UNUSED
-}
-
-#[inline(always)]
-const fn is_reading(x: BorrowFlag) -> bool {
- x > UNUSED
-}
-
-impl<T> BqlRefCell<T> {
- /// Creates a new `BqlRefCell` containing `value`.
- ///
- /// # Examples
- ///
- /// ```
- /// use qemu_api::cell::BqlRefCell;
- ///
- /// let c = BqlRefCell::new(5);
- /// ```
- #[inline]
- pub const fn new(value: T) -> BqlRefCell<T> {
- BqlRefCell {
- value: UnsafeCell::new(value),
- borrow: Cell::new(UNUSED),
- #[cfg(feature = "debug_cell")]
- borrowed_at: Cell::new(None),
- }
- }
-}
-
-// This ensures the panicking code is outlined from `borrow_mut` for
-// `BqlRefCell`.
-#[inline(never)]
-#[cold]
-#[cfg(feature = "debug_cell")]
-fn panic_already_borrowed(source: &Cell<Option<&'static std::panic::Location<'static>>>) -> ! {
- // If a borrow occurred, then we must already have an outstanding borrow,
- // so `borrowed_at` will be `Some`
- panic!("already borrowed at {:?}", source.take().unwrap())
-}
-
-#[inline(never)]
-#[cold]
-#[cfg(not(feature = "debug_cell"))]
-fn panic_already_borrowed() -> ! {
- panic!("already borrowed")
-}
-
-impl<T> BqlRefCell<T> {
- #[inline]
- #[allow(clippy::unused_self)]
- fn panic_already_borrowed(&self) -> ! {
- #[cfg(feature = "debug_cell")]
- {
- panic_already_borrowed(&self.borrowed_at)
- }
- #[cfg(not(feature = "debug_cell"))]
- {
- panic_already_borrowed()
- }
- }
-
- /// Immutably borrows the wrapped value.
- ///
- /// The borrow lasts until the returned `BqlRef` exits scope. Multiple
- /// immutable borrows can be taken out at the same time.
- ///
- /// # Panics
- ///
- /// Panics if the value is currently mutably borrowed.
- ///
- /// # Examples
- ///
- /// ```
- /// use qemu_api::cell::BqlRefCell;
- /// # qemu_api::cell::bql_start_test();
- ///
- /// let c = BqlRefCell::new(5);
- ///
- /// let borrowed_five = c.borrow();
- /// let borrowed_five2 = c.borrow();
- /// ```
- ///
- /// An example of panic:
- ///
- /// ```should_panic
- /// use qemu_api::cell::BqlRefCell;
- /// # qemu_api::cell::bql_start_test();
- ///
- /// let c = BqlRefCell::new(5);
- ///
- /// let m = c.borrow_mut();
- /// let b = c.borrow(); // this causes a panic
- /// ```
- #[inline]
- #[track_caller]
- pub fn borrow(&self) -> BqlRef<'_, T> {
- if let Some(b) = BorrowRef::new(&self.borrow) {
- // `borrowed_at` is always the *first* active borrow
- if b.borrow.get() == 1 {
- #[cfg(feature = "debug_cell")]
- self.borrowed_at.set(Some(std::panic::Location::caller()));
- }
-
- bql_block_unlock(true);
-
- // SAFETY: `BorrowRef` ensures that there is only immutable access
- // to the value while borrowed.
- let value = unsafe { NonNull::new_unchecked(self.value.get()) };
- BqlRef { value, borrow: b }
- } else {
- self.panic_already_borrowed()
- }
- }
-
- /// Mutably borrows the wrapped value.
- ///
- /// The borrow lasts until the returned `BqlRefMut` or all `BqlRefMut`s
- /// derived from it exit scope. The value cannot be borrowed while this
- /// borrow is active.
- ///
- /// # Panics
- ///
- /// Panics if the value is currently borrowed.
- ///
- /// # Examples
- ///
- /// ```
- /// use qemu_api::cell::BqlRefCell;
- /// # qemu_api::cell::bql_start_test();
- ///
- /// let c = BqlRefCell::new("hello".to_owned());
- ///
- /// *c.borrow_mut() = "bonjour".to_owned();
- ///
- /// assert_eq!(&*c.borrow(), "bonjour");
- /// ```
- ///
- /// An example of panic:
- ///
- /// ```should_panic
- /// use qemu_api::cell::BqlRefCell;
- /// # qemu_api::cell::bql_start_test();
- ///
- /// let c = BqlRefCell::new(5);
- /// let m = c.borrow();
- ///
- /// let b = c.borrow_mut(); // this causes a panic
- /// ```
- #[inline]
- #[track_caller]
- pub fn borrow_mut(&self) -> BqlRefMut<'_, T> {
- if let Some(b) = BorrowRefMut::new(&self.borrow) {
- #[cfg(feature = "debug_cell")]
- {
- self.borrowed_at.set(Some(std::panic::Location::caller()));
- }
-
- // SAFETY: this only adjusts a counter
- bql_block_unlock(true);
-
- // SAFETY: `BorrowRefMut` guarantees unique access.
- let value = unsafe { NonNull::new_unchecked(self.value.get()) };
- BqlRefMut {
- value,
- _borrow: b,
- marker: PhantomData,
- }
- } else {
- self.panic_already_borrowed()
- }
- }
-
- /// Returns a raw pointer to the underlying data in this cell.
- ///
- /// # Examples
- ///
- /// ```
- /// use qemu_api::cell::BqlRefCell;
- ///
- /// let c = BqlRefCell::new(5);
- ///
- /// let ptr = c.as_ptr();
- /// ```
- #[inline]
- pub const fn as_ptr(&self) -> *mut T {
- self.value.get()
- }
-}
-
-// SAFETY: Same as for std::sync::Mutex. In the end this is a Mutex that is
-// stored out-of-line. Even though BqlRefCell includes Cells, they are
-// themselves protected by the Big QEMU Lock. Furtheremore, the Big QEMU
-// Lock cannot be released while any borrows is active.
-unsafe impl<T> Send for BqlRefCell<T> where T: Send {}
-unsafe impl<T> Sync for BqlRefCell<T> {}
-
-impl<T: Clone> Clone for BqlRefCell<T> {
- /// # Panics
- ///
- /// Panics if the value is currently mutably borrowed.
- #[inline]
- #[track_caller]
- fn clone(&self) -> BqlRefCell<T> {
- BqlRefCell::new(self.borrow().clone())
- }
-
- /// # Panics
- ///
- /// Panics if `source` is currently mutably borrowed.
- #[inline]
- #[track_caller]
- fn clone_from(&mut self, source: &Self) {
- self.value.get_mut().clone_from(&source.borrow())
- }
-}
-
-impl<T: Default> Default for BqlRefCell<T> {
- /// Creates a `BqlRefCell<T>`, with the `Default` value for T.
- #[inline]
- fn default() -> BqlRefCell<T> {
- BqlRefCell::new(Default::default())
- }
-}
-
-impl<T: PartialEq> PartialEq for BqlRefCell<T> {
- /// # Panics
- ///
- /// Panics if the value in either `BqlRefCell` is currently mutably
- /// borrowed.
- #[inline]
- fn eq(&self, other: &BqlRefCell<T>) -> bool {
- *self.borrow() == *other.borrow()
- }
-}
-
-impl<T: Eq> Eq for BqlRefCell<T> {}
-
-impl<T: PartialOrd> PartialOrd for BqlRefCell<T> {
- /// # Panics
- ///
- /// Panics if the value in either `BqlRefCell` is currently mutably
- /// borrowed.
- #[inline]
- fn partial_cmp(&self, other: &BqlRefCell<T>) -> Option<Ordering> {
- self.borrow().partial_cmp(&*other.borrow())
- }
-}
-
-impl<T: Ord> Ord for BqlRefCell<T> {
- /// # Panics
- ///
- /// Panics if the value in either `BqlRefCell` is currently mutably
- /// borrowed.
- #[inline]
- fn cmp(&self, other: &BqlRefCell<T>) -> Ordering {
- self.borrow().cmp(&*other.borrow())
- }
-}
-
-impl<T> From<T> for BqlRefCell<T> {
- /// Creates a new `BqlRefCell<T>` containing the given value.
- fn from(t: T) -> BqlRefCell<T> {
- BqlRefCell::new(t)
- }
-}
-
-struct BorrowRef<'b> {
- borrow: &'b Cell<BorrowFlag>,
-}
-
-impl<'b> BorrowRef<'b> {
- #[inline]
- fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> {
- let b = borrow.get().wrapping_add(1);
- if !is_reading(b) {
- // Incrementing borrow can result in a non-reading value (<= 0) in these cases:
- // 1. It was < 0, i.e. there are writing borrows, so we can't allow a read
- // borrow due to Rust's reference aliasing rules
- // 2. It was isize::MAX (the max amount of reading borrows) and it overflowed
- // into isize::MIN (the max amount of writing borrows) so we can't allow an
- // additional read borrow because isize can't represent so many read borrows
- // (this can only happen if you mem::forget more than a small constant amount
- // of `BqlRef`s, which is not good practice)
- None
- } else {
- // Incrementing borrow can result in a reading value (> 0) in these cases:
- // 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read
- // borrow
- // 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize is
- // large enough to represent having one more read borrow
- borrow.set(b);
- Some(BorrowRef { borrow })
- }
- }
-}
-
-impl Drop for BorrowRef<'_> {
- #[inline]
- fn drop(&mut self) {
- let borrow = self.borrow.get();
- debug_assert!(is_reading(borrow));
- self.borrow.set(borrow - 1);
- bql_block_unlock(false)
- }
-}
-
-impl Clone for BorrowRef<'_> {
- #[inline]
- fn clone(&self) -> Self {
- BorrowRef::new(self.borrow).unwrap()
- }
-}
-
-/// Wraps a borrowed reference to a value in a `BqlRefCell` box.
-/// A wrapper type for an immutably borrowed value from a `BqlRefCell<T>`.
-///
-/// See the [module-level documentation](self) for more.
-pub struct BqlRef<'b, T: 'b> {
- // NB: we use a pointer instead of `&'b T` to avoid `noalias` violations, because a
- // `BqlRef` argument doesn't hold immutability for its whole scope, only until it drops.
- // `NonNull` is also covariant over `T`, just like we would have with `&T`.
- value: NonNull<T>,
- borrow: BorrowRef<'b>,
-}
-
-impl<T> Deref for BqlRef<'_, T> {
- type Target = T;
-
- #[inline]
- fn deref(&self) -> &T {
- // SAFETY: the value is accessible as long as we hold our borrow.
- unsafe { self.value.as_ref() }
- }
-}
-
-impl<'b, T> BqlRef<'b, T> {
- /// Copies a `BqlRef`.
- ///
- /// The `BqlRefCell` is already immutably borrowed, so this cannot fail.
- ///
- /// This is an associated function that needs to be used as
- /// `BqlRef::clone(...)`. A `Clone` implementation or a method would
- /// interfere with the widespread use of `r.borrow().clone()` to clone
- /// the contents of a `BqlRefCell`.
- #[must_use]
- #[inline]
- #[allow(clippy::should_implement_trait)]
- pub fn clone(orig: &BqlRef<'b, T>) -> BqlRef<'b, T> {
- BqlRef {
- value: orig.value,
- borrow: orig.borrow.clone(),
- }
- }
-}
-
-impl<T: fmt::Debug> fmt::Debug for BqlRef<'_, T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- (**self).fmt(f)
- }
-}
-
-impl<T: fmt::Display> fmt::Display for BqlRef<'_, T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- (**self).fmt(f)
- }
-}
-
-struct BorrowRefMut<'b> {
- borrow: &'b Cell<BorrowFlag>,
-}
-
-impl<'b> BorrowRefMut<'b> {
- #[inline]
- fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> {
- // There must currently be no existing references when borrow_mut() is
- // called, so we explicitly only allow going from UNUSED to UNUSED - 1.
- match borrow.get() {
- UNUSED => {
- borrow.set(UNUSED - 1);
- Some(BorrowRefMut { borrow })
- }
- _ => None,
- }
- }
-}
-
-impl Drop for BorrowRefMut<'_> {
- #[inline]
- fn drop(&mut self) {
- let borrow = self.borrow.get();
- debug_assert!(is_writing(borrow));
- self.borrow.set(borrow + 1);
- bql_block_unlock(false)
- }
-}
-
-/// A wrapper type for a mutably borrowed value from a `BqlRefCell<T>`.
-///
-/// See the [module-level documentation](self) for more.
-pub struct BqlRefMut<'b, T: 'b> {
- // NB: we use a pointer instead of `&'b mut T` to avoid `noalias` violations, because a
- // `BqlRefMut` argument doesn't hold exclusivity for its whole scope, only until it drops.
- value: NonNull<T>,
- _borrow: BorrowRefMut<'b>,
- // `NonNull` is covariant over `T`, so we need to reintroduce invariance.
- marker: PhantomData<&'b mut T>,
-}
-
-impl<T> Deref for BqlRefMut<'_, T> {
- type Target = T;
-
- #[inline]
- fn deref(&self) -> &T {
- // SAFETY: the value is accessible as long as we hold our borrow.
- unsafe { self.value.as_ref() }
- }
-}
-
-impl<T> DerefMut for BqlRefMut<'_, T> {
- #[inline]
- fn deref_mut(&mut self) -> &mut T {
- // SAFETY: the value is accessible as long as we hold our borrow.
- unsafe { self.value.as_mut() }
- }
-}
-
-impl<T: fmt::Debug> fmt::Debug for BqlRefMut<'_, T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- (**self).fmt(f)
- }
-}
-
-impl<T: fmt::Display> fmt::Display for BqlRefMut<'_, T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- (**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 Rust's
-/// strict aliasing rules, which normally prevent mutation through shared
-/// references.
-///
-/// Wrapping the struct with `Opaque<T>` ensures that the Rust compiler does not
-/// assume the usual constraints that Rust structs require, and allows using
-/// shared references on the Rust side.
-///
-/// `Opaque<T>` is `#[repr(transparent)]`, so that it matches the memory layout
-/// of `T`.
-#[repr(transparent)]
-pub struct Opaque<T> {
- value: UnsafeCell<MaybeUninit<T>>,
- // PhantomPinned also allows multiple references to the `Opaque<T>`, i.e.
- // one `&mut Opaque<T>` can coexist with a `&mut T` or any number of `&T`;
- // see https://docs.rs/pinned-aliasable/latest/pinned_aliasable/.
- _pin: PhantomPinned,
-}
-
-impl<T> Opaque<T> {
- /// Creates a new shared reference from a C pointer
- ///
- /// # Safety
- ///
- /// The pointer must be valid, though it need not point to a valid value.
- pub unsafe fn from_raw<'a>(ptr: *mut T) -> &'a Self {
- let ptr = NonNull::new(ptr).unwrap().cast::<Self>();
- // 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 function,
- /// but the functions containing the dereference are usually safe. The
- /// value returned from `uninit()` must be initialized and pinned before
- /// 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 function,
- /// but the functions containing the dereference are usually safe. The
- /// value returned from `uninit()` must be pinned (and possibly initialized)
- /// 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 UnsafeCell
- // because it takes a *const Self instead.
- slot.cast()
- }
-}
-
-impl<T> fmt::Debug for Opaque<T> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let mut name: String = "Opaque<".to_string();
- name += std::any::type_name::<T>();
- name += ">";
- f.debug_tuple(&name).field(&self.as_ptr()).finish()
- }
-}
-
-impl<T: Default> Opaque<T> {
- /// 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 function,
- /// 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<String>,
-/// }
-///
-/// unsafe impl Wrapper for Example {
-/// type Wrapped = 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 following
-/// methods:
-///
-/// ```ignore
-/// pub const unsafe fn from_raw<'a>(value: *mut Self::Wrapped) -> &'a Self;
-/// 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<T> Wrapper for Opaque<T> {
- type Wrapped = T;
-}
diff --git a/rust/qemu-api/src/chardev.rs b/rust/qemu-api/src/chardev.rs
deleted file mode 100644
index 6e0590d..0000000
--- a/rust/qemu-api/src/chardev.rs
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2024 Red Hat, Inc.
-// Author(s): Paolo Bonzini <pbonzini@redhat.com>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! Bindings for character devices
-//!
-//! Character devices in QEMU can run under the big QEMU lock or in a separate
-//! `GMainContext`. Here we only support the former, because the bindings
-//! enforce that the BQL is taken whenever the functions in [`CharBackend`] are
-//! called.
-
-use std::{
- ffi::{c_int, c_void, CStr},
- fmt::{self, Debug},
- io::{self, ErrorKind, Write},
- marker::PhantomPinned,
- ptr::addr_of_mut,
- slice,
-};
-
-use crate::{
- bindings,
- callbacks::FnCall,
- cell::{BqlRefMut, Opaque},
- prelude::*,
-};
-
-/// A safe wrapper around [`bindings::Chardev`].
-#[repr(transparent)]
-#[derive(qemu_api_macros::Wrapper)]
-pub struct Chardev(Opaque<bindings::Chardev>);
-
-pub type ChardevClass = bindings::ChardevClass;
-pub type Event = bindings::QEMUChrEvent;
-
-/// A safe wrapper around [`bindings::CharBackend`], denoting the character
-/// back-end that is used for example by a device. Compared to the
-/// underlying C struct it adds BQL protection, and is marked as pinned
-/// because the QOM object ([`bindings::Chardev`]) contains a pointer to
-/// the `CharBackend`.
-pub struct CharBackend {
- inner: BqlRefCell<bindings::CharBackend>,
- _pin: PhantomPinned,
-}
-
-impl Write for BqlRefMut<'_, bindings::CharBackend> {
- fn flush(&mut self) -> io::Result<()> {
- Ok(())
- }
-
- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
- let chr: &mut bindings::CharBackend = self;
-
- let len = buf.len().try_into().unwrap();
- let r = unsafe { bindings::qemu_chr_fe_write(addr_of_mut!(*chr), buf.as_ptr(), len) };
- errno::into_io_result(r).map(|cnt| cnt as usize)
- }
-
- fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
- let chr: &mut bindings::CharBackend = self;
-
- let len = buf.len().try_into().unwrap();
- let r = unsafe { bindings::qemu_chr_fe_write_all(addr_of_mut!(*chr), buf.as_ptr(), len) };
- errno::into_io_result(r).and_then(|cnt| {
- if cnt as usize == buf.len() {
- Ok(())
- } else {
- Err(ErrorKind::WriteZero.into())
- }
- })
- }
-}
-
-impl Debug for CharBackend {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // SAFETY: accessed just to print the values
- let chr = self.inner.as_ptr();
- Debug::fmt(unsafe { &*chr }, f)
- }
-}
-
-// FIXME: use something like PinnedDrop from the pinned_init crate
-impl Drop for CharBackend {
- fn drop(&mut self) {
- self.disable_handlers();
- }
-}
-
-impl CharBackend {
- /// Enable the front-end's character device handlers, if there is an
- /// associated `Chardev`.
- pub fn enable_handlers<
- 'chardev,
- 'owner: 'chardev,
- T,
- CanReceiveFn: for<'a> FnCall<(&'a T,), u32>,
- ReceiveFn: for<'a, 'b> FnCall<(&'a T, &'b [u8])>,
- EventFn: for<'a> FnCall<(&'a T, Event)>,
- >(
- // When "self" is dropped, the handlers are automatically disabled.
- // However, this is not necessarily true if the owner is dropped.
- // So require the owner to outlive the character device.
- &'chardev self,
- owner: &'owner T,
- _can_receive: CanReceiveFn,
- _receive: ReceiveFn,
- _event: EventFn,
- ) {
- unsafe extern "C" fn rust_can_receive_cb<T, F: for<'a> FnCall<(&'a T,), u32>>(
- opaque: *mut c_void,
- ) -> c_int {
- // SAFETY: the values are safe according to the contract of
- // enable_handlers() and qemu_chr_fe_set_handlers()
- let owner: &T = unsafe { &*(opaque.cast::<T>()) };
- let r = F::call((owner,));
- r.try_into().unwrap()
- }
-
- unsafe extern "C" fn rust_receive_cb<T, F: for<'a, 'b> FnCall<(&'a T, &'b [u8])>>(
- opaque: *mut c_void,
- buf: *const u8,
- size: c_int,
- ) {
- // SAFETY: the values are safe according to the contract of
- // enable_handlers() and qemu_chr_fe_set_handlers()
- let owner: &T = unsafe { &*(opaque.cast::<T>()) };
- let buf = unsafe { slice::from_raw_parts(buf, size.try_into().unwrap()) };
- F::call((owner, buf))
- }
-
- unsafe extern "C" fn rust_event_cb<T, F: for<'a> FnCall<(&'a T, Event)>>(
- opaque: *mut c_void,
- event: Event,
- ) {
- // SAFETY: the values are safe according to the contract of
- // enable_handlers() and qemu_chr_fe_set_handlers()
- let owner: &T = unsafe { &*(opaque.cast::<T>()) };
- F::call((owner, event))
- }
-
- let _: () = CanReceiveFn::ASSERT_IS_SOME;
- let receive_cb: Option<unsafe extern "C" fn(*mut c_void, *const u8, c_int)> =
- if ReceiveFn::is_some() {
- Some(rust_receive_cb::<T, ReceiveFn>)
- } else {
- None
- };
- let event_cb: Option<unsafe extern "C" fn(*mut c_void, Event)> = if EventFn::is_some() {
- Some(rust_event_cb::<T, EventFn>)
- } else {
- None
- };
-
- let mut chr = self.inner.borrow_mut();
- // SAFETY: the borrow promises that the BQL is taken
- unsafe {
- bindings::qemu_chr_fe_set_handlers(
- addr_of_mut!(*chr),
- Some(rust_can_receive_cb::<T, CanReceiveFn>),
- receive_cb,
- event_cb,
- None,
- (owner as *const T).cast_mut().cast::<c_void>(),
- core::ptr::null_mut(),
- true,
- );
- }
- }
-
- /// Disable the front-end's character device handlers.
- pub fn disable_handlers(&self) {
- let mut chr = self.inner.borrow_mut();
- // SAFETY: the borrow promises that the BQL is taken
- unsafe {
- bindings::qemu_chr_fe_set_handlers(
- addr_of_mut!(*chr),
- None,
- None,
- None,
- None,
- core::ptr::null_mut(),
- core::ptr::null_mut(),
- true,
- );
- }
- }
-
- /// Notify that the frontend is ready to receive data.
- pub fn accept_input(&self) {
- let mut chr = self.inner.borrow_mut();
- // SAFETY: the borrow promises that the BQL is taken
- unsafe { bindings::qemu_chr_fe_accept_input(addr_of_mut!(*chr)) }
- }
-
- /// Temporarily borrow the character device, allowing it to be used
- /// as an implementor of `Write`. Note that it is not valid to drop
- /// 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()
- }
-
- /// Send a continuous stream of zero bits on the line if `enabled` is
- /// true, or a short stream if `enabled` is false.
- pub fn send_break(&self, long: bool) -> io::Result<()> {
- let mut chr = self.inner.borrow_mut();
- let mut duration: c_int = long.into();
- // SAFETY: the borrow promises that the BQL is taken
- let r = unsafe {
- bindings::qemu_chr_fe_ioctl(
- addr_of_mut!(*chr),
- bindings::CHR_IOCTL_SERIAL_SET_BREAK as i32,
- addr_of_mut!(duration).cast::<c_void>(),
- )
- };
-
- errno::into_io_result(r).map(|_| ())
- }
-
- /// Write data to a character backend from the front end. This function
- /// will send data from the front end to the back end. Unlike
- /// `write`, this function will block if the back end cannot
- /// consume all of the data attempted to be written.
- ///
- /// Returns the number of bytes consumed (0 if no associated Chardev) or an
- /// error.
- pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
- let len = buf.len().try_into().unwrap();
- // SAFETY: qemu_chr_fe_write is thread-safe
- let r = unsafe { bindings::qemu_chr_fe_write(self.inner.as_ptr(), buf.as_ptr(), len) };
- errno::into_io_result(r).map(|cnt| cnt as usize)
- }
-
- /// Write data to a character backend from the front end. This function
- /// will send data from the front end to the back end. Unlike
- /// `write`, this function will block if the back end cannot
- /// consume all of the data attempted to be written.
- ///
- /// Returns the number of bytes consumed (0 if no associated Chardev) or an
- /// error.
- pub fn write_all(&self, buf: &[u8]) -> io::Result<()> {
- let len = buf.len().try_into().unwrap();
- // SAFETY: qemu_chr_fe_write_all is thread-safe
- let r = unsafe { bindings::qemu_chr_fe_write_all(self.inner.as_ptr(), buf.as_ptr(), len) };
- errno::into_io_result(r).and_then(|cnt| {
- if cnt as usize == buf.len() {
- Ok(())
- } else {
- Err(ErrorKind::WriteZero.into())
- }
- })
- }
-}
-
-unsafe impl ObjectType for Chardev {
- type Class = ChardevClass;
- const TYPE_NAME: &'static CStr =
- unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_CHARDEV) };
-}
-qom_isa!(Chardev: Object);
diff --git a/rust/qemu-api/src/errno.rs b/rust/qemu-api/src/errno.rs
deleted file mode 100644
index 18d1014..0000000
--- a/rust/qemu-api/src/errno.rs
+++ /dev/null
@@ -1,345 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! Utility functions to convert `errno` to and from
-//! [`io::Error`]/[`io::Result`]
-//!
-//! QEMU C functions often have a "positive success/negative `errno`" calling
-//! convention. This module provides functions to portably convert an integer
-//! into an [`io::Result`] and back.
-
-use std::{convert::TryFrom, io, io::ErrorKind};
-
-/// An `errno` value that can be converted into an [`io::Error`]
-pub struct Errno(pub u16);
-
-// On Unix, from_raw_os_error takes an errno value and OS errors
-// are printed using strerror. On Windows however it takes a
-// GetLastError() value; therefore we need to convert errno values
-// into io::Error by hand. This is the same mapping that the
-// standard library uses to retrieve the kind of OS errors
-// (`std::sys::pal::unix::decode_error_kind`).
-impl From<Errno> for ErrorKind {
- fn from(value: Errno) -> ErrorKind {
- use ErrorKind::*;
- let Errno(errno) = value;
- match i32::from(errno) {
- libc::EPERM | libc::EACCES => PermissionDenied,
- libc::ENOENT => NotFound,
- libc::EINTR => Interrupted,
- x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock,
- libc::ENOMEM => OutOfMemory,
- libc::EEXIST => AlreadyExists,
- libc::EINVAL => InvalidInput,
- libc::EPIPE => BrokenPipe,
- libc::EADDRINUSE => AddrInUse,
- libc::EADDRNOTAVAIL => AddrNotAvailable,
- libc::ECONNABORTED => ConnectionAborted,
- libc::ECONNREFUSED => ConnectionRefused,
- libc::ECONNRESET => ConnectionReset,
- libc::ENOTCONN => NotConnected,
- libc::ENOTSUP => Unsupported,
- libc::ETIMEDOUT => TimedOut,
- _ => Other,
- }
- }
-}
-
-// This is used on Windows for all io::Errors, but also on Unix if the
-// io::Error does not have a raw OS error. This is the reversed
-// mapping of the above; EIO is returned for unknown ErrorKinds.
-impl From<io::ErrorKind> for Errno {
- fn from(value: io::ErrorKind) -> Errno {
- use ErrorKind::*;
- let errno = match value {
- // can be both EPERM or EACCES :( pick one
- PermissionDenied => libc::EPERM,
- NotFound => libc::ENOENT,
- Interrupted => libc::EINTR,
- WouldBlock => libc::EAGAIN,
- OutOfMemory => libc::ENOMEM,
- AlreadyExists => libc::EEXIST,
- InvalidInput => libc::EINVAL,
- BrokenPipe => libc::EPIPE,
- AddrInUse => libc::EADDRINUSE,
- AddrNotAvailable => libc::EADDRNOTAVAIL,
- ConnectionAborted => libc::ECONNABORTED,
- ConnectionRefused => libc::ECONNREFUSED,
- ConnectionReset => libc::ECONNRESET,
- NotConnected => libc::ENOTCONN,
- Unsupported => libc::ENOTSUP,
- TimedOut => libc::ETIMEDOUT,
- _ => libc::EIO,
- };
- Errno(errno as u16)
- }
-}
-
-impl From<Errno> for io::Error {
- #[cfg(unix)]
- fn from(value: Errno) -> io::Error {
- let Errno(errno) = value;
- io::Error::from_raw_os_error(errno.into())
- }
-
- #[cfg(windows)]
- fn from(value: Errno) -> io::Error {
- let error_kind: ErrorKind = value.into();
- error_kind.into()
- }
-}
-
-impl From<io::Error> for Errno {
- fn from(value: io::Error) -> Errno {
- if cfg!(unix) {
- if let Some(errno) = value.raw_os_error() {
- return Errno(u16::try_from(errno).unwrap());
- }
- }
- value.kind().into()
- }
-}
-
-/// Internal traits; used to enable [`into_io_result`] and [`into_neg_errno`]
-/// for the "right" set of types.
-mod traits {
- use super::Errno;
-
- /// A signed type that can be converted into an
- /// [`io::Result`](std::io::Result)
- pub trait GetErrno {
- /// Unsigned variant of `Self`, used as the type for the `Ok` case.
- type Out;
-
- /// Return `Ok(self)` if positive, `Err(Errno(-self))` if negative
- fn into_errno_result(self) -> Result<Self::Out, Errno>;
- }
-
- /// A type that can be taken out of an [`io::Result`](std::io::Result) and
- /// converted into "positive success/negative `errno`" convention.
- pub trait MergeErrno {
- /// Signed variant of `Self`, used as the return type of
- /// [`into_neg_errno`](super::into_neg_errno).
- type Out: From<u16> + std::ops::Neg<Output = Self::Out>;
-
- /// Return `self`, asserting that it is in range
- fn map_ok(self) -> Self::Out;
- }
-
- macro_rules! get_errno {
- ($t:ty, $out:ty) => {
- impl GetErrno for $t {
- type Out = $out;
- fn into_errno_result(self) -> Result<Self::Out, Errno> {
- match self {
- 0.. => Ok(self as $out),
- -65535..=-1 => Err(Errno(-self as u16)),
- _ => panic!("{self} is not a negative errno"),
- }
- }
- }
- };
- }
-
- get_errno!(i32, u32);
- get_errno!(i64, u64);
- get_errno!(isize, usize);
-
- macro_rules! merge_errno {
- ($t:ty, $out:ty) => {
- impl MergeErrno for $t {
- type Out = $out;
- fn map_ok(self) -> Self::Out {
- self.try_into().unwrap()
- }
- }
- };
- }
-
- merge_errno!(u8, i32);
- merge_errno!(u16, i32);
- merge_errno!(u32, i32);
- merge_errno!(u64, i64);
-
- impl MergeErrno for () {
- type Out = i32;
- fn map_ok(self) -> i32 {
- 0
- }
- }
-}
-
-use traits::{GetErrno, MergeErrno};
-
-/// Convert an integer value into a [`io::Result`].
-///
-/// Positive values are turned into an `Ok` result; negative values
-/// are interpreted as negated `errno` and turned into an `Err`.
-///
-/// ```
-/// # use qemu_api::errno::into_io_result;
-/// # use std::io::ErrorKind;
-/// let ok = into_io_result(1i32).unwrap();
-/// assert_eq!(ok, 1u32);
-///
-/// let err = into_io_result(-1i32).unwrap_err(); // -EPERM
-/// assert_eq!(err.kind(), ErrorKind::PermissionDenied);
-/// ```
-///
-/// # Panics
-///
-/// Since the result is an unsigned integer, negative values must
-/// be close to 0; values that are too far away are considered
-/// likely overflows and will panic:
-///
-/// ```should_panic
-/// # use qemu_api::errno::into_io_result;
-/// # #[allow(dead_code)]
-/// let err = into_io_result(-0x1234_5678i32); // panic
-/// ```
-pub fn into_io_result<T: GetErrno>(value: T) -> io::Result<T::Out> {
- value.into_errno_result().map_err(Into::into)
-}
-
-/// Convert a [`Result`] into an integer value, using negative `errno`
-/// values to report errors.
-///
-/// ```
-/// # use qemu_api::errno::into_neg_errno;
-/// # use std::io::{self, ErrorKind};
-/// let ok: io::Result<()> = Ok(());
-/// assert_eq!(into_neg_errno(ok), 0);
-///
-/// let err: io::Result<()> = Err(ErrorKind::InvalidInput.into());
-/// assert_eq!(into_neg_errno(err), -22); // -EINVAL
-/// ```
-///
-/// Since this module also provides the ability to convert [`io::Error`]
-/// to an `errno` value, [`io::Result`] is the most commonly used type
-/// for the argument of this function:
-///
-/// # Panics
-///
-/// Since the result is a signed integer, integer `Ok` values must remain
-/// positive:
-///
-/// ```should_panic
-/// # use qemu_api::errno::into_neg_errno;
-/// # use std::io;
-/// let err: io::Result<u32> = Ok(0x8899_AABB);
-/// into_neg_errno(err) // panic
-/// # ;
-/// ```
-pub fn into_neg_errno<T: MergeErrno, E: Into<Errno>>(value: Result<T, E>) -> T::Out {
- match value {
- Ok(x) => x.map_ok(),
- Err(err) => -T::Out::from(err.into().0),
- }
-}
-
-#[cfg(test)]
-mod tests {
- use std::io::ErrorKind;
-
- use super::*;
- use crate::assert_match;
-
- #[test]
- pub fn test_from_u8() {
- let ok: io::Result<_> = Ok(42u8);
- assert_eq!(into_neg_errno(ok), 42);
-
- let err: io::Result<u8> = Err(io::ErrorKind::PermissionDenied.into());
- assert_eq!(into_neg_errno(err), -1);
-
- if cfg!(unix) {
- let os_err: io::Result<u8> = Err(io::Error::from_raw_os_error(10));
- assert_eq!(into_neg_errno(os_err), -10);
- }
- }
-
- #[test]
- pub fn test_from_u16() {
- let ok: io::Result<_> = Ok(1234u16);
- assert_eq!(into_neg_errno(ok), 1234);
-
- let err: io::Result<u16> = Err(io::ErrorKind::PermissionDenied.into());
- assert_eq!(into_neg_errno(err), -1);
-
- if cfg!(unix) {
- let os_err: io::Result<u16> = Err(io::Error::from_raw_os_error(10));
- assert_eq!(into_neg_errno(os_err), -10);
- }
- }
-
- #[test]
- pub fn test_i32() {
- assert_match!(into_io_result(1234i32), Ok(1234));
-
- let err = into_io_result(-1i32).unwrap_err();
- #[cfg(unix)]
- assert_match!(err.raw_os_error(), Some(1));
- assert_match!(err.kind(), ErrorKind::PermissionDenied);
- }
-
- #[test]
- pub fn test_from_u32() {
- let ok: io::Result<_> = Ok(1234u32);
- assert_eq!(into_neg_errno(ok), 1234);
-
- let err: io::Result<u32> = Err(io::ErrorKind::PermissionDenied.into());
- assert_eq!(into_neg_errno(err), -1);
-
- if cfg!(unix) {
- let os_err: io::Result<u32> = Err(io::Error::from_raw_os_error(10));
- assert_eq!(into_neg_errno(os_err), -10);
- }
- }
-
- #[test]
- pub fn test_i64() {
- assert_match!(into_io_result(1234i64), Ok(1234));
-
- let err = into_io_result(-22i64).unwrap_err();
- #[cfg(unix)]
- assert_match!(err.raw_os_error(), Some(22));
- assert_match!(err.kind(), ErrorKind::InvalidInput);
- }
-
- #[test]
- pub fn test_from_u64() {
- let ok: io::Result<_> = Ok(1234u64);
- assert_eq!(into_neg_errno(ok), 1234);
-
- let err: io::Result<u64> = Err(io::ErrorKind::InvalidInput.into());
- assert_eq!(into_neg_errno(err), -22);
-
- if cfg!(unix) {
- let os_err: io::Result<u64> = Err(io::Error::from_raw_os_error(6));
- assert_eq!(into_neg_errno(os_err), -6);
- }
- }
-
- #[test]
- pub fn test_isize() {
- assert_match!(into_io_result(1234isize), Ok(1234));
-
- let err = into_io_result(-4isize).unwrap_err();
- #[cfg(unix)]
- assert_match!(err.raw_os_error(), Some(4));
- assert_match!(err.kind(), ErrorKind::Interrupted);
- }
-
- #[test]
- pub fn test_from_unit() {
- let ok: io::Result<_> = Ok(());
- assert_eq!(into_neg_errno(ok), 0);
-
- let err: io::Result<()> = Err(io::ErrorKind::OutOfMemory.into());
- assert_eq!(into_neg_errno(err), -12);
-
- if cfg!(unix) {
- let os_err: io::Result<()> = Err(io::Error::from_raw_os_error(2));
- assert_eq!(into_neg_errno(os_err), -2);
- }
- }
-}
diff --git a/rust/qemu-api/src/irq.rs b/rust/qemu-api/src/irq.rs
deleted file mode 100644
index 1526e6f..0000000
--- a/rust/qemu-api/src/irq.rs
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2024 Red Hat, Inc.
-// Author(s): Paolo Bonzini <pbonzini@redhat.com>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! Bindings for interrupt sources
-
-use std::{
- ffi::{c_int, CStr},
- marker::PhantomData,
- ptr,
-};
-
-use crate::{
- bindings::{self, qemu_set_irq},
- cell::Opaque,
- prelude::*,
- qom::ObjectClass,
-};
-
-/// An opaque wrapper around [`bindings::IRQState`].
-#[repr(transparent)]
-#[derive(Debug, qemu_api_macros::Wrapper)]
-pub struct IRQState(Opaque<bindings::IRQState>);
-
-/// Interrupt sources are used by devices to pass changes to a value (typically
-/// a boolean). The interrupt sink is usually an interrupt controller or
-/// GPIO controller.
-///
-/// As far as devices are concerned, interrupt sources are always active-high:
-/// for example, `InterruptSource<bool>`'s [`raise`](InterruptSource::raise)
-/// method sends a `true` value to the sink. If the guest has to see a
-/// different polarity, that change is performed by the board between the
-/// device and the interrupt controller.
-///
-/// 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
-/// initially leaves the pointer to a NULL value, representing an unconnected
-/// interrupt. To connect it, whoever creates the device fills the pointer with
-/// the sink's `IRQState *`, for example using `sysbus_connect_irq`. Because
-/// devices are generally shared objects, interrupt sources are an example of
-/// the interior mutability pattern.
-///
-/// Interrupt sources can only be triggered under the Big QEMU Lock; `BqlCell`
-/// allows access from whatever thread has it.
-#[derive(Debug)]
-#[repr(transparent)]
-pub struct InterruptSource<T = bool>
-where
- c_int: From<T>,
-{
- cell: BqlCell<*mut bindings::IRQState>,
- _marker: PhantomData<T>,
-}
-
-// SAFETY: the implementation asserts via `BqlCell` that the BQL is taken
-unsafe impl<T> Sync for InterruptSource<T> where c_int: From<T> {}
-
-impl InterruptSource<bool> {
- /// Send a low (`false`) value to the interrupt sink.
- pub fn lower(&self) {
- self.set(false);
- }
-
- /// Send a high-low pulse to the interrupt sink.
- pub fn pulse(&self) {
- self.set(true);
- self.set(false);
- }
-
- /// Send a high (`true`) value to the interrupt sink.
- pub fn raise(&self) {
- self.set(true);
- }
-}
-
-impl<T> InterruptSource<T>
-where
- c_int: From<T>,
-{
- /// Send `level` to the interrupt sink.
- pub fn set(&self, level: T) {
- let ptr = self.cell.get();
- // SAFETY: the pointer is retrieved under the BQL and remains valid
- // until the BQL is released, which is after qemu_set_irq() is entered.
- unsafe {
- qemu_set_irq(ptr, level.into());
- }
- }
-
- pub(crate) const fn as_ptr(&self) -> *mut *mut bindings::IRQState {
- self.cell.as_ptr()
- }
-
- pub(crate) const fn slice_as_ptr(slice: &[Self]) -> *mut *mut bindings::IRQState {
- assert!(!slice.is_empty());
- slice[0].as_ptr()
- }
-}
-
-impl Default for InterruptSource {
- fn default() -> Self {
- InterruptSource {
- cell: BqlCell::new(ptr::null_mut()),
- _marker: PhantomData,
- }
- }
-}
-
-unsafe impl ObjectType for IRQState {
- type Class = ObjectClass;
- const TYPE_NAME: &'static CStr =
- unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_IRQ) };
-}
-qom_isa!(IRQState: Object);
diff --git a/rust/qemu-api/src/lib.rs b/rust/qemu-api/src/lib.rs
deleted file mode 100644
index 234a94e..0000000
--- a/rust/qemu-api/src/lib.rs
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2024, Linaro Limited
-// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#![cfg_attr(not(MESON), doc = include_str!("../README.md"))]
-#![deny(clippy::missing_const_for_fn)]
-
-#[rustfmt::skip]
-pub mod bindings;
-
-// preserve one-item-per-"use" syntax, it is clearer
-// for prelude-like modules
-#[rustfmt::skip]
-pub mod prelude;
-
-pub mod assertions;
-pub mod bitops;
-pub mod callbacks;
-pub mod cell;
-pub mod chardev;
-pub mod errno;
-pub mod irq;
-pub mod memory;
-pub mod module;
-pub mod qdev;
-pub mod qom;
-pub mod sysbus;
-pub mod timer;
-pub mod vmstate;
-pub mod zeroable;
-
-use std::{
- alloc::{GlobalAlloc, Layout},
- ffi::c_void,
-};
-
-#[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 = QemuAllocator::new();
-/// ```
-#[derive(Clone, Copy, Debug)]
-#[repr(C)]
-pub struct QemuAllocator {
- _unused: [u8; 0],
-}
-
-#[cfg_attr(all(feature = "allocator", not(test)), global_allocator)]
-pub static GLOBAL: QemuAllocator = 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 Darwin
- // and OpenBSD, the alignment is 16 bytes on both 64-bit and 32-bit systems.
- #[cfg(all(
- target_pointer_width = "32",
- not(any(target_os = "macos", target_os = "openbsd"))
- ))]
- pub const DEFAULT_ALIGNMENT_BYTES: Option<usize> = Some(8);
- #[cfg(all(
- target_pointer_width = "64",
- not(any(target_os = "macos", target_os = "openbsd"))
- ))]
- pub const DEFAULT_ALIGNMENT_BYTES: Option<usize> = Some(16);
- #[cfg(all(
- any(target_pointer_width = "32", target_pointer_width = "64"),
- any(target_os = "macos", target_os = "openbsd")
- ))]
- pub const DEFAULT_ALIGNMENT_BYTES: Option<usize> = Some(16);
- #[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
- pub const DEFAULT_ALIGNMENT_BYTES: Option<usize> = None;
-
- pub const fn new() -> Self {
- Self { _unused: [] }
- }
-}
-
-impl Default for QemuAllocator {
- fn default() -> Self {
- Self::new()
- }
-}
-
-// Sanity check.
-const _: [(); 8] = [(); ::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 default.checked_rem(layout.align()) == Some(0))
- {
- // SAFETY: g_malloc0() is safe to call.
- unsafe { g_malloc0(layout.size().try_into().unwrap()).cast::<u8>() }
- } 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::<u8>()
- }
- }
- #[cfg(not(HAVE_GLIB_WITH_ALIGNED_ALLOC))]
- {
- // SAFETY: qemu_memalign() is safe to call.
- unsafe { qemu_memalign(layout.align(), layout.size()).cast::<u8>() }
- }
- }
- }
-
- unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
- if matches!(Self::DEFAULT_ALIGNMENT_BYTES, Some(default) if default.checked_rem(layout.align()) == 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 thus 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 thus a valid aligned
- // glib-allocated pointer, so `qemu_vfree`ing is safe.
- unsafe { qemu_vfree(ptr.cast::<_>()) }
- }
- }
- }
-}
diff --git a/rust/qemu-api/src/memory.rs b/rust/qemu-api/src/memory.rs
deleted file mode 100644
index 9ef2694..0000000
--- a/rust/qemu-api/src/memory.rs
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2024 Red Hat, Inc.
-// Author(s): Paolo Bonzini <pbonzini@redhat.com>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! Bindings for `MemoryRegion`, `MemoryRegionOps` and `MemTxAttrs`
-
-use std::{
- ffi::{c_uint, c_void, CStr, CString},
- marker::PhantomData,
-};
-
-pub use bindings::{hwaddr, MemTxAttrs};
-
-use crate::{
- bindings::{self, device_endian, memory_region_init_io},
- callbacks::FnCall,
- cell::Opaque,
- prelude::*,
- zeroable::Zeroable,
-};
-
-pub struct MemoryRegionOps<T>(
- bindings::MemoryRegionOps,
- // Note: quite often you'll see PhantomData<fn(&T)> mentioned when discussing
- // covariance and contravariance; you don't need any of those to understand
- // this usage of PhantomData. Quite simply, MemoryRegionOps<T> *logically*
- // holds callbacks that take an argument of type &T, except the type is erased
- // before the callback is stored in the bindings::MemoryRegionOps field.
- // The argument of PhantomData is a function pointer in order to represent
- // that relationship; while that will also provide desirable and safe variance
- // for T, variance is not the point but just a consequence.
- PhantomData<fn(&T)>,
-);
-
-// SAFETY: When a *const T is passed to the callbacks, the call itself
-// is done in a thread-safe manner. The invocation is okay as long as
-// T itself is `Sync`.
-unsafe impl<T: Sync> Sync for MemoryRegionOps<T> {}
-
-#[derive(Clone)]
-pub struct MemoryRegionOpsBuilder<T>(bindings::MemoryRegionOps, PhantomData<fn(&T)>);
-
-unsafe extern "C" fn memory_region_ops_read_cb<T, F: for<'a> FnCall<(&'a T, hwaddr, u32), u64>>(
- opaque: *mut c_void,
- addr: hwaddr,
- size: c_uint,
-) -> u64 {
- F::call((unsafe { &*(opaque.cast::<T>()) }, addr, size))
-}
-
-unsafe extern "C" fn memory_region_ops_write_cb<T, F: for<'a> FnCall<(&'a T, hwaddr, u64, u32)>>(
- opaque: *mut c_void,
- addr: hwaddr,
- data: u64,
- size: c_uint,
-) {
- F::call((unsafe { &*(opaque.cast::<T>()) }, addr, data, size))
-}
-
-impl<T> MemoryRegionOpsBuilder<T> {
- #[must_use]
- pub const fn read<F: for<'a> FnCall<(&'a T, hwaddr, u32), u64>>(mut self, _f: &F) -> Self {
- self.0.read = Some(memory_region_ops_read_cb::<T, F>);
- self
- }
-
- #[must_use]
- pub const fn write<F: for<'a> FnCall<(&'a T, hwaddr, u64, u32)>>(mut self, _f: &F) -> Self {
- self.0.write = Some(memory_region_ops_write_cb::<T, F>);
- self
- }
-
- #[must_use]
- pub const fn big_endian(mut self) -> Self {
- self.0.endianness = device_endian::DEVICE_BIG_ENDIAN;
- self
- }
-
- #[must_use]
- pub const fn little_endian(mut self) -> Self {
- self.0.endianness = device_endian::DEVICE_LITTLE_ENDIAN;
- self
- }
-
- #[must_use]
- pub const fn native_endian(mut self) -> Self {
- self.0.endianness = device_endian::DEVICE_NATIVE_ENDIAN;
- self
- }
-
- #[must_use]
- pub const fn valid_sizes(mut self, min: u32, max: u32) -> Self {
- self.0.valid.min_access_size = min;
- self.0.valid.max_access_size = max;
- self
- }
-
- #[must_use]
- pub const fn valid_unaligned(mut self) -> Self {
- self.0.valid.unaligned = true;
- self
- }
-
- #[must_use]
- pub const fn impl_sizes(mut self, min: u32, max: u32) -> Self {
- self.0.impl_.min_access_size = min;
- self.0.impl_.max_access_size = max;
- self
- }
-
- #[must_use]
- pub const fn impl_unaligned(mut self) -> Self {
- self.0.impl_.unaligned = true;
- self
- }
-
- #[must_use]
- pub const fn build(self) -> MemoryRegionOps<T> {
- MemoryRegionOps::<T>(self.0, PhantomData)
- }
-
- #[must_use]
- pub const fn new() -> Self {
- Self(bindings::MemoryRegionOps::ZERO, PhantomData)
- }
-}
-
-impl<T> Default for MemoryRegionOpsBuilder<T> {
- fn default() -> Self {
- Self::new()
- }
-}
-
-/// A safe wrapper around [`bindings::MemoryRegion`].
-#[repr(transparent)]
-#[derive(qemu_api_macros::Wrapper)]
-pub struct MemoryRegion(Opaque<bindings::MemoryRegion>);
-
-unsafe impl Send for MemoryRegion {}
-unsafe impl Sync for MemoryRegion {}
-
-impl MemoryRegion {
- // inline to ensure that it is not included in tests, which only
- // link to hwcore and qom. FIXME: inlining is actually the opposite
- // of what we want, since this is the type-erased version of the
- // init_io function below. Look into splitting the qemu_api crate.
- #[inline(always)]
- unsafe fn do_init_io(
- slot: *mut bindings::MemoryRegion,
- owner: *mut Object,
- ops: &'static bindings::MemoryRegionOps,
- name: &'static str,
- size: u64,
- ) {
- unsafe {
- let cstr = CString::new(name).unwrap();
- memory_region_init_io(
- slot,
- owner.cast::<bindings::Object>(),
- ops,
- owner.cast::<c_void>(),
- cstr.as_ptr(),
- size,
- );
- }
- }
-
- pub fn init_io<T: IsA<Object>>(
- &mut self,
- owner: *mut T,
- ops: &'static MemoryRegionOps<T>,
- name: &'static str,
- size: u64,
- ) {
- unsafe {
- Self::do_init_io(
- self.0.as_mut_ptr(),
- owner.cast::<Object>(),
- &ops.0,
- name,
- size,
- );
- }
- }
-}
-
-unsafe impl ObjectType for MemoryRegion {
- type Class = bindings::MemoryRegionClass;
- const TYPE_NAME: &'static CStr =
- unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_MEMORY_REGION) };
-}
-qom_isa!(MemoryRegion: Object);
-
-/// A special `MemTxAttrs` constant, used to indicate that no memory
-/// attributes are specified.
-///
-/// Bus masters which don't specify any attributes will get this,
-/// which has all attribute bits clear except the topmost one
-/// (so that we can distinguish "all attributes deliberately clear"
-/// from "didn't specify" if necessary).
-pub const MEMTXATTRS_UNSPECIFIED: MemTxAttrs = MemTxAttrs {
- unspecified: true,
- ..Zeroable::ZERO
-};
diff --git a/rust/qemu-api/src/module.rs b/rust/qemu-api/src/module.rs
deleted file mode 100644
index fa5cea3..0000000
--- a/rust/qemu-api/src/module.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2024, Linaro Limited
-// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! Macro to register blocks of code that run as QEMU starts up.
-
-#[macro_export]
-macro_rules! module_init {
- ($type:ident => $body:block) => {
- const _: () = {
- #[used]
- #[cfg_attr(
- not(any(target_vendor = "apple", target_os = "windows")),
- link_section = ".init_array"
- )]
- #[cfg_attr(target_vendor = "apple", link_section = "__DATA,__mod_init_func")]
- #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
- pub static LOAD_MODULE: extern "C" fn() = {
- extern "C" fn init_fn() {
- $body
- }
-
- extern "C" fn ctor_fn() {
- unsafe {
- $crate::bindings::register_module_init(
- Some(init_fn),
- $crate::bindings::module_init_type::$type,
- );
- }
- }
-
- ctor_fn
- };
- };
- };
-
- // shortcut because it's quite common that $body needs unsafe {}
- ($type:ident => unsafe $body:block) => {
- $crate::module_init! {
- $type => { unsafe { $body } }
- }
- };
-}
diff --git a/rust/qemu-api/src/prelude.rs b/rust/qemu-api/src/prelude.rs
deleted file mode 100644
index 43bfcd5..0000000
--- a/rust/qemu-api/src/prelude.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2024 Red Hat, Inc.
-// Author(s): Paolo Bonzini <pbonzini@redhat.com>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! Commonly used traits and types for QEMU.
-
-pub use crate::bitops::IntegerExt;
-
-pub use crate::cell::BqlCell;
-pub use crate::cell::BqlRefCell;
-
-pub use crate::errno;
-
-pub use crate::qdev::DeviceMethods;
-
-pub use crate::qom::InterfaceType;
-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::ObjectMethods;
-pub use crate::qom::ObjectType;
-
-pub use crate::qom_isa;
-
-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
deleted file mode 100644
index 1279d7a..0000000
--- a/rust/qemu-api/src/qdev.rs
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright 2024, Linaro Limited
-// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! Bindings to create devices and access device functionality from Rust.
-
-use std::{
- ffi::{c_int, c_void, CStr, CString},
- ptr::NonNull,
-};
-
-pub use bindings::{ClockEvent, DeviceClass, Property, ResetType};
-
-use crate::{
- bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, Error, ResettableClass},
- callbacks::FnCall,
- cell::{bql_locked, Opaque},
- chardev::Chardev,
- irq::InterruptSource,
- prelude::*,
- qom::{ObjectClass, ObjectImpl, Owned},
- vmstate::VMStateDescription,
-};
-
-/// A safe wrapper around [`bindings::Clock`].
-#[repr(transparent)]
-#[derive(Debug, qemu_api_macros::Wrapper)]
-pub struct Clock(Opaque<bindings::Clock>);
-
-unsafe impl Send for Clock {}
-unsafe impl Sync for Clock {}
-
-/// A safe wrapper around [`bindings::DeviceState`].
-#[repr(transparent)]
-#[derive(Debug, qemu_api_macros::Wrapper)]
-pub struct DeviceState(Opaque<bindings::DeviceState>);
-
-unsafe impl Send for DeviceState {}
-unsafe impl Sync for DeviceState {}
-
-/// Trait providing the contents of the `ResettablePhases` struct,
-/// which is part of the QOM `Resettable` interface.
-pub trait ResettablePhasesImpl {
- /// If not None, this is called when the object enters reset. It
- /// can reset local state of the object, but it must not do anything that
- /// has a side-effect on other objects, such as raising or lowering an
- /// [`InterruptSource`], or reading or writing guest memory. It takes the
- /// reset's type as argument.
- const ENTER: Option<fn(&Self, ResetType)> = None;
-
- /// If not None, this is called when the object for entry into reset, once
- /// every object in the system which is being reset has had its
- /// `ResettablePhasesImpl::ENTER` method called. At this point devices
- /// can do actions that affect other objects.
- ///
- /// If in doubt, implement this method.
- const HOLD: Option<fn(&Self, ResetType)> = None;
-
- /// If not None, this phase is called when the object leaves the reset
- /// state. Actions affecting other objects are permitted.
- const EXIT: Option<fn(&Self, ResetType)> = None;
-}
-
-/// # Safety
-///
-/// We expect the FFI user of this function to pass a valid pointer that
-/// 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,
- typ: ResetType,
-) {
- let state = NonNull::new(obj).unwrap().cast::<T>();
- T::ENTER.unwrap()(unsafe { state.as_ref() }, typ);
-}
-
-/// # Safety
-///
-/// We expect the FFI user of this function to pass a valid pointer that
-/// 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,
- typ: ResetType,
-) {
- let state = NonNull::new(obj).unwrap().cast::<T>();
- T::HOLD.unwrap()(unsafe { state.as_ref() }, typ);
-}
-
-/// # Safety
-///
-/// We expect the FFI user of this function to pass a valid pointer that
-/// 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,
- typ: ResetType,
-) {
- let state = NonNull::new(obj).unwrap().cast::<T>();
- T::EXIT.unwrap()(unsafe { state.as_ref() }, typ);
-}
-
-/// Trait providing the contents of [`DeviceClass`].
-pub trait DeviceImpl: ObjectImpl + ResettablePhasesImpl + IsA<DeviceState> {
- /// _Realization_ is the second stage of device creation. It contains
- /// all operations that depend on device properties and can fail (note:
- /// this is not yet supported for Rust devices).
- ///
- /// If not `None`, the parent class's `realize` method is overridden
- /// with the function pointed to by `REALIZE`.
- const REALIZE: Option<fn(&Self)> = None;
-
- /// An array providing the properties that the user can set on the
- /// device. Not a `const` because referencing statics in constants
- /// is unstable until Rust 1.83.0.
- fn properties() -> &'static [Property] {
- &[]
- }
-
- /// A `VMStateDescription` providing the migration format for the device
- /// Not a `const` because referencing statics in constants is unstable
- /// until Rust 1.83.0.
- fn vmsd() -> Option<&'static VMStateDescription> {
- None
- }
-}
-
-/// # Safety
-///
-/// This function is only called through the QOM machinery and
-/// used by `DeviceClass::class_init`.
-/// We expect the FFI user of this function to pass a valid pointer that
-/// 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_realize_fn<T: DeviceImpl>(
- dev: *mut bindings::DeviceState,
- _errp: *mut *mut Error,
-) {
- let state = NonNull::new(dev).unwrap().cast::<T>();
- T::REALIZE.unwrap()(unsafe { state.as_ref() });
-}
-
-unsafe impl InterfaceType for ResettableClass {
- const TYPE_NAME: &'static CStr =
- unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_RESETTABLE_INTERFACE) };
-}
-
-impl ResettableClass {
- /// Fill in the virtual methods of `ResettableClass` based on the
- /// definitions in the `ResettablePhasesImpl` trait.
- pub fn class_init<T: ResettablePhasesImpl>(&mut self) {
- if <T as ResettablePhasesImpl>::ENTER.is_some() {
- self.phases.enter = Some(rust_resettable_enter_fn::<T>);
- }
- if <T as ResettablePhasesImpl>::HOLD.is_some() {
- self.phases.hold = Some(rust_resettable_hold_fn::<T>);
- }
- if <T as ResettablePhasesImpl>::EXIT.is_some() {
- self.phases.exit = Some(rust_resettable_exit_fn::<T>);
- }
- }
-}
-
-impl DeviceClass {
- /// Fill in the virtual methods of `DeviceClass` based on the definitions in
- /// the `DeviceImpl` trait.
- pub fn class_init<T: DeviceImpl>(&mut self) {
- if <T as DeviceImpl>::REALIZE.is_some() {
- self.realize = Some(rust_realize_fn::<T>);
- }
- if let Some(vmsd) = <T as DeviceImpl>::vmsd() {
- self.vmsd = vmsd;
- }
- let prop = <T as DeviceImpl>::properties();
- if !prop.is_empty() {
- unsafe {
- bindings::device_class_set_props_n(self, prop.as_ptr(), prop.len());
- }
- }
-
- ResettableClass::cast::<DeviceState>(self).class_init::<T>();
- self.parent_class.class_init::<T>();
- }
-}
-
-#[macro_export]
-macro_rules! define_property {
- ($name:expr, $state:ty, $field:ident, $prop:expr, $type:ty, bit = $bitnr:expr, default = $defval:expr$(,)*) => {
- $crate::bindings::Property {
- // use associated function syntax for type checking
- name: ::std::ffi::CStr::as_ptr($name),
- info: $prop,
- offset: ::std::mem::offset_of!($state, $field) as isize,
- bitnr: $bitnr,
- set_default: true,
- defval: $crate::bindings::Property__bindgen_ty_1 { u: $defval as u64 },
- ..$crate::zeroable::Zeroable::ZERO
- }
- };
- ($name:expr, $state:ty, $field:ident, $prop:expr, $type:ty, default = $defval:expr$(,)*) => {
- $crate::bindings::Property {
- // use associated function syntax for type checking
- name: ::std::ffi::CStr::as_ptr($name),
- info: $prop,
- 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
- }
- };
- ($name:expr, $state:ty, $field:ident, $prop:expr, $type:ty$(,)*) => {
- $crate::bindings::Property {
- // use associated function syntax for type checking
- name: ::std::ffi::CStr::as_ptr($name),
- info: $prop,
- offset: ::std::mem::offset_of!($state, $field) as isize,
- set_default: false,
- ..$crate::zeroable::Zeroable::ZERO
- }
- };
-}
-
-#[macro_export]
-macro_rules! declare_properties {
- ($ident:ident, $($prop:expr),*$(,)*) => {
- pub static $ident: [$crate::bindings::Property; {
- let mut len = 0;
- $({
- _ = stringify!($prop);
- len += 1;
- })*
- len
- }] = [
- $($prop),*,
- ];
- };
-}
-
-unsafe impl ObjectType for DeviceState {
- type Class = DeviceClass;
- const TYPE_NAME: &'static CStr =
- unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_DEVICE) };
-}
-qom_isa!(DeviceState: Object);
-
-/// Trait for methods exposed by the [`DeviceState`] class. The methods can be
-/// called on all objects that have the trait `IsA<DeviceState>`.
-///
-/// The trait should only be used through the blanket implementation,
-/// which guarantees safety via `IsA`.
-pub trait DeviceMethods: ObjectDeref
-where
- Self::Target: IsA<DeviceState>,
-{
- /// Add an input clock named `name`. Invoke the callback with
- /// `self` as the first parameter for the events that are requested.
- ///
- /// The resulting clock is added as a child of `self`, but it also
- /// stays alive until after `Drop::drop` is called because C code
- /// keeps an extra reference to it until `device_finalize()` calls
- /// `qdev_finalize_clocklist()`. Therefore (unlike most cases in
- /// which Rust code has a reference to a child object) it would be
- /// possible for this function to return a `&Clock` too.
- #[inline]
- fn init_clock_in<F: for<'a> FnCall<(&'a Self::Target, ClockEvent)>>(
- &self,
- name: &str,
- _cb: &F,
- events: ClockEvent,
- ) -> Owned<Clock> {
- fn do_init_clock_in(
- dev: &DeviceState,
- name: &str,
- cb: Option<unsafe extern "C" fn(*mut c_void, ClockEvent)>,
- events: ClockEvent,
- ) -> Owned<Clock> {
- assert!(bql_locked());
-
- // SAFETY: the clock is heap allocated, but qdev_init_clock_in()
- // does not gift the reference to its caller; so use Owned::from to
- // add one. The callback is disabled automatically when the clock
- // is unparented, which happens before the device is finalized.
- unsafe {
- let cstr = CString::new(name).unwrap();
- let clk = bindings::qdev_init_clock_in(
- dev.as_mut_ptr(),
- cstr.as_ptr(),
- cb,
- dev.as_void_ptr(),
- events.0,
- );
-
- let clk: &Clock = Clock::from_raw(clk);
- Owned::from(clk)
- }
- }
-
- let cb: Option<unsafe extern "C" fn(*mut c_void, ClockEvent)> = if F::is_some() {
- unsafe extern "C" fn rust_clock_cb<T, F: for<'a> FnCall<(&'a T, ClockEvent)>>(
- opaque: *mut c_void,
- event: ClockEvent,
- ) {
- // SAFETY: the opaque is "this", which is indeed a pointer to T
- F::call((unsafe { &*(opaque.cast::<T>()) }, event))
- }
- Some(rust_clock_cb::<Self::Target, F>)
- } else {
- None
- };
-
- do_init_clock_in(self.upcast(), name, cb, events)
- }
-
- /// Add an output clock named `name`.
- ///
- /// The resulting clock is added as a child of `self`, but it also
- /// stays alive until after `Drop::drop` is called because C code
- /// keeps an extra reference to it until `device_finalize()` calls
- /// `qdev_finalize_clocklist()`. Therefore (unlike most cases in
- /// which Rust code has a reference to a child object) it would be
- /// possible for this function to return a `&Clock` too.
- #[inline]
- fn init_clock_out(&self, name: &str) -> Owned<Clock> {
- unsafe {
- let cstr = CString::new(name).unwrap();
- let clk = bindings::qdev_init_clock_out(self.upcast().as_mut_ptr(), cstr.as_ptr());
-
- let clk: &Clock = Clock::from_raw(clk);
- Owned::from(clk)
- }
- }
-
- fn prop_set_chr(&self, propname: &str, chr: &Owned<Chardev>) {
- assert!(bql_locked());
- let c_propname = CString::new(propname).unwrap();
- let chr: &Chardev = chr;
- unsafe {
- bindings::qdev_prop_set_chr(
- self.upcast().as_mut_ptr(),
- c_propname.as_ptr(),
- chr.as_mut_ptr(),
- );
- }
- }
-
- fn init_gpio_in<F: for<'a> FnCall<(&'a Self::Target, u32, u32)>>(
- &self,
- num_lines: u32,
- _cb: F,
- ) {
- fn do_init_gpio_in(
- dev: &DeviceState,
- num_lines: u32,
- gpio_in_cb: unsafe extern "C" fn(*mut c_void, c_int, c_int),
- ) {
- unsafe {
- qdev_init_gpio_in(dev.as_mut_ptr(), Some(gpio_in_cb), num_lines as c_int);
- }
- }
-
- let _: () = F::ASSERT_IS_SOME;
- unsafe extern "C" fn rust_irq_handler<T, F: for<'a> FnCall<(&'a T, u32, u32)>>(
- opaque: *mut c_void,
- line: c_int,
- level: c_int,
- ) {
- // SAFETY: the opaque was passed as a reference to `T`
- F::call((unsafe { &*(opaque.cast::<T>()) }, line as u32, level as u32))
- }
-
- let gpio_in_cb: unsafe extern "C" fn(*mut c_void, c_int, c_int) =
- rust_irq_handler::<Self::Target, F>;
-
- do_init_gpio_in(self.upcast(), num_lines, gpio_in_cb);
- }
-
- fn init_gpio_out(&self, pins: &[InterruptSource]) {
- unsafe {
- qdev_init_gpio_out(
- self.upcast().as_mut_ptr(),
- InterruptSource::slice_as_ptr(pins),
- pins.len() as c_int,
- );
- }
- }
-}
-
-impl<R: ObjectDeref> DeviceMethods for R where R::Target: IsA<DeviceState> {}
-
-unsafe impl ObjectType for Clock {
- type Class = ObjectClass;
- const TYPE_NAME: &'static CStr =
- unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_CLOCK) };
-}
-qom_isa!(Clock: Object);
diff --git a/rust/qemu-api/src/qom.rs b/rust/qemu-api/src/qom.rs
deleted file mode 100644
index 41e5a5e..0000000
--- a/rust/qemu-api/src/qom.rs
+++ /dev/null
@@ -1,772 +0,0 @@
-// Copyright 2024, Linaro Limited
-// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! Bindings to access QOM functionality from Rust.
-//!
-//! The QEMU Object Model (QOM) provides inheritance and dynamic typing for QEMU
-//! devices. This module makes QOM's features available in Rust through three
-//! main mechanisms:
-//!
-//! * Automatic creation and registration of `TypeInfo` for classes that are
-//! written in Rust, as well as mapping between Rust traits and QOM vtables.
-//!
-//! * Type-safe casting between parent and child classes, through the [`IsA`]
-//! trait and methods such as [`upcast`](ObjectCast::upcast) and
-//! [`downcast`](ObjectCast::downcast).
-//!
-//! * Automatic delegation of parent class methods to child classes. When a
-//! trait uses [`IsA`] as a bound, its contents become available to all child
-//! classes through blanket implementations. This works both for class methods
-//! and for instance methods accessed through references or smart pointers.
-//!
-//! # Structure of a class
-//!
-//! A leaf class only needs a struct holding instance state. The struct must
-//! implement the [`ObjectType`] and [`IsA`] traits, as well as any `*Impl`
-//! traits that exist for its superclasses.
-//!
-//! If a class has subclasses, it will also provide a struct for instance data,
-//! with the same characteristics as for concrete classes, but it also needs
-//! additional components to support virtual methods:
-//!
-//! * a struct for class data, for example `DeviceClass`. This corresponds to
-//! the C "class struct" and holds the vtable that is used by instances of the
-//! class and its subclasses. It must start with its parent's class struct.
-//!
-//! * a trait for virtual method implementations, for example `DeviceImpl`.
-//! Child classes implement this trait to provide their own behavior for
-//! virtual methods. The trait's methods take `&self` to access instance data.
-//! The traits have the appropriate specialization of `IsA<>` as a supertrait,
-//! for example `IsA<DeviceState>` for `DeviceImpl`.
-//!
-//! * a trait for instance methods, for example `DeviceMethods`. This trait is
-//! automatically implemented for any reference or smart pointer to a device
-//! instance. It calls into the vtable provides access across all subclasses
-//! to methods defined for the class.
-//!
-//! * optionally, a trait for class methods, for example `DeviceClassMethods`.
-//! This provides access to class-wide functionality that doesn't depend on
-//! instance data. Like instance methods, these are automatically inherited by
-//! child classes.
-//!
-//! # Class structures
-//!
-//! Each QOM class that has virtual methods describes them in a
-//! _class struct_. Class structs include a parent field corresponding
-//! to the vtable of the parent class, all the way up to [`ObjectClass`].
-//!
-//! As mentioned above, virtual methods are defined via traits such as
-//! `DeviceImpl`. Class structs do not define any trait but, conventionally,
-//! all of them have a `class_init` method to initialize the virtual methods
-//! based on the trait and then call the same method on the superclass.
-//!
-//! ```ignore
-//! impl YourSubclassClass
-//! {
-//! pub fn class_init<T: YourSubclassImpl>(&mut self) {
-//! ...
-//! klass.parent_class::class_init<T>();
-//! }
-//! }
-//! ```
-//!
-//! If a class implements a QOM interface. In that case, the function must
-//! contain, for each interface, an extra forwarding call as follows:
-//!
-//! ```ignore
-//! ResettableClass::cast::<Self>(self).class_init::<Self>();
-//! ```
-//!
-//! These `class_init` functions are methods on the class rather than a trait,
-//! because the bound on `T` (`DeviceImpl` in this case), will change for every
-//! class struct. The functions are pointed to by the
-//! [`ObjectImpl::CLASS_INIT`] function pointer. While there is no default
-//! implementation, in most cases it will be enough to write it as follows:
-//!
-//! ```ignore
-//! const CLASS_INIT: fn(&mut Self::Class)> = Self::Class::class_init::<Self>;
-//! ```
-//!
-//! This design incurs a small amount of code duplication but, by not using
-//! traits, it allows the flexibility of implementing bindings in any crate,
-//! without incurring into violations of orphan rules for traits.
-
-use std::{
- ffi::{c_void, CStr},
- fmt,
- mem::ManuallyDrop,
- ops::{Deref, DerefMut},
- ptr::NonNull,
-};
-
-pub use bindings::ObjectClass;
-
-use crate::{
- bindings::{
- self, object_class_dynamic_cast, object_dynamic_cast, object_get_class,
- object_get_typename, object_new, object_ref, object_unref, TypeInfo,
- },
- cell::{bql_locked, Opaque},
-};
-
-/// A safe wrapper around [`bindings::Object`].
-#[repr(transparent)]
-#[derive(Debug, qemu_api_macros::Wrapper)]
-pub struct Object(Opaque<bindings::Object>);
-
-unsafe impl Send for Object {}
-unsafe impl Sync for Object {}
-
-/// Marker trait: `Self` can be statically upcasted to `P` (i.e. `P` is a direct
-/// or indirect parent of `Self`).
-///
-/// # Safety
-///
-/// The struct `Self` must be `#[repr(C)]` and must begin, directly or
-/// indirectly, with a field of type `P`. This ensures that invalid casts,
-/// which rely on `IsA<>` for static checking, are rejected at compile time.
-pub unsafe trait IsA<P: ObjectType>: ObjectType {}
-
-// SAFETY: it is always safe to cast to your own type
-unsafe impl<T: ObjectType> IsA<T> for T {}
-
-/// Macro to mark superclasses of QOM classes. This enables type-safe
-/// up- and downcasting.
-///
-/// # Safety
-///
-/// This macro is a thin wrapper around the [`IsA`] trait and performs
-/// no checking whatsoever of what is declared. It is the caller's
-/// responsibility to have $struct begin, directly or indirectly, with
-/// a field of type `$parent`.
-#[macro_export]
-macro_rules! qom_isa {
- ($struct:ty : $($parent:ty),* ) => {
- $(
- // SAFETY: it is the caller responsibility to have $parent as the
- // first field
- unsafe impl $crate::qom::IsA<$parent> for $struct {}
-
- impl AsRef<$parent> for $struct {
- fn as_ref(&self) -> &$parent {
- // SAFETY: follows the same rules as for IsA<U>, which is
- // declared above.
- let ptr: *const Self = self;
- unsafe { &*ptr.cast::<$parent>() }
- }
- }
- )*
- };
-}
-
-/// This is the same as [`ManuallyDrop<T>`](std::mem::ManuallyDrop), though
-/// it hides the standard methods of `ManuallyDrop`.
-///
-/// The first field of an `ObjectType` must be of type `ParentField<T>`.
-/// (Technically, this is only necessary if there is at least one Rust
-/// superclass in the hierarchy). This is to ensure that the parent field is
-/// dropped after the subclass; this drop order is enforced by the C
-/// `object_deinit` function.
-///
-/// # Examples
-///
-/// ```ignore
-/// #[repr(C)]
-/// #[derive(qemu_api_macros::Object)]
-/// pub struct MyDevice {
-/// parent: ParentField<DeviceState>,
-/// ...
-/// }
-/// ```
-#[derive(Debug)]
-#[repr(transparent)]
-pub struct ParentField<T: ObjectType>(std::mem::ManuallyDrop<T>);
-
-impl<T: ObjectType> Deref for ParentField<T> {
- type Target = T;
-
- #[inline(always)]
- fn deref(&self) -> &Self::Target {
- &self.0
- }
-}
-
-impl<T: ObjectType> DerefMut for ParentField<T> {
- #[inline(always)]
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.0
- }
-}
-
-impl<T: fmt::Display + ObjectType> fmt::Display for ParentField<T> {
- #[inline(always)]
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
- self.0.fmt(f)
- }
-}
-
-unsafe extern "C" fn rust_instance_init<T: ObjectImpl>(obj: *mut bindings::Object) {
- let mut state = NonNull::new(obj).unwrap().cast::<T>();
- // SAFETY: obj is an instance of T, since rust_instance_init<T>
- // is called from QOM core as the instance_init function
- // for class T
- unsafe {
- T::INSTANCE_INIT.unwrap()(state.as_mut());
- }
-}
-
-unsafe extern "C" fn rust_instance_post_init<T: ObjectImpl>(obj: *mut bindings::Object) {
- let state = NonNull::new(obj).unwrap().cast::<T>();
- // SAFETY: obj is an instance of T, since rust_instance_post_init<T>
- // is called from QOM core as the instance_post_init function
- // for class T
- T::INSTANCE_POST_INIT.unwrap()(unsafe { state.as_ref() });
-}
-
-unsafe extern "C" fn rust_class_init<T: ObjectType + ObjectImpl>(
- klass: *mut ObjectClass,
- _data: *const c_void,
-) {
- let mut klass = NonNull::new(klass)
- .unwrap()
- .cast::<<T as ObjectType>::Class>();
- // SAFETY: klass is a T::Class, since rust_class_init<T>
- // is called from QOM core as the class_init function
- // for class T
- <T as ObjectImpl>::CLASS_INIT(unsafe { klass.as_mut() })
-}
-
-unsafe extern "C" fn drop_object<T: ObjectImpl>(obj: *mut bindings::Object) {
- // SAFETY: obj is an instance of T, since drop_object<T> is called
- // from the QOM core function object_deinit() as the instance_finalize
- // function for class T. Note that while object_deinit() will drop the
- // superclass field separately after this function returns, `T` must
- // implement the unsafe trait ObjectType; the safety rules for the
- // trait mandate that the parent field is manually dropped.
- unsafe { std::ptr::drop_in_place(obj.cast::<T>()) }
-}
-
-/// Trait exposed by all structs corresponding to QOM objects.
-///
-/// # Safety
-///
-/// For classes declared in C:
-///
-/// - `Class` and `TYPE` must match the data in the `TypeInfo`;
-///
-/// - the first field of the struct must be of the instance type corresponding
-/// to the superclass, as declared in the `TypeInfo`
-///
-/// - likewise, the first field of the `Class` struct must be of the class type
-/// corresponding to the superclass
-///
-/// For classes declared in Rust and implementing [`ObjectImpl`]:
-///
-/// - the struct must be `#[repr(C)]`;
-///
-/// - the first field of the struct must be of type
-/// [`ParentField<T>`](ParentField), where `T` is the parent type
-/// [`ObjectImpl::ParentType`]
-///
-/// - the first field of the `Class` must be of the class struct corresponding
-/// to the superclass, which is `ObjectImpl::ParentType::Class`. `ParentField`
-/// is not needed here.
-///
-/// In both cases, having a separate class type is not necessary if the subclass
-/// does not add any field.
-pub unsafe trait ObjectType: Sized {
- /// The QOM class object corresponding to this struct. This is used
- /// to automatically generate a `class_init` method.
- type Class;
-
- /// The name of the type, which can be passed to `object_new()` to
- /// generate an instance of this type.
- const TYPE_NAME: &'static CStr;
-
- /// Return the receiver as an Object. This is always safe, even
- /// if this type represents an interface.
- fn as_object(&self) -> &Object {
- unsafe { &*self.as_ptr().cast() }
- }
-
- /// Return the receiver as a const raw pointer to Object.
- /// This is preferrable to `as_object_mut_ptr()` if a C
- /// function only needs a `const Object *`.
- fn as_object_ptr(&self) -> *const bindings::Object {
- self.as_object().as_ptr()
- }
-
- /// Return the receiver as a mutable raw pointer to Object.
- ///
- /// # Safety
- ///
- /// This cast is always safe, but because the result is mutable
- /// and the incoming reference is not, this should only be used
- /// for calls to C functions, and only if needed.
- unsafe fn as_object_mut_ptr(&self) -> *mut bindings::Object {
- self.as_object().as_mut_ptr()
- }
-}
-
-/// Trait exposed by all structs corresponding to QOM interfaces.
-/// Unlike `ObjectType`, it is implemented on the class type (which provides
-/// the vtable for the interfaces).
-///
-/// # Safety
-///
-/// `TYPE` must match the contents of the `TypeInfo` as found in the C code;
-/// right now, interfaces can only be declared in C.
-pub unsafe trait InterfaceType: Sized {
- /// The name of the type, which can be passed to
- /// `object_class_dynamic_cast()` to obtain the pointer to the vtable
- /// for this interface.
- const TYPE_NAME: &'static CStr;
-
- /// Return the vtable for the interface; `U` is the type that
- /// lists the interface in its `TypeInfo`.
- ///
- /// # Examples
- ///
- /// This function is usually called by a `class_init` method in `U::Class`.
- /// For example, `DeviceClass::class_init<T>` initializes its `Resettable`
- /// interface as follows:
- ///
- /// ```ignore
- /// ResettableClass::cast::<DeviceState>(self).class_init::<T>();
- /// ```
- ///
- /// where `T` is the concrete subclass that is being initialized.
- ///
- /// # Panics
- ///
- /// Panic if the incoming argument if `T` does not implement the interface.
- fn cast<U: ObjectType>(klass: &mut U::Class) -> &mut Self {
- unsafe {
- // SAFETY: upcasting to ObjectClass is always valid, and the
- // return type is either NULL or the argument itself
- let result: *mut Self = object_class_dynamic_cast(
- (klass as *mut U::Class).cast(),
- Self::TYPE_NAME.as_ptr(),
- )
- .cast();
- result.as_mut().unwrap()
- }
- }
-}
-
-/// This trait provides safe casting operations for QOM objects to raw pointers,
-/// to be used for example for FFI. The trait can be applied to any kind of
-/// reference or smart pointers, and enforces correctness through the [`IsA`]
-/// trait.
-pub trait ObjectDeref: Deref
-where
- Self::Target: ObjectType,
-{
- /// Convert to a const Rust pointer, to be used for example for FFI.
- /// The target pointer type must be the type of `self` or a superclass
- fn as_ptr<U: ObjectType>(&self) -> *const U
- where
- Self::Target: IsA<U>,
- {
- let ptr: *const Self::Target = self.deref();
- ptr.cast::<U>()
- }
-
- /// Convert to a mutable Rust pointer, to be used for example for FFI.
- /// The target pointer type must be the type of `self` or a superclass.
- /// Used to implement interior mutability for objects.
- ///
- /// # Safety
- ///
- /// This method is safe because only the actual dereference of the pointer
- /// has to be unsafe. Bindings to C APIs will use it a lot, but care has
- /// to be taken because it overrides the const-ness of `&self`.
- fn as_mut_ptr<U: ObjectType>(&self) -> *mut U
- where
- Self::Target: IsA<U>,
- {
- #[allow(clippy::as_ptr_cast_mut)]
- {
- self.as_ptr::<U>().cast_mut()
- }
- }
-}
-
-/// Trait that adds extra functionality for `&T` where `T` is a QOM
-/// object type. Allows conversion to/from C objects in generic code.
-pub trait ObjectCast: ObjectDeref + Copy
-where
- Self::Target: ObjectType,
-{
- /// Safely convert from a derived type to one of its parent types.
- ///
- /// This is always safe; the [`IsA`] trait provides static verification
- /// trait that `Self` dereferences to `U` or a child of `U`.
- fn upcast<'a, U: ObjectType>(self) -> &'a U
- where
- Self::Target: IsA<U>,
- Self: 'a,
- {
- // SAFETY: soundness is declared via IsA<U>, which is an unsafe trait
- unsafe { self.unsafe_cast::<U>() }
- }
-
- /// Attempt to convert to a derived type.
- ///
- /// Returns `None` if the object is not actually of type `U`. This is
- /// verified at runtime by checking the object's type information.
- fn downcast<'a, U: IsA<Self::Target>>(self) -> Option<&'a U>
- where
- Self: 'a,
- {
- self.dynamic_cast::<U>()
- }
-
- /// Attempt to convert between any two types in the QOM hierarchy.
- ///
- /// Returns `None` if the object is not actually of type `U`. This is
- /// verified at runtime by checking the object's type information.
- fn dynamic_cast<'a, U: ObjectType>(self) -> Option<&'a U>
- where
- Self: 'a,
- {
- unsafe {
- // SAFETY: upcasting to Object is always valid, and the
- // return type is either NULL or the argument itself
- let result: *const U =
- object_dynamic_cast(self.as_object_mut_ptr(), U::TYPE_NAME.as_ptr()).cast();
-
- result.as_ref()
- }
- }
-
- /// Convert to any QOM type without verification.
- ///
- /// # Safety
- ///
- /// What safety? You need to know yourself that the cast is correct; only
- /// use when performance is paramount. It is still better than a raw
- /// pointer `cast()`, which does not even check that you remain in the
- /// realm of QOM `ObjectType`s.
- ///
- /// `unsafe_cast::<Object>()` is always safe.
- unsafe fn unsafe_cast<'a, U: ObjectType>(self) -> &'a U
- where
- Self: 'a,
- {
- unsafe { &*(self.as_ptr::<Self::Target>().cast::<U>()) }
- }
-}
-
-impl<T: ObjectType> ObjectDeref for &T {}
-impl<T: ObjectType> ObjectCast for &T {}
-
-impl<T: ObjectType> ObjectDeref for &mut T {}
-
-/// Trait a type must implement to be registered with QEMU.
-pub trait ObjectImpl: ObjectType + IsA<Object> {
- /// The parent of the type. This should match the first field of the
- /// struct that implements `ObjectImpl`, minus the `ParentField<_>` wrapper.
- type ParentType: ObjectType;
-
- /// Whether the object can be instantiated
- const ABSTRACT: bool = false;
-
- /// Function that is called to initialize an object. The parent class will
- /// have already been initialized so the type is only responsible for
- /// initializing its own members.
- ///
- /// FIXME: The argument is not really a valid reference. `&mut
- /// MaybeUninit<Self>` would be a better description.
- const INSTANCE_INIT: Option<unsafe fn(&mut Self)> = None;
-
- /// Function that is called to finish initialization of an object, once
- /// `INSTANCE_INIT` functions have been called.
- const INSTANCE_POST_INIT: Option<fn(&Self)> = None;
-
- /// Called on descendent classes after all parent class initialization
- /// has occurred, but before the class itself is initialized. This
- /// is only useful if a class is not a leaf, and can be used to undo
- /// the effects of copying the contents of the parent's class struct
- /// to the descendants.
- const CLASS_BASE_INIT: Option<
- unsafe extern "C" fn(klass: *mut ObjectClass, data: *const c_void),
- > = None;
-
- const TYPE_INFO: TypeInfo = TypeInfo {
- name: Self::TYPE_NAME.as_ptr(),
- parent: Self::ParentType::TYPE_NAME.as_ptr(),
- instance_size: core::mem::size_of::<Self>(),
- instance_align: core::mem::align_of::<Self>(),
- instance_init: match Self::INSTANCE_INIT {
- None => None,
- Some(_) => Some(rust_instance_init::<Self>),
- },
- instance_post_init: match Self::INSTANCE_POST_INIT {
- None => None,
- Some(_) => Some(rust_instance_post_init::<Self>),
- },
- instance_finalize: Some(drop_object::<Self>),
- abstract_: Self::ABSTRACT,
- class_size: core::mem::size_of::<Self::Class>(),
- class_init: Some(rust_class_init::<Self>),
- class_base_init: Self::CLASS_BASE_INIT,
- class_data: core::ptr::null(),
- interfaces: core::ptr::null(),
- };
-
- // methods on ObjectClass
- const UNPARENT: Option<fn(&Self)> = None;
-
- /// Store into the argument the virtual method implementations
- /// for `Self`. On entry, the virtual method pointers are set to
- /// the default values coming from the parent classes; the function
- /// can change them to override virtual methods of a parent class.
- ///
- /// Usually defined simply as `Self::Class::class_init::<Self>`;
- /// however a default implementation cannot be included here, because the
- /// bounds that the `Self::Class::class_init` method places on `Self` are
- /// not known in advance.
- ///
- /// # Safety
- ///
- /// While `klass`'s parent class is initialized on entry, the other fields
- /// are all zero; it is therefore assumed that all fields in `T` can be
- /// zeroed, otherwise it would not be possible to provide the class as a
- /// `&mut T`. TODO: it may be possible to add an unsafe trait that checks
- /// that all fields *after the parent class* (but not the parent class
- /// itself) are Zeroable. This unsafe trait can be added via a derive
- /// macro.
- const CLASS_INIT: fn(&mut Self::Class);
-}
-
-/// # Safety
-///
-/// We expect the FFI user of this function to pass a valid pointer that
-/// 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_unparent_fn<T: ObjectImpl>(dev: *mut bindings::Object) {
- let state = NonNull::new(dev).unwrap().cast::<T>();
- T::UNPARENT.unwrap()(unsafe { state.as_ref() });
-}
-
-impl ObjectClass {
- /// Fill in the virtual methods of `ObjectClass` based on the definitions in
- /// the `ObjectImpl` trait.
- pub fn class_init<T: ObjectImpl>(&mut self) {
- if <T as ObjectImpl>::UNPARENT.is_some() {
- self.unparent = Some(rust_unparent_fn::<T>);
- }
- }
-}
-
-unsafe impl ObjectType for Object {
- type Class = ObjectClass;
- const TYPE_NAME: &'static CStr =
- unsafe { CStr::from_bytes_with_nul_unchecked(bindings::TYPE_OBJECT) };
-}
-
-/// A reference-counted pointer to a QOM object.
-///
-/// `Owned<T>` wraps `T` with automatic reference counting. It increases the
-/// reference count when created via [`Owned::from`] or cloned, and decreases
-/// it when dropped. This ensures that the reference count remains elevated
-/// as long as any `Owned<T>` references to it exist.
-///
-/// `Owned<T>` can be used for two reasons:
-/// * because the lifetime of the QOM object is unknown and someone else could
-/// take a reference (similar to `Arc<T>`, for example): in this case, the
-/// object can escape and outlive the Rust struct that contains the `Owned<T>`
-/// field;
-///
-/// * to ensure that the object stays alive until after `Drop::drop` is called
-/// on the Rust struct: in this case, the object will always die together with
-/// the Rust struct that contains the `Owned<T>` field.
-///
-/// Child properties are an example of the second case: in C, an object that
-/// is created with `object_initialize_child` will die *before*
-/// `instance_finalize` is called, whereas Rust expects the struct to have valid
-/// contents when `Drop::drop` is called. Therefore Rust structs that have
-/// child properties need to keep a reference to the child object. Right now
-/// this can be done with `Owned<T>`; in the future one might have a separate
-/// `Child<'parent, T>` smart pointer that keeps a reference to a `T`, like
-/// `Owned`, but does not allow cloning.
-///
-/// Note that dropping an `Owned<T>` requires the big QEMU lock to be taken.
-#[repr(transparent)]
-#[derive(PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct Owned<T: ObjectType>(NonNull<T>);
-
-// The following rationale for safety is taken from Linux's kernel::sync::Arc.
-
-// SAFETY: It is safe to send `Owned<T>` to another thread when the underlying
-// `T` is `Sync` because it effectively means sharing `&T` (which is safe
-// because `T` is `Sync`); additionally, it needs `T` to be `Send` because any
-// thread that has an `Owned<T>` may ultimately access `T` using a
-// mutable reference when the reference count reaches zero and `T` is dropped.
-unsafe impl<T: ObjectType + Send + Sync> Send for Owned<T> {}
-
-// SAFETY: It is safe to send `&Owned<T>` to another thread when the underlying
-// `T` is `Sync` because it effectively means sharing `&T` (which is safe
-// because `T` is `Sync`); additionally, it needs `T` to be `Send` because any
-// thread that has a `&Owned<T>` may clone it and get an `Owned<T>` on that
-// thread, so the thread may ultimately access `T` using a mutable reference
-// when the reference count reaches zero and `T` is dropped.
-unsafe impl<T: ObjectType + Sync + Send> Sync for Owned<T> {}
-
-impl<T: ObjectType> Owned<T> {
- /// Convert a raw C pointer into an owned reference to the QOM
- /// object it points to. The object's reference count will be
- /// decreased when the `Owned` is dropped.
- ///
- /// # Panics
- ///
- /// Panics if `ptr` is NULL.
- ///
- /// # Safety
- ///
- /// The caller must indeed own a reference to the QOM object.
- /// The object must not be embedded in another unless the outer
- /// object is guaranteed to have a longer lifetime.
- ///
- /// A raw pointer obtained via [`Owned::into_raw()`] can always be passed
- /// back to `from_raw()` (assuming the original `Owned` was valid!),
- /// since the owned reference remains there between the calls to
- /// `into_raw()` and `from_raw()`.
- pub unsafe fn from_raw(ptr: *const T) -> Self {
- // SAFETY NOTE: while NonNull requires a mutable pointer, only
- // Deref is implemented so the pointer passed to from_raw
- // remains const
- Owned(NonNull::new(ptr.cast_mut()).unwrap())
- }
-
- /// Obtain a raw C pointer from a reference. `src` is consumed
- /// and the reference is leaked.
- #[allow(clippy::missing_const_for_fn)]
- pub fn into_raw(src: Owned<T>) -> *mut T {
- let src = ManuallyDrop::new(src);
- src.0.as_ptr()
- }
-
- /// Increase the reference count of a QOM object and return
- /// a new owned reference to it.
- ///
- /// # Safety
- ///
- /// The object must not be embedded in another, unless the outer
- /// object is guaranteed to have a longer lifetime.
- pub unsafe fn from(obj: &T) -> Self {
- unsafe {
- object_ref(obj.as_object_mut_ptr().cast::<c_void>());
-
- // SAFETY NOTE: while NonNull requires a mutable pointer, only
- // Deref is implemented so the reference passed to from_raw
- // remains shared
- Owned(NonNull::new_unchecked(obj.as_mut_ptr()))
- }
- }
-}
-
-impl<T: ObjectType> Clone for Owned<T> {
- fn clone(&self) -> Self {
- // SAFETY: creation method is unsafe; whoever calls it has
- // responsibility that the pointer is valid, and remains valid
- // throughout the lifetime of the `Owned<T>` and its clones.
- unsafe { Owned::from(self.deref()) }
- }
-}
-
-impl<T: ObjectType> Deref for Owned<T> {
- type Target = T;
-
- fn deref(&self) -> &Self::Target {
- // SAFETY: creation method is unsafe; whoever calls it has
- // responsibility that the pointer is valid, and remains valid
- // throughout the lifetime of the `Owned<T>` and its clones.
- // With that guarantee, reference counting ensures that
- // the object remains alive.
- unsafe { &*self.0.as_ptr() }
- }
-}
-impl<T: ObjectType> ObjectDeref for Owned<T> {}
-
-impl<T: ObjectType> Drop for Owned<T> {
- fn drop(&mut self) {
- assert!(bql_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<T>` and its clones.
- unsafe {
- object_unref(self.as_object_mut_ptr().cast::<c_void>());
- }
- }
-}
-
-impl<T: IsA<Object>> fmt::Debug for Owned<T> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.deref().debug_fmt(f)
- }
-}
-
-/// Trait for class methods exposed by the Object class. The methods can be
-/// called on all objects that have the trait `IsA<Object>`.
-///
-/// The trait should only be used through the blanket implementation,
-/// which guarantees safety via `IsA`
-pub trait ObjectClassMethods: IsA<Object> {
- /// Return a new reference counted instance of this class
- fn new() -> Owned<Self> {
- assert!(bql_locked());
- // SAFETY: the object created by object_new is allocated on
- // the heap and has a reference count of 1
- unsafe {
- let raw_obj = object_new(Self::TYPE_NAME.as_ptr());
- let obj = Object::from_raw(raw_obj).unsafe_cast::<Self>();
- Owned::from_raw(obj)
- }
- }
-}
-
-/// Trait for methods exposed by the Object class. The methods can be
-/// called on all objects that have the trait `IsA<Object>`.
-///
-/// The trait should only be used through the blanket implementation,
-/// which guarantees safety via `IsA`
-pub trait ObjectMethods: ObjectDeref
-where
- Self::Target: IsA<Object>,
-{
- /// Return the name of the type of `self`
- fn typename(&self) -> std::borrow::Cow<'_, str> {
- let obj = self.upcast::<Object>();
- // SAFETY: safety of this is the requirement for implementing IsA
- // The result of the C API has static lifetime
- unsafe {
- let p = object_get_typename(obj.as_mut_ptr());
- CStr::from_ptr(p).to_string_lossy()
- }
- }
-
- fn get_class(&self) -> &'static <Self::Target as ObjectType>::Class {
- let obj = self.upcast::<Object>();
-
- // SAFETY: all objects can call object_get_class; the actual class
- // type is guaranteed by the implementation of `ObjectType` and
- // `ObjectImpl`.
- let klass: &'static <Self::Target as ObjectType>::Class =
- unsafe { &*object_get_class(obj.as_mut_ptr()).cast() };
-
- klass
- }
-
- /// Convenience function for implementing the Debug trait
- fn debug_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_tuple(&self.typename())
- .field(&(self as *const Self))
- .finish()
- }
-}
-
-impl<T> ObjectClassMethods for T where T: IsA<Object> {}
-impl<R: ObjectDeref> ObjectMethods for R where R::Target: IsA<Object> {}
diff --git a/rust/qemu-api/src/sysbus.rs b/rust/qemu-api/src/sysbus.rs
deleted file mode 100644
index e92502a..0000000
--- a/rust/qemu-api/src/sysbus.rs
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2024 Red Hat, Inc.
-// Author(s): Paolo Bonzini <pbonzini@redhat.com>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! Bindings to access `sysbus` functionality from Rust.
-
-use std::{ffi::CStr, ptr::addr_of_mut};
-
-pub use bindings::SysBusDeviceClass;
-
-use crate::{
- bindings,
- cell::{bql_locked, Opaque},
- irq::{IRQState, InterruptSource},
- memory::MemoryRegion,
- prelude::*,
- qdev::{DeviceImpl, DeviceState},
- qom::Owned,
-};
-
-/// A safe wrapper around [`bindings::SysBusDevice`].
-#[repr(transparent)]
-#[derive(Debug, qemu_api_macros::Wrapper)]
-pub struct SysBusDevice(Opaque<bindings::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) };
-}
-qom_isa!(SysBusDevice: DeviceState, Object);
-
-// TODO: add virtual methods
-pub trait SysBusDeviceImpl: DeviceImpl + IsA<SysBusDevice> {}
-
-impl SysBusDeviceClass {
- /// Fill in the virtual methods of `SysBusDeviceClass` based on the
- /// definitions in the `SysBusDeviceImpl` trait.
- pub fn class_init<T: SysBusDeviceImpl>(self: &mut SysBusDeviceClass) {
- self.parent_class.class_init::<T>();
- }
-}
-
-/// Trait for methods of [`SysBusDevice`] and its subclasses.
-pub trait SysBusDeviceMethods: ObjectDeref
-where
- Self::Target: IsA<SysBusDevice>,
-{
- /// Expose a memory region to the board so that it can give it an address
- /// in guest memory. Note that the ordering of calls to `init_mmio` is
- /// important, since whoever creates the sysbus device will refer to the
- /// region with a number that corresponds to the order of calls to
- /// `init_mmio`.
- fn init_mmio(&self, iomem: &MemoryRegion) {
- assert!(bql_locked());
- unsafe {
- bindings::sysbus_init_mmio(self.upcast().as_mut_ptr(), iomem.as_mut_ptr());
- }
- }
-
- /// Expose an interrupt source outside the device as a qdev GPIO output.
- /// Note that the ordering of calls to `init_irq` is important, since
- /// 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());
- unsafe {
- bindings::sysbus_init_irq(self.upcast().as_mut_ptr(), irq.as_ptr());
- }
- }
-
- // TODO: do we want a type like GuestAddress here?
- fn mmio_addr(&self, id: u32) -> Option<u64> {
- assert!(bql_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 id: usize = id.try_into().unwrap();
- if sbd.mmio[id].memory.is_null() {
- None
- } else {
- Some(sbd.mmio[id].addr)
- }
- }
-
- // TODO: do we want a type like GuestAddress here?
- fn mmio_map(&self, id: u32, addr: u64) {
- assert!(bql_locked());
- let id: i32 = id.try_into().unwrap();
- unsafe {
- bindings::sysbus_mmio_map(self.upcast().as_mut_ptr(), id, addr);
- }
- }
-
- // Owned<> is used here because sysbus_connect_irq (via
- // object_property_set_link) adds a reference to the IRQState,
- // which can prolong its life
- fn connect_irq(&self, id: u32, irq: &Owned<IRQState>) {
- assert!(bql_locked());
- 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());
- }
- }
-
- fn sysbus_realize(&self) {
- // TODO: return an Error
- assert!(bql_locked());
- unsafe {
- bindings::sysbus_realize(
- self.upcast().as_mut_ptr(),
- addr_of_mut!(bindings::error_fatal),
- );
- }
- }
-}
-
-impl<R: ObjectDeref> SysBusDeviceMethods for R where R::Target: IsA<SysBusDevice> {}
diff --git a/rust/qemu-api/src/timer.rs b/rust/qemu-api/src/timer.rs
deleted file mode 100644
index 868bd88..0000000
--- a/rust/qemu-api/src/timer.rs
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (C) 2024 Intel Corporation.
-// Author(s): Zhao Liu <zhai1.liu@intel.com>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-use std::{
- ffi::{c_int, c_void},
- pin::Pin,
-};
-
-use crate::{
- bindings::{self, qemu_clock_get_ns, timer_del, timer_init_full, timer_mod, QEMUClockType},
- callbacks::FnCall,
- cell::Opaque,
-};
-
-/// A safe wrapper around [`bindings::QEMUTimer`].
-#[repr(transparent)]
-#[derive(Debug, qemu_api_macros::Wrapper)]
-pub struct Timer(Opaque<bindings::QEMUTimer>);
-
-unsafe impl Send for Timer {}
-unsafe impl Sync for Timer {}
-
-#[repr(transparent)]
-#[derive(qemu_api_macros::Wrapper)]
-pub struct TimerListGroup(Opaque<bindings::QEMUTimerListGroup>);
-
-unsafe impl Send for TimerListGroup {}
-unsafe impl Sync for TimerListGroup {}
-
-impl Timer {
- pub const MS: u32 = bindings::SCALE_MS;
- pub const US: u32 = bindings::SCALE_US;
- pub const NS: u32 = bindings::SCALE_NS;
-
- /// Create a `Timer` struct without initializing it.
- ///
- /// # Safety
- ///
- /// The timer must be initialized before it is armed with
- /// [`modify`](Self::modify).
- pub unsafe fn new() -> Self {
- // SAFETY: requirements relayed to callers of Timer::new
- Self(unsafe { Opaque::zeroed() })
- }
-
- /// Create a new timer with the given attributes.
- pub fn init_full<'timer, 'opaque: 'timer, T, F>(
- self: Pin<&'timer mut Self>,
- timer_list_group: Option<&TimerListGroup>,
- clk_type: ClockType,
- scale: u32,
- attributes: u32,
- _cb: F,
- opaque: &'opaque T,
- ) where
- F: for<'a> FnCall<(&'a T,)>,
- {
- let _: () = F::ASSERT_IS_SOME;
-
- /// timer expiration callback
- unsafe extern "C" fn rust_timer_handler<T, F: for<'a> FnCall<(&'a T,)>>(
- opaque: *mut c_void,
- ) {
- // SAFETY: the opaque was passed as a reference to `T`.
- F::call((unsafe { &*(opaque.cast::<T>()) },))
- }
-
- let timer_cb: unsafe extern "C" fn(*mut c_void) = rust_timer_handler::<T, F>;
-
- // SAFETY: the opaque outlives the timer
- unsafe {
- timer_init_full(
- self.as_mut_ptr(),
- if let Some(g) = timer_list_group {
- g as *const TimerListGroup as *mut _
- } else {
- ::core::ptr::null_mut()
- },
- clk_type.id,
- scale as c_int,
- attributes as c_int,
- Some(timer_cb),
- (opaque as *const T).cast::<c_void>().cast_mut(),
- )
- }
- }
-
- pub fn modify(&self, expire_time: u64) {
- // SAFETY: the only way to obtain a Timer safely is via methods that
- // take a Pin<&mut Self>, therefore the timer is pinned
- unsafe { timer_mod(self.as_mut_ptr(), expire_time as i64) }
- }
-
- pub fn delete(&self) {
- // SAFETY: the only way to obtain a Timer safely is via methods that
- // take a Pin<&mut Self>, therefore the timer is pinned
- unsafe { timer_del(self.as_mut_ptr()) }
- }
-}
-
-// FIXME: use something like PinnedDrop from the pinned_init crate
-impl Drop for Timer {
- fn drop(&mut self) {
- self.delete()
- }
-}
-
-pub struct ClockType {
- id: QEMUClockType,
-}
-
-impl ClockType {
- pub fn get_ns(&self) -> u64 {
- // SAFETY: cannot be created outside this module, therefore id
- // is valid
- (unsafe { qemu_clock_get_ns(self.id) }) as u64
- }
-}
-
-pub const CLOCK_VIRTUAL: ClockType = ClockType {
- id: QEMUClockType::QEMU_CLOCK_VIRTUAL,
-};
-
-pub const NANOSECONDS_PER_SECOND: u64 = 1000000000;
diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs
deleted file mode 100644
index 9c8b239..0000000
--- a/rust/qemu-api/src/vmstate.rs
+++ /dev/null
@@ -1,604 +0,0 @@
-// Copyright 2024, Linaro Limited
-// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-//! Helper macros to declare migration state for device models.
-//!
-//! This module includes four families of macros:
-//!
-//! * [`vmstate_unused!`](crate::vmstate_unused) and
-//! [`vmstate_of!`](crate::vmstate_of), which are used to express the
-//! migration format for a struct. This is based on the [`VMState`] trait,
-//! which is defined by all migrateable types.
-//!
-//! * [`impl_vmstate_forward`](crate::impl_vmstate_forward) and
-//! [`impl_vmstate_bitsized`](crate::impl_vmstate_bitsized), which help with
-//! the definition of the [`VMState`] trait (respectively for transparent
-//! structs and for `bilge`-defined types)
-//!
-//! * helper macros to declare a device model state struct, in particular
-//! [`vmstate_subsections`](crate::vmstate_subsections) and
-//! [`vmstate_fields`](crate::vmstate_fields).
-//!
-//! * direct equivalents to the C macros declared in
-//! `include/migration/vmstate.h`. These are not type-safe and only provide
-//! functionality that is missing from `vmstate_of!`.
-
-use core::{marker::PhantomData, mem, ptr::NonNull};
-use std::ffi::{c_int, c_void};
-
-pub use crate::bindings::{VMStateDescription, VMStateField};
-use crate::{
- bindings::VMStateFlags, callbacks::FnCall, prelude::*, qom::Owned, zeroable::Zeroable,
-};
-
-/// This macro is used to call a function with a generic argument bound
-/// to the type of a field. The function must take a
-/// [`PhantomData`]`<T>` argument; `T` is the type of
-/// field `$field` in the `$typ` type.
-///
-/// # Examples
-///
-/// ```
-/// # use qemu_api::call_func_with_field;
-/// # use core::marker::PhantomData;
-/// const fn size_of_field<T>(_: PhantomData<T>) -> usize {
-/// std::mem::size_of::<T>()
-/// }
-///
-/// struct Foo {
-/// x: u16,
-/// };
-/// // calls size_of_field::<u16>()
-/// assert_eq!(call_func_with_field!(size_of_field, Foo, x), 2);
-/// ```
-#[macro_export]
-macro_rules! call_func_with_field {
- // Based on the answer by user steffahn (Frank Steffahn) at
- // https://users.rust-lang.org/t/inferring-type-of-field/122857
- // and used under MIT license
- ($func:expr, $typ:ty, $($field:tt).+) => {
- $func(loop {
- #![allow(unreachable_code)]
- const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> { ::core::marker::PhantomData }
- // Unreachable code is exempt from checks on uninitialized values.
- // Use that trick to infer the type of this PhantomData.
- break ::core::marker::PhantomData;
- break phantom__(&{ let value__: $typ; value__.$($field).+ });
- })
- };
-}
-
-/// Workaround for lack of `const_refs_static`: references to global variables
-/// can be included in a `static`, but not in a `const`; unfortunately, this
-/// is exactly what would go in the `VMStateField`'s `info` member.
-///
-/// This enum contains the contents of the `VMStateField`'s `info` member,
-/// but as an `enum` instead of a pointer.
-#[allow(non_camel_case_types)]
-pub enum VMStateFieldType {
- null,
- vmstate_info_bool,
- vmstate_info_int8,
- vmstate_info_int16,
- vmstate_info_int32,
- vmstate_info_int64,
- vmstate_info_uint8,
- vmstate_info_uint16,
- vmstate_info_uint32,
- vmstate_info_uint64,
- vmstate_info_timer,
-}
-
-/// Workaround for lack of `const_refs_static`. Converts a `VMStateFieldType`
-/// to a `*const VMStateInfo`, for inclusion in a `VMStateField`.
-#[macro_export]
-macro_rules! info_enum_to_ref {
- ($e:expr) => {
- unsafe {
- match $e {
- $crate::vmstate::VMStateFieldType::null => ::core::ptr::null(),
- $crate::vmstate::VMStateFieldType::vmstate_info_bool => {
- ::core::ptr::addr_of!($crate::bindings::vmstate_info_bool)
- }
- $crate::vmstate::VMStateFieldType::vmstate_info_int8 => {
- ::core::ptr::addr_of!($crate::bindings::vmstate_info_int8)
- }
- $crate::vmstate::VMStateFieldType::vmstate_info_int16 => {
- ::core::ptr::addr_of!($crate::bindings::vmstate_info_int16)
- }
- $crate::vmstate::VMStateFieldType::vmstate_info_int32 => {
- ::core::ptr::addr_of!($crate::bindings::vmstate_info_int32)
- }
- $crate::vmstate::VMStateFieldType::vmstate_info_int64 => {
- ::core::ptr::addr_of!($crate::bindings::vmstate_info_int64)
- }
- $crate::vmstate::VMStateFieldType::vmstate_info_uint8 => {
- ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint8)
- }
- $crate::vmstate::VMStateFieldType::vmstate_info_uint16 => {
- ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint16)
- }
- $crate::vmstate::VMStateFieldType::vmstate_info_uint32 => {
- ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint32)
- }
- $crate::vmstate::VMStateFieldType::vmstate_info_uint64 => {
- ::core::ptr::addr_of!($crate::bindings::vmstate_info_uint64)
- }
- $crate::vmstate::VMStateFieldType::vmstate_info_timer => {
- ::core::ptr::addr_of!($crate::bindings::vmstate_info_timer)
- }
- }
- }
- };
-}
-
-/// A trait for types that can be included in a device's migration stream. It
-/// provides the base contents of a `VMStateField` (minus the name and offset).
-///
-/// # Safety
-///
-/// The contents of this trait go straight into structs that are parsed by C
-/// code and used to introspect into other structs. Generally, you don't need
-/// to implement it except via macros that do it for you, such as
-/// `impl_vmstate_bitsized!`.
-pub unsafe trait VMState {
- /// The `info` member of a `VMStateField` is a pointer and as such cannot
- /// yet be included in the [`BASE`](VMState::BASE) associated constant;
- /// this is only allowed by Rust 1.83.0 and newer. For now, include the
- /// member as an enum which is stored in a separate constant.
- const SCALAR_TYPE: VMStateFieldType = VMStateFieldType::null;
-
- /// The base contents of a `VMStateField` (minus the name and offset) for
- /// the type that is implementing the trait.
- const BASE: VMStateField;
-
- /// A flag that is added to another field's `VMStateField` to specify the
- /// length's type in a variable-sized array. If this is not a supported
- /// type for the length (i.e. if it is not `u8`, `u16`, `u32`), using it
- /// in a call to [`vmstate_of!`](crate::vmstate_of) will cause a
- /// compile-time error.
- const VARRAY_FLAG: VMStateFlags = {
- panic!("invalid type for variable-sized array");
- };
-}
-
-/// Internal utility function to retrieve a type's `VMStateFieldType`;
-/// used by [`vmstate_of!`](crate::vmstate_of).
-pub const fn vmstate_scalar_type<T: VMState>(_: PhantomData<T>) -> VMStateFieldType {
- T::SCALAR_TYPE
-}
-
-/// Internal utility function to retrieve a type's `VMStateField`;
-/// used by [`vmstate_of!`](crate::vmstate_of).
-pub const fn vmstate_base<T: VMState>(_: PhantomData<T>) -> VMStateField {
- T::BASE
-}
-
-/// Internal utility function to retrieve a type's `VMStateFlags` when it
-/// is used as the element count of a `VMSTATE_VARRAY`; used by
-/// [`vmstate_of!`](crate::vmstate_of).
-pub const fn vmstate_varray_flag<T: VMState>(_: PhantomData<T>) -> VMStateFlags {
- T::VARRAY_FLAG
-}
-
-/// Return the `VMStateField` for a field of a struct. The field must be
-/// visible in the current scope.
-///
-/// Only a limited set of types is supported out of the box:
-/// * scalar types (integer and `bool`)
-/// * the C struct `QEMUTimer`
-/// * a transparent wrapper for any of the above (`Cell`, `UnsafeCell`,
-/// [`BqlCell`], [`BqlRefCell`]
-/// * a raw pointer to any of the above
-/// * a `NonNull` pointer, a `Box` or an [`Owned`] for any of the above
-/// * an array of any of the above
-///
-/// In order to support other types, the trait `VMState` must be implemented
-/// for them. The macros
-/// [`impl_vmstate_bitsized!`](crate::impl_vmstate_bitsized)
-/// and [`impl_vmstate_forward!`](crate::impl_vmstate_forward) help with this.
-#[macro_export]
-macro_rules! vmstate_of {
- ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:expr)?])? $(, $test_fn:expr)? $(,)?) => {
- $crate::bindings::VMStateField {
- name: ::core::concat!(::core::stringify!($field_name), "\0")
- .as_bytes()
- .as_ptr() as *const ::std::os::raw::c_char,
- offset: ::std::mem::offset_of!($struct_name, $field_name),
- $(num_offset: ::std::mem::offset_of!($struct_name, $num),)?
- $(field_exists: $crate::vmstate_exist_fn!($struct_name, $test_fn),)?
- // The calls to `call_func_with_field!` are the magic that
- // computes most of the VMStateField from the type of the field.
- info: $crate::info_enum_to_ref!($crate::call_func_with_field!(
- $crate::vmstate::vmstate_scalar_type,
- $struct_name,
- $field_name
- )),
- ..$crate::call_func_with_field!(
- $crate::vmstate::vmstate_base,
- $struct_name,
- $field_name
- )$(.with_varray_flag($crate::call_func_with_field!(
- $crate::vmstate::vmstate_varray_flag,
- $struct_name,
- $num))
- $(.with_varray_multiply($factor))?)?
- }
- };
-}
-
-impl 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) -> VMStateField {
- 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) -> VMStateField {
- 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) -> VMStateField {
- 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.
-///
-/// # Examples
-///
-/// ```
-/// # use qemu_api::impl_vmstate_forward;
-/// pub struct Fifo([u8; 16]);
-/// impl_vmstate_forward!(Fifo);
-/// ```
-#[macro_export]
-macro_rules! impl_vmstate_forward {
- // This is similar to impl_vmstate_transparent below, but it
- // uses the same trick as vmstate_of! to obtain the type of
- // the first field of the tuple
- ($tuple:ty) => {
- unsafe impl $crate::vmstate::VMState for $tuple {
- const SCALAR_TYPE: $crate::vmstate::VMStateFieldType =
- $crate::call_func_with_field!($crate::vmstate::vmstate_scalar_type, $tuple, 0);
- const BASE: $crate::bindings::VMStateField =
- $crate::call_func_with_field!($crate::vmstate::vmstate_base, $tuple, 0);
- }
- };
-}
-
-// Transparent wrappers: just use the internal type
-
-macro_rules! impl_vmstate_transparent {
- ($type:ty where $base:tt: VMState $($where:tt)*) => {
- unsafe impl<$base> VMState for $type where $base: VMState $($where)* {
- const SCALAR_TYPE: VMStateFieldType = <$base as VMState>::SCALAR_TYPE;
- const BASE: VMStateField = VMStateField {
- size: mem::size_of::<$type>(),
- ..<$base as VMState>::BASE
- };
- const VARRAY_FLAG: VMStateFlags = <$base as VMState>::VARRAY_FLAG;
- }
- };
-}
-
-impl_vmstate_transparent!(std::cell::Cell<T> where T: VMState);
-impl_vmstate_transparent!(std::cell::UnsafeCell<T> where T: VMState);
-impl_vmstate_transparent!(std::pin::Pin<T> where T: VMState);
-impl_vmstate_transparent!(crate::cell::BqlCell<T> where T: VMState);
-impl_vmstate_transparent!(crate::cell::BqlRefCell<T> where T: VMState);
-impl_vmstate_transparent!(crate::cell::Opaque<T> where T: VMState);
-
-#[macro_export]
-macro_rules! impl_vmstate_bitsized {
- ($type:ty) => {
- unsafe impl $crate::vmstate::VMState for $type {
- const SCALAR_TYPE: $crate::vmstate::VMStateFieldType =
- <<<$type as ::bilge::prelude::Bitsized>::ArbitraryInt
- as ::bilge::prelude::Number>::UnderlyingType
- as $crate::vmstate::VMState>::SCALAR_TYPE;
- const BASE: $crate::bindings::VMStateField =
- <<<$type as ::bilge::prelude::Bitsized>::ArbitraryInt
- as ::bilge::prelude::Number>::UnderlyingType
- as $crate::vmstate::VMState>::BASE;
- const VARRAY_FLAG: $crate::bindings::VMStateFlags =
- <<<$type as ::bilge::prelude::Bitsized>::ArbitraryInt
- as ::bilge::prelude::Number>::UnderlyingType
- as $crate::vmstate::VMState>::VARRAY_FLAG;
- }
- };
-}
-
-// Scalar types using predefined VMStateInfos
-
-macro_rules! impl_vmstate_scalar {
- ($info:ident, $type:ty$(, $varray_flag:ident)?) => {
- unsafe impl VMState for $type {
- const SCALAR_TYPE: VMStateFieldType = VMStateFieldType::$info;
- const BASE: VMStateField = VMStateField {
- size: mem::size_of::<$type>(),
- flags: VMStateFlags::VMS_SINGLE,
- ..Zeroable::ZERO
- };
- $(const VARRAY_FLAG: VMStateFlags = VMStateFlags::$varray_flag;)?
- }
- };
-}
-
-impl_vmstate_scalar!(vmstate_info_bool, bool);
-impl_vmstate_scalar!(vmstate_info_int8, i8);
-impl_vmstate_scalar!(vmstate_info_int16, i16);
-impl_vmstate_scalar!(vmstate_info_int32, i32);
-impl_vmstate_scalar!(vmstate_info_int64, i64);
-impl_vmstate_scalar!(vmstate_info_uint8, u8, VMS_VARRAY_UINT8);
-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);
-
-// Pointer types using the underlying type's VMState plus VMS_POINTER
-// Note that references are not supported, though references to cells
-// could be allowed.
-
-macro_rules! impl_vmstate_pointer {
- ($type:ty where $base:tt: VMState $($where:tt)*) => {
- unsafe impl<$base> VMState for $type where $base: VMState $($where)* {
- const SCALAR_TYPE: VMStateFieldType = <T as VMState>::SCALAR_TYPE;
- const BASE: VMStateField = <$base as VMState>::BASE.with_pointer_flag();
- }
- };
-}
-
-impl_vmstate_pointer!(*const T where T: VMState);
-impl_vmstate_pointer!(*mut T where T: VMState);
-impl_vmstate_pointer!(NonNull<T> where T: VMState);
-
-// Unlike C pointers, Box is always non-null therefore there is no need
-// to specify VMS_ALLOC.
-impl_vmstate_pointer!(Box<T> where T: VMState);
-impl_vmstate_pointer!(Owned<T> where T: VMState + ObjectType);
-
-// Arrays using the underlying type's VMState plus
-// VMS_ARRAY/VMS_ARRAY_OF_POINTER
-
-unsafe impl<T: VMState, const N: usize> VMState for [T; N] {
- const SCALAR_TYPE: VMStateFieldType = <T as VMState>::SCALAR_TYPE;
- const BASE: VMStateField = <T as VMState>::BASE.with_array_flag(N);
-}
-
-#[doc(alias = "VMSTATE_UNUSED")]
-#[macro_export]
-macro_rules! vmstate_unused {
- ($size:expr) => {{
- $crate::bindings::VMStateField {
- name: c"unused".as_ptr(),
- size: $size,
- info: unsafe { ::core::ptr::addr_of!($crate::bindings::vmstate_info_unused_buffer) },
- flags: $crate::bindings::VMStateFlags::VMS_BUFFER,
- ..$crate::zeroable::Zeroable::ZERO
- }
- }};
-}
-
-pub extern "C" fn rust_vms_test_field_exists<T, F: for<'a> FnCall<(&'a T, u8), bool>>(
- opaque: *mut c_void,
- version_id: c_int,
-) -> bool {
- // SAFETY: the opaque was passed as a reference to `T`.
- let owner: &T = unsafe { &*(opaque.cast::<T>()) };
- let version: u8 = version_id.try_into().unwrap();
- F::call((owner, version))
-}
-
-pub type VMSFieldExistCb = unsafe extern "C" fn(
- opaque: *mut std::os::raw::c_void,
- version_id: std::os::raw::c_int,
-) -> bool;
-
-#[macro_export]
-macro_rules! vmstate_exist_fn {
- ($struct_name:ty, $test_fn:expr) => {{
- const fn test_cb_builder__<T, F: for<'a> $crate::callbacks::FnCall<(&'a T, u8), bool>>(
- _phantom: ::core::marker::PhantomData<F>,
- ) -> $crate::vmstate::VMSFieldExistCb {
- let _: () = F::ASSERT_IS_SOME;
- $crate::vmstate::rust_vms_test_field_exists::<T, F>
- }
-
- const fn phantom__<T>(_: &T) -> ::core::marker::PhantomData<T> {
- ::core::marker::PhantomData
- }
- Some(test_cb_builder__::<$struct_name, _>(phantom__(&$test_fn)))
- }};
-}
-
-// FIXME: including the `vmsd` field in a `const` is not possible without
-// the const_refs_static feature (stabilized in Rust 1.83.0). Without it,
-// it is not possible to use VMS_STRUCT in a transparent manner using
-// `vmstate_of!`. While VMSTATE_CLOCK can at least try to be type-safe,
-// VMSTATE_STRUCT includes $type only for documentation purposes; it
-// is checked against $field_name and $struct_name, but not against $vmsd
-// which is what really would matter.
-#[doc(alias = "VMSTATE_STRUCT")]
-#[macro_export]
-macro_rules! vmstate_struct {
- ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:expr)?])?, $vmsd:expr, $type:ty $(, $test_fn:expr)? $(,)?) => {
- $crate::bindings::VMStateField {
- name: ::core::concat!(::core::stringify!($field_name), "\0")
- .as_bytes()
- .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, $type $(, num = $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
- } $(.with_varray_flag_unchecked(
- $crate::call_func_with_field!(
- $crate::vmstate::vmstate_varray_flag,
- $struct_name,
- $num
- )
- )
- $(.with_varray_multiply($factor))?)?
- };
-}
-
-#[doc(alias = "VMSTATE_CLOCK")]
-#[macro_export]
-macro_rules! vmstate_clock {
- ($struct_name:ty, $field_name:ident $([0 .. $num:ident $(* $factor:expr)?])?) => {{
- $crate::bindings::VMStateField {
- name: ::core::concat!(::core::stringify!($field_name), "\0")
- .as_bytes()
- .as_ptr() as *const ::std::os::raw::c_char,
- offset: {
- $crate::assert_field_type!(
- $struct_name,
- $field_name,
- $crate::qom::Owned<$crate::qdev::Clock> $(, num = $num)?
- );
- ::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) },
- ..$crate::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.
-#[macro_export]
-macro_rules! vmstate_fields {
- ($($field:expr),*$(,)*) => {{
- static _FIELDS: &[$crate::bindings::VMStateField] = &[
- $($field),*,
- $crate::bindings::VMStateField {
- flags: $crate::bindings::VMStateFlags::VMS_END,
- ..$crate::zeroable::Zeroable::ZERO
- }
- ];
- _FIELDS.as_ptr()
- }}
-}
-
-#[doc(alias = "VMSTATE_VALIDATE")]
-#[macro_export]
-macro_rules! vmstate_validate {
- ($struct_name:ty, $test_name:expr, $test_fn:expr $(,)?) => {
- $crate::bindings::VMStateField {
- name: ::std::ffi::CStr::as_ptr($test_name),
- field_exists: $crate::vmstate_exist_fn!($struct_name, $test_fn),
- flags: $crate::bindings::VMStateFlags(
- $crate::bindings::VMStateFlags::VMS_MUST_EXIST.0
- | $crate::bindings::VMStateFlags::VMS_ARRAY.0,
- ),
- num: 0, // 0 elements: no data, only run test_fn callback
- ..$crate::zeroable::Zeroable::ZERO
- }
- };
-}
-
-/// A transparent wrapper type for the `subsections` field of
-/// [`VMStateDescription`].
-///
-/// This is necessary to be able to declare subsection descriptions as statics,
-/// because the only way to implement `Sync` for a foreign type (and `*const`
-/// pointers are foreign types in Rust) is to create a wrapper struct and
-/// `unsafe impl Sync` for it.
-///
-/// This struct is used in the
-/// [`vm_state_subsections`](crate::vmstate_subsections) macro implementation.
-#[repr(transparent)]
-pub struct VMStateSubsectionsWrapper(pub &'static [*const crate::bindings::VMStateDescription]);
-
-unsafe impl Sync for VMStateSubsectionsWrapper {}
-
-/// Helper macro to declare a list of subsections ([`VMStateDescription`])
-/// into a static and return a pointer to the array of pointers it created.
-#[macro_export]
-macro_rules! vmstate_subsections {
- ($($subsection:expr),*$(,)*) => {{
- static _SUBSECTIONS: $crate::vmstate::VMStateSubsectionsWrapper = $crate::vmstate::VMStateSubsectionsWrapper(&[
- $({
- static _SUBSECTION: $crate::bindings::VMStateDescription = $subsection;
- ::core::ptr::addr_of!(_SUBSECTION)
- }),*,
- ::core::ptr::null()
- ]);
- _SUBSECTIONS.0.as_ptr()
- }}
-}
diff --git a/rust/qemu-api/src/zeroable.rs b/rust/qemu-api/src/zeroable.rs
deleted file mode 100644
index d8239d0..0000000
--- 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 bytes.
-
-/// Encapsulates the requirement that
-/// `MaybeUninit::<Self>::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<T>` 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 = unsafe { ::core::mem::MaybeUninit::<Self>::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 {}