aboutsummaryrefslogtreecommitdiff
path: root/rust/hw/char/pl011/src
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2025-02-10 16:11:58 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2025-02-13 12:19:34 +0100
commit7630ca2a701a0f79728996e660cda06518c97b9b (patch)
treee5dea0c62d84107da1b947042e90d0ee8f7ad809 /rust/hw/char/pl011/src
parenta22bd55ffd889f3027c3158d0014c76f204c69dd (diff)
downloadqemu-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.rs41
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)]