rust: qdev: wrap Clock and DeviceState with Opaque<>

Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2025-02-14 11:45:25 +01:00
parent 7fb4a99df1
commit fc22d650d5
3 changed files with 49 additions and 27 deletions

View file

@ -34,12 +34,6 @@ unsafe impl Sync for CharBackend {}
unsafe impl Send for Chardev {} unsafe impl Send for Chardev {}
unsafe impl Sync for Chardev {} unsafe impl Sync for Chardev {}
unsafe impl Send for Clock {}
unsafe impl Sync for Clock {}
unsafe impl Send for DeviceState {}
unsafe impl Sync for DeviceState {}
unsafe impl Send for MemoryRegion {} unsafe impl Send for MemoryRegion {}
unsafe impl Sync for MemoryRegion {} unsafe impl Sync for MemoryRegion {}

View file

@ -10,12 +10,12 @@ use std::{
ptr::NonNull, ptr::NonNull,
}; };
pub use bindings::{Clock, ClockEvent, DeviceClass, DeviceState, Property, ResetType}; pub use bindings::{ClockEvent, DeviceClass, Property, ResetType};
use crate::{ use crate::{
bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, Error, ResettableClass}, bindings::{self, qdev_init_gpio_in, qdev_init_gpio_out, Error, ResettableClass},
callbacks::FnCall, callbacks::FnCall,
cell::bql_locked, cell::{bql_locked, Opaque},
chardev::Chardev, chardev::Chardev,
irq::InterruptSource, irq::InterruptSource,
prelude::*, prelude::*,
@ -23,6 +23,22 @@ use crate::{
vmstate::VMStateDescription, 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, /// Trait providing the contents of the `ResettablePhases` struct,
/// which is part of the QOM `Resettable` interface. /// which is part of the QOM `Resettable` interface.
pub trait ResettablePhasesImpl { pub trait ResettablePhasesImpl {
@ -117,7 +133,10 @@ pub trait DeviceImpl: ObjectImpl + ResettablePhasesImpl + IsA<DeviceState> {
/// We expect the FFI user of this function to pass a valid pointer that /// 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 /// can be downcasted to type `T`. We also expect the device is
/// readable/writeable from one thread at any time. /// readable/writeable from one thread at any time.
unsafe extern "C" fn rust_realize_fn<T: DeviceImpl>(dev: *mut DeviceState, _errp: *mut *mut Error) { 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>(); let state = NonNull::new(dev).unwrap().cast::<T>();
T::REALIZE.unwrap()(unsafe { state.as_ref() }); T::REALIZE.unwrap()(unsafe { state.as_ref() });
} }
@ -251,7 +270,7 @@ where
events: ClockEvent, events: ClockEvent,
) -> Owned<Clock> { ) -> Owned<Clock> {
fn do_init_clock_in( fn do_init_clock_in(
dev: *mut DeviceState, dev: &DeviceState,
name: &str, name: &str,
cb: Option<unsafe extern "C" fn(*mut c_void, ClockEvent)>, cb: Option<unsafe extern "C" fn(*mut c_void, ClockEvent)>,
events: ClockEvent, events: ClockEvent,
@ -265,14 +284,15 @@ where
unsafe { unsafe {
let cstr = CString::new(name).unwrap(); let cstr = CString::new(name).unwrap();
let clk = bindings::qdev_init_clock_in( let clk = bindings::qdev_init_clock_in(
dev, dev.as_mut_ptr(),
cstr.as_ptr(), cstr.as_ptr(),
cb, cb,
dev.cast::<c_void>(), dev.as_void_ptr(),
events.0, events.0,
); );
Owned::from(&*clk) let clk: &Clock = Clock::from_raw(clk);
Owned::from(clk)
} }
} }
@ -289,7 +309,7 @@ where
None None
}; };
do_init_clock_in(self.as_mut_ptr(), name, cb, events) do_init_clock_in(self.upcast(), name, cb, events)
} }
/// Add an output clock named `name`. /// Add an output clock named `name`.
@ -304,9 +324,10 @@ where
fn init_clock_out(&self, name: &str) -> Owned<Clock> { fn init_clock_out(&self, name: &str) -> Owned<Clock> {
unsafe { unsafe {
let cstr = CString::new(name).unwrap(); let cstr = CString::new(name).unwrap();
let clk = bindings::qdev_init_clock_out(self.as_mut_ptr(), cstr.as_ptr()); let clk = bindings::qdev_init_clock_out(self.upcast().as_mut_ptr(), cstr.as_ptr());
Owned::from(&*clk) let clk: &Clock = Clock::from_raw(clk);
Owned::from(clk)
} }
} }
@ -314,7 +335,11 @@ where
assert!(bql_locked()); assert!(bql_locked());
let c_propname = CString::new(propname).unwrap(); let c_propname = CString::new(propname).unwrap();
unsafe { unsafe {
bindings::qdev_prop_set_chr(self.as_mut_ptr(), c_propname.as_ptr(), chr.as_mut_ptr()); bindings::qdev_prop_set_chr(
self.upcast().as_mut_ptr(),
c_propname.as_ptr(),
chr.as_mut_ptr(),
);
} }
} }
@ -323,8 +348,17 @@ where
num_lines: u32, num_lines: u32,
_cb: F, _cb: F,
) { ) {
let _: () = F::ASSERT_IS_SOME; 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)>>( unsafe extern "C" fn rust_irq_handler<T, F: for<'a> FnCall<(&'a T, u32, u32)>>(
opaque: *mut c_void, opaque: *mut c_void,
line: c_int, line: c_int,
@ -337,19 +371,13 @@ where
let gpio_in_cb: unsafe extern "C" fn(*mut c_void, c_int, c_int) = let gpio_in_cb: unsafe extern "C" fn(*mut c_void, c_int, c_int) =
rust_irq_handler::<Self::Target, F>; rust_irq_handler::<Self::Target, F>;
unsafe { do_init_gpio_in(self.upcast(), num_lines, gpio_in_cb);
qdev_init_gpio_in(
self.as_mut_ptr::<DeviceState>(),
Some(gpio_in_cb),
num_lines as c_int,
);
}
} }
fn init_gpio_out(&self, pins: &[InterruptSource]) { fn init_gpio_out(&self, pins: &[InterruptSource]) {
unsafe { unsafe {
qdev_init_gpio_out( qdev_init_gpio_out(
self.as_mut_ptr::<DeviceState>(), self.upcast().as_mut_ptr(),
InterruptSource::slice_as_ptr(pins), InterruptSource::slice_as_ptr(pins),
pins.len() as c_int, pins.len() as c_int,
); );

View file

@ -470,7 +470,7 @@ macro_rules! vmstate_clock {
$crate::assert_field_type!( $crate::assert_field_type!(
$struct_name, $struct_name,
$field_name, $field_name,
$crate::qom::Owned<$crate::bindings::Clock> $crate::qom::Owned<$crate::qdev::Clock>
); );
$crate::offset_of!($struct_name, $field_name) $crate::offset_of!($struct_name, $field_name)
}, },