Re: [PATCH 07/12] rust: qdev: switch from legacy reset to Resettable

2025-02-10 Thread Zhao Liu
On Fri, Feb 07, 2025 at 11:16:18AM +0100, Paolo Bonzini wrote:
> Date: Fri,  7 Feb 2025 11:16:18 +0100
> From: Paolo Bonzini 
> Subject: [PATCH 07/12] rust: qdev: switch from legacy reset to Resettable
> X-Mailer: git-send-email 2.48.1
> 
> Signed-off-by: Paolo Bonzini 
> ---
>  meson.build  |   1 +
>  rust/hw/char/pl011/src/device.rs |  10 ++-
>  rust/qemu-api/src/qdev.rs| 111 ---
>  rust/qemu-api/tests/tests.rs |   5 +-
>  4 files changed, 99 insertions(+), 28 deletions(-)
>

Reviewed-by: Zhao Liu 




[PATCH 07/12] rust: qdev: switch from legacy reset to Resettable

2025-02-07 Thread Paolo Bonzini
Signed-off-by: Paolo Bonzini 
---
 meson.build  |   1 +
 rust/hw/char/pl011/src/device.rs |  10 ++-
 rust/qemu-api/src/qdev.rs| 111 ---
 rust/qemu-api/tests/tests.rs |   5 +-
 4 files changed, 99 insertions(+), 28 deletions(-)

diff --git a/meson.build b/meson.build
index 131b2225ab6..32abefb7c48 100644
--- a/meson.build
+++ b/meson.build
@@ -4072,6 +4072,7 @@ if have_rust
 'MigrationPriority',
 'QEMUChrEvent',
 'QEMUClockType',
+'ResetType',
 'device_endian',
 'module_init_type',
   ]
diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/device.rs
index 37936a328b8..1d0390b4fbe 100644
--- a/rust/hw/char/pl011/src/device.rs
+++ b/rust/hw/char/pl011/src/device.rs
@@ -18,7 +18,7 @@
 c_str, impl_vmstate_forward,
 irq::InterruptSource,
 prelude::*,
-qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property},
+qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType, 
ResettablePhasesImpl},
 qom::{ClassInitImpl, ObjectImpl, Owned, ParentField},
 sysbus::{SysBusDevice, SysBusDeviceClass},
 vmstate::VMStateDescription,
@@ -171,7 +171,10 @@ fn vmsd() -> Option<&'static VMStateDescription> {
 Some(&device_class::VMSTATE_PL011)
 }
 const REALIZE: Option = Some(Self::realize);
-const RESET: Option = Some(Self::reset);
+}
+
+impl ResettablePhasesImpl for PL011State {
+const HOLD: Option = Some(Self::reset_hold);
 }
 
 impl PL011Registers {
@@ -622,7 +625,7 @@ pub fn realize(&self) {
 }
 }
 
-pub fn reset(&self) {
+pub fn reset_hold(&self, _type: ResetType) {
 self.regs.borrow_mut().reset();
 }
 
@@ -737,3 +740,4 @@ impl ObjectImpl for PL011Luminary {
 }
 
 impl DeviceImpl for PL011Luminary {}
+impl ResettablePhasesImpl for PL011Luminary {}
diff --git a/rust/qemu-api/src/qdev.rs b/rust/qemu-api/src/qdev.rs
index cb6f12e726c..2ec1ecc8489 100644
--- a/rust/qemu-api/src/qdev.rs
+++ b/rust/qemu-api/src/qdev.rs
@@ -10,10 +10,10 @@
 ptr::NonNull,
 };
 
-pub use bindings::{Clock, ClockEvent, DeviceClass, DeviceState, Property};
+pub use bindings::{Clock, ClockEvent, DeviceClass, DeviceState, Property, 
ResetType};
 
 use crate::{
-bindings::{self, Error},
+bindings::{self, Error, ResettableClass},
 callbacks::FnCall,
 cell::bql_locked,
 prelude::*,
@@ -21,8 +21,70 @@
 vmstate::VMStateDescription,
 };
 
+/// 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`](crate::irq::InterruptSource), or reading or
+/// writing guest memory. It takes the reset's type as argument.
+const ENTER: Option = 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 = None;
+
+/// If not None, this phase is called when the object leaves the reset
+/// state. Actions affecting other objects are permitted.
+const EXIT: Option = 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(
+obj: *mut Object,
+typ: ResetType,
+) {
+let state = NonNull::new(obj).unwrap().cast::();
+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(
+obj: *mut Object,
+typ: ResetType,
+) {
+let state = NonNull::new(obj).unwrap().cast::();
+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(
+obj: *mut Object,
+typ: ResetType,
+) {
+let state = NonNull::new(obj).unwrap().cast::();
+T::EXIT.unwrap()(unsafe { state.as_ref() }, typ);
+}
+
 /// Trait providing the contents of [`DeviceClass`].
-pub trait DeviceImpl: ObjectImpl {
+pub trait DeviceImpl: ObjectImpl + ResettablePhasesImpl {
 /// _Realization_ is the s