[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 02/10] rust: vmstate: implement VMState for non-leaf types
From: |
Paolo Bonzini |
Subject: |
[PATCH 02/10] rust: vmstate: implement VMState for non-leaf types |
Date: |
Fri, 17 Jan 2025 10:00:38 +0100 |
Arrays, pointers and cells use a VMStateField that is based on that
for the inner type. The implementation therefore delegates to the
VMState implementation of the inner type.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
rust/qemu-api/src/vmstate.rs | 79 +++++++++++++++++++++++++++++++++++-
1 file changed, 78 insertions(+), 1 deletion(-)
diff --git a/rust/qemu-api/src/vmstate.rs b/rust/qemu-api/src/vmstate.rs
index b839a7d6b7f..abe15c96011 100644
--- a/rust/qemu-api/src/vmstate.rs
+++ b/rust/qemu-api/src/vmstate.rs
@@ -19,8 +19,9 @@
//! `include/migration/vmstate.h`. These are not type-safe and should not be
//! used if the equivalent functionality is available with `vmstate_of!`.
-use core::marker::PhantomData;
+use core::{marker::PhantomData, mem, ptr::NonNull};
+use crate::bindings::VMStateFlags;
pub use crate::bindings::{VMStateDescription, VMStateField};
/// This macro is used to call a function with a generic argument bound
@@ -102,6 +103,15 @@ macro_rules! vmstate_of {
};
}
+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 {
@@ -111,6 +121,73 @@ pub const fn with_version_id(mut self, version_id: i32) ->
Self {
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);
+ }
+ 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
+ }
+}
+
+// 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 BASE: VMStateField = VMStateField {
+ size: mem::size_of::<$type>(),
+ ..<$base as VMState>::BASE
+ };
+ }
+ };
+}
+
+impl_vmstate_transparent!(std::cell::Cell<T> where T: VMState);
+impl_vmstate_transparent!(std::cell::UnsafeCell<T> where T: VMState);
+impl_vmstate_transparent!(crate::cell::BqlCell<T> where T: VMState);
+impl_vmstate_transparent!(crate::cell::BqlRefCell<T> where T: VMState);
+
+// 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 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);
+
+// 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 BASE: VMStateField = <T as VMState>::BASE.with_array_flag(N);
}
#[doc(alias = "VMSTATE_UNUSED_BUFFER")]
--
2.47.1
- [PATCH 00/10] rust: (mostly) type safe VMState, Paolo Bonzini, 2025/01/17
- [PATCH 01/10] rust: vmstate: add new type safe implementation, Paolo Bonzini, 2025/01/17
- [PATCH 04/10] rust: vmstate: implement Zeroable for VMStateField, Paolo Bonzini, 2025/01/17
- [PATCH 05/10] rust: vmstate: implement VMState for scalar types, Paolo Bonzini, 2025/01/17
- [PATCH 03/10] rust: vmstate: add varray support to vmstate_of!, Paolo Bonzini, 2025/01/17
- [PATCH 07/10] rust: qemu_api: add vmstate_struct, Paolo Bonzini, 2025/01/17
- [PATCH 06/10] rust: vmstate: add public utility macros to implement VMState, Paolo Bonzini, 2025/01/17
- [PATCH 08/10] rust: pl011: switch vmstate to new-style macros, Paolo Bonzini, 2025/01/17
- [PATCH 10/10] rust: vmstate: make order of parameters consistent in vmstate_clock, Paolo Bonzini, 2025/01/17
- [PATCH 09/10] rust: vmstate: remove translation of C vmstate macros, Paolo Bonzini, 2025/01/17
- [PATCH 02/10] rust: vmstate: implement VMState for non-leaf types,
Paolo Bonzini <=