mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 00:33:55 -06:00
rust: qdev: add clock creation
Add a Rust version of qdev_init_clock_in, which can be used in instance_init. There are a couple differences with the C version: - in Rust the object keeps its own reference to the clock (in addition to the one embedded in the NamedClockList), and the reference is dropped automatically by instance_finalize(); this is encoded in the signature of DeviceClassMethods::init_clock_in, which makes the lifetime of the clock independent of that of the object it holds. This goes unnoticed in the C version and is due to the existence of aliases. - also, anything that happens during instance_init uses the pinned_init framework to operate on a partially initialized object, and is done through class methods (i.e. through DeviceClassMethods rather than DeviceMethods) because the device does not exist yet. Therefore, Rust code *must* create clocks from instance_init, which is stricter than C. Reviewed-by: Zhao Liu <zhao1.liu@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
66bcc554d2
commit
201ef001dd
4 changed files with 125 additions and 31 deletions
|
@ -10,17 +10,16 @@ use std::{
|
|||
|
||||
use qemu_api::{
|
||||
bindings::{
|
||||
error_fatal, hwaddr, memory_region_init_io, qdev_init_clock_in, qdev_prop_set_chr,
|
||||
qemu_chr_fe_accept_input, qemu_chr_fe_ioctl, qemu_chr_fe_set_handlers,
|
||||
qemu_chr_fe_write_all, qemu_irq, sysbus_connect_irq, sysbus_mmio_map, sysbus_realize,
|
||||
CharBackend, Chardev, Clock, ClockEvent, MemoryRegion, QEMUChrEvent,
|
||||
CHR_IOCTL_SERIAL_SET_BREAK,
|
||||
error_fatal, hwaddr, memory_region_init_io, qdev_prop_set_chr, qemu_chr_fe_accept_input,
|
||||
qemu_chr_fe_ioctl, qemu_chr_fe_set_handlers, qemu_chr_fe_write_all, qemu_irq,
|
||||
sysbus_connect_irq, sysbus_mmio_map, sysbus_realize, CharBackend, Chardev, MemoryRegion,
|
||||
QEMUChrEvent, CHR_IOCTL_SERIAL_SET_BREAK,
|
||||
},
|
||||
c_str, impl_vmstate_forward,
|
||||
irq::InterruptSource,
|
||||
prelude::*,
|
||||
qdev::{DeviceImpl, DeviceState, Property},
|
||||
qom::{ClassInitImpl, ObjectImpl, ParentField},
|
||||
qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property},
|
||||
qom::{ClassInitImpl, ObjectImpl, Owned, ParentField},
|
||||
sysbus::{SysBusDevice, SysBusDeviceClass},
|
||||
vmstate::VMStateDescription,
|
||||
};
|
||||
|
@ -131,7 +130,7 @@ pub struct PL011State {
|
|||
#[doc(alias = "irq")]
|
||||
pub interrupts: [InterruptSource; IRQMASK.len()],
|
||||
#[doc(alias = "clk")]
|
||||
pub clock: NonNull<Clock>,
|
||||
pub clock: Owned<Clock>,
|
||||
#[doc(alias = "migrate_clk")]
|
||||
pub migrate_clock: bool,
|
||||
}
|
||||
|
@ -485,8 +484,6 @@ impl PL011State {
|
|||
/// location/instance. All its fields are expected to hold unitialized
|
||||
/// values with the sole exception of `parent_obj`.
|
||||
unsafe fn init(&mut self) {
|
||||
const CLK_NAME: &CStr = c_str!("clk");
|
||||
|
||||
// SAFETY:
|
||||
//
|
||||
// self and self.iomem are guaranteed to be valid at this point since callers
|
||||
|
@ -506,22 +503,16 @@ impl PL011State {
|
|||
|
||||
// SAFETY:
|
||||
//
|
||||
// self.clock is not initialized at this point; but since `NonNull<_>` is Copy,
|
||||
// we can overwrite the undefined value without side effects. This is
|
||||
// safe since all PL011State instances are created by QOM code which
|
||||
// calls this function to initialize the fields; therefore no code is
|
||||
// able to access an invalid self.clock value.
|
||||
unsafe {
|
||||
let dev: &mut DeviceState = self.upcast_mut();
|
||||
self.clock = NonNull::new(qdev_init_clock_in(
|
||||
dev,
|
||||
CLK_NAME.as_ptr(),
|
||||
None, /* pl011_clock_update */
|
||||
addr_of_mut!(*self).cast::<c_void>(),
|
||||
ClockEvent::ClockUpdate.0,
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
// self.clock is not initialized at this point; but since `Owned<_>` is
|
||||
// not Drop, we can overwrite the undefined value without side effects;
|
||||
// it's not sound but, because for all PL011State instances are created
|
||||
// by QOM code which calls this function to initialize the fields, at
|
||||
// leastno code is able to access an invalid self.clock value.
|
||||
self.clock = self.init_clock_in("clk", &Self::clock_update, ClockEvent::ClockUpdate);
|
||||
}
|
||||
|
||||
const fn clock_update(&self, _event: ClockEvent) {
|
||||
/* pl011_trace_baudrate_change(s); */
|
||||
}
|
||||
|
||||
fn post_init(&self) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue