diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2025-02-10 16:11:58 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2025-02-13 12:19:34 +0100 |
commit | 7630ca2a701a0f79728996e660cda06518c97b9b (patch) | |
tree | e5dea0c62d84107da1b947042e90d0ee8f7ad809 /rust/hw/char/pl011/src | |
parent | a22bd55ffd889f3027c3158d0014c76f204c69dd (diff) | |
download | qemu-7630ca2a701a0f79728996e660cda06518c97b9b.zip qemu-7630ca2a701a0f79728996e660cda06518c97b9b.tar.gz qemu-7630ca2a701a0f79728996e660cda06518c97b9b.tar.bz2 |
rust: pl011: convert pl011_create to safe Rust
Not a major change but, as a small but significant step in creating
qdev bindings, show how pl011_create can be written without "unsafe"
calls (apart from converting pointers to references).
This also provides a starting point for creating Error** bindings.
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'rust/hw/char/pl011/src')
-rw-r--r-- | rust/hw/char/pl011/src/device.rs | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/device.rs index 4e95907..fe73771 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -10,14 +10,12 @@ use std::{ use qemu_api::{ bindings::{ - error_fatal, 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, QEMUChrEvent, - CHR_IOCTL_SERIAL_SET_BREAK, + qemu_chr_fe_accept_input, qemu_chr_fe_ioctl, qemu_chr_fe_set_handlers, + qemu_chr_fe_write_all, CharBackend, QEMUChrEvent, CHR_IOCTL_SERIAL_SET_BREAK, }, chardev::Chardev, - c_str, impl_vmstate_forward, - irq::InterruptSource, + impl_vmstate_forward, + irq::{IRQState, InterruptSource}, memory::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder}, prelude::*, qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType, ResettablePhasesImpl}, @@ -698,26 +696,27 @@ pub unsafe extern "C" fn pl011_event(opaque: *mut c_void, event: QEMUChrEvent) { /// # Safety /// -/// We expect the FFI user of this function to pass a valid pointer for `chr`. +/// We expect the FFI user of this function to pass a valid pointer for `chr` +/// and `irq`. #[no_mangle] pub unsafe extern "C" fn pl011_create( addr: u64, - irq: qemu_irq, + irq: *mut IRQState, chr: *mut Chardev, ) -> *mut DeviceState { - let pl011 = PL011State::new(); - unsafe { - let dev = pl011.as_mut_ptr::<DeviceState>(); - qdev_prop_set_chr(dev, c_str!("chardev").as_ptr(), chr); - - let sysbus = pl011.as_mut_ptr::<SysBusDevice>(); - sysbus_realize(sysbus, addr_of_mut!(error_fatal)); - sysbus_mmio_map(sysbus, 0, addr); - sysbus_connect_irq(sysbus, 0, irq); - - // return the pointer, which is kept alive by the QOM tree; drop owned ref - pl011.as_mut_ptr() - } + // SAFETY: The callers promise that they have owned references. + // They do not gift them to pl011_create, so use `Owned::from`. + let irq = unsafe { Owned::<IRQState>::from(&*irq) }; + let chr = unsafe { Owned::<Chardev>::from(&*chr) }; + + let dev = PL011State::new(); + dev.prop_set_chr("chardev", &chr); + dev.sysbus_realize(); + dev.mmio_map(0, addr); + dev.connect_irq(0, &irq); + + // The pointer is kept alive by the QOM tree; drop the owned ref + dev.as_mut_ptr() } #[repr(C)] |