mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 04:13:53 -06:00
rust: vmstate: implement VMState for non-leaf types
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>
This commit is contained in:
parent
0d43ddae35
commit
80aa3045bd
1 changed files with 78 additions and 1 deletions
|
@ -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 @@ impl VMStateField {
|
|||
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")]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue