diff options
Diffstat (limited to 'rust/qemu-api/src')
-rw-r--r-- | rust/qemu-api/src/assertions.rs | 152 | ||||
-rw-r--r-- | rust/qemu-api/src/bindings.rs | 55 | ||||
-rw-r--r-- | rust/qemu-api/src/bitops.rs | 119 | ||||
-rw-r--r-- | rust/qemu-api/src/callbacks.rs | 241 | ||||
-rw-r--r-- | rust/qemu-api/src/cell.rs | 1105 | ||||
-rw-r--r-- | rust/qemu-api/src/chardev.rs | 260 | ||||
-rw-r--r-- | rust/qemu-api/src/errno.rs | 345 | ||||
-rw-r--r-- | rust/qemu-api/src/irq.rs | 115 | ||||
-rw-r--r-- | rust/qemu-api/src/lib.rs | 165 | ||||
-rw-r--r-- | rust/qemu-api/src/memory.rs | 204 | ||||
-rw-r--r-- | rust/qemu-api/src/module.rs | 43 | ||||
-rw-r--r-- | rust/qemu-api/src/prelude.rs | 29 | ||||
-rw-r--r-- | rust/qemu-api/src/qdev.rs | 395 | ||||
-rw-r--r-- | rust/qemu-api/src/qom.rs | 772 | ||||
-rw-r--r-- | rust/qemu-api/src/sysbus.rs | 122 | ||||
-rw-r--r-- | rust/qemu-api/src/timer.rs | 125 | ||||
-rw-r--r-- | rust/qemu-api/src/vmstate.rs | 604 | ||||
-rw-r--r-- | rust/qemu-api/src/zeroable.rs | 37 |
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 {} |