diff options
Diffstat (limited to 'rust/hw/char/pl011/src/device.rs')
| -rw-r--r-- | rust/hw/char/pl011/src/device.rs | 199 |
1 files changed, 80 insertions, 119 deletions
diff --git a/rust/hw/char/pl011/src/device.rs b/rust/hw/char/pl011/src/device.rs index ceb71dd99b..1b4587d5f6 100644 --- a/rust/hw/char/pl011/src/device.rs +++ b/rust/hw/char/pl011/src/device.rs @@ -2,30 +2,22 @@ // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> // SPDX-License-Identifier: GPL-2.0-or-later -use std::{ - ffi::{c_int, c_void, CStr}, - mem::size_of, - ptr::NonNull, +use std::{ffi::CStr, mem::size_of}; + +use bql::BqlRefCell; +use chardev::{CharBackend, Chardev, Event}; +use common::{static_assert, uninit_field_mut}; +use hwcore::{ + Clock, ClockEvent, DeviceImpl, DeviceMethods, DeviceState, IRQState, InterruptSource, + ResetType, ResettablePhasesImpl, SysBusDevice, SysBusDeviceImpl, SysBusDeviceMethods, }; - -use qemu_api::{ - bindings::{qdev_prop_bool, qdev_prop_chr}, - chardev::{CharBackend, Chardev, Event}, - impl_vmstate_forward, - irq::{IRQState, InterruptSource}, - log::Log, - log_mask_ln, - memory::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder}, - prelude::*, - qdev::{Clock, ClockEvent, DeviceImpl, DeviceState, Property, ResetType, ResettablePhasesImpl}, - qom::{ObjectImpl, Owned, ParentField, ParentInit}, - static_assert, - sysbus::{SysBusDevice, SysBusDeviceImpl}, - uninit_field_mut, - vmstate::VMStateDescription, - vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmstate_unused, - zeroable::Zeroable, +use migration::{ + self, impl_vmstate_forward, impl_vmstate_struct, vmstate_fields, vmstate_of, + vmstate_subsections, vmstate_unused, VMStateDescription, VMStateDescriptionBuilder, }; +use qom::{prelude::*, ObjectImpl, Owned, ParentField, ParentInit}; +use system::{hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder}; +use util::{log::Log, log_mask_ln}; use crate::registers::{self, Interrupt, RegisterOffset}; @@ -105,12 +97,13 @@ pub struct PL011Registers { } #[repr(C)] -#[derive(qemu_api_macros::Object)] +#[derive(qom::Object, hwcore::Device)] /// PL011 Device Model in QEMU pub struct PL011State { pub parent_obj: ParentField<SysBusDevice>, pub iomem: MemoryRegion, #[doc(alias = "chr")] + #[property(rename = "chardev")] pub char_backend: CharBackend, pub regs: BqlRefCell<PL011Registers>, /// QEMU interrupts @@ -129,6 +122,7 @@ pub struct PL011State { #[doc(alias = "clk")] pub clock: Owned<Clock>, #[doc(alias = "migrate_clk")] + #[property(rename = "migrate-clk", default = true)] pub migrate_clock: bool, } @@ -136,7 +130,7 @@ pub struct PL011State { // structs, so the size of the Rust version must not be any larger // than the size of the C one. If this assert triggers you need to // expand the padding_for_rust[] array in the C PL011State struct. -static_assert!(size_of::<PL011State>() <= size_of::<qemu_api::bindings::PL011State>()); +static_assert!(size_of::<PL011State>() <= size_of::<crate::bindings::PL011State>()); qom_isa!(PL011State : SysBusDevice, DeviceState, Object); @@ -176,13 +170,8 @@ impl ObjectImpl for PL011State { } impl DeviceImpl for PL011State { - fn properties() -> &'static [Property] { - &PL011_PROPERTIES - } - fn vmsd() -> Option<&'static VMStateDescription> { - Some(&VMSTATE_PL011) - } - const REALIZE: Option<fn(&Self) -> qemu_api::Result<()>> = Some(Self::realize); + const VMSTATE: Option<VMStateDescription<Self>> = Some(VMSTATE_PL011); + const REALIZE: Option<fn(&Self) -> util::Result<()>> = Some(Self::realize); } impl ResettablePhasesImpl for PL011State { @@ -469,10 +458,10 @@ impl PL011Registers { false } - pub fn post_load(&mut self) -> Result<(), ()> { + pub fn post_load(&mut self) -> Result<(), migration::InvalidError> { /* Sanity-check input state */ if self.read_pos >= self.read_fifo.len() || self.read_count > self.read_fifo.len() { - return Err(()); + return Err(migration::InvalidError); } if !self.fifo_enabled() && self.read_count > 0 && self.read_pos > 0 { @@ -531,6 +520,10 @@ impl PL011State { /* pl011_trace_baudrate_change(s); */ } + pub fn clock_needed(&self) -> bool { + self.migrate_clock + } + fn post_init(&self) { self.init_mmio(&self.iomem); for irq in self.interrupts.iter() { @@ -629,7 +622,7 @@ impl PL011State { } } - fn realize(&self) -> qemu_api::Result<()> { + fn realize(&self) -> util::Result<()> { self.char_backend .enable_handlers(self, Self::can_receive, Self::receive, Self::event); Ok(()) @@ -647,7 +640,7 @@ impl PL011State { } } - pub fn post_load(&self, _version_id: u32) -> Result<(), ()> { + pub fn post_load(&self, _version_id: u8) -> Result<(), migration::InvalidError> { self.regs.borrow_mut().post_load() } } @@ -690,7 +683,7 @@ pub unsafe extern "C" fn pl011_create( } #[repr(C)] -#[derive(qemu_api_macros::Object)] +#[derive(qom::Object, hwcore::Device)] /// PL011 Luminary device model. pub struct PL011Luminary { parent_obj: ParentField<PL011State>, @@ -717,87 +710,55 @@ impl DeviceImpl for PL011Luminary {} impl ResettablePhasesImpl for PL011Luminary {} impl SysBusDeviceImpl for PL011Luminary {} -extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool { - let state = NonNull::new(opaque).unwrap().cast::<PL011State>(); - unsafe { state.as_ref().migrate_clock } -} - /// Migration subsection for [`PL011State`] clock. -static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription { - name: c"pl011/clock".as_ptr(), - version_id: 1, - minimum_version_id: 1, - needed: Some(pl011_clock_needed), - fields: vmstate_fields! { - vmstate_clock!(PL011State, clock), - }, - ..Zeroable::ZERO -}; - -extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int { - let state = NonNull::new(opaque).unwrap().cast::<PL011State>(); - let result = unsafe { state.as_ref().post_load(version_id as u32) }; - if result.is_err() { - -1 - } else { - 0 - } -} - -static VMSTATE_PL011_REGS: VMStateDescription = VMStateDescription { - name: c"pl011/regs".as_ptr(), - version_id: 2, - minimum_version_id: 2, - fields: vmstate_fields! { - vmstate_of!(PL011Registers, flags), - vmstate_of!(PL011Registers, line_control), - vmstate_of!(PL011Registers, receive_status_error_clear), - vmstate_of!(PL011Registers, control), - vmstate_of!(PL011Registers, dmacr), - vmstate_of!(PL011Registers, int_enabled), - vmstate_of!(PL011Registers, int_level), - vmstate_of!(PL011Registers, read_fifo), - vmstate_of!(PL011Registers, ilpr), - vmstate_of!(PL011Registers, ibrd), - vmstate_of!(PL011Registers, fbrd), - vmstate_of!(PL011Registers, ifl), - vmstate_of!(PL011Registers, read_pos), - vmstate_of!(PL011Registers, read_count), - vmstate_of!(PL011Registers, read_trigger), - }, - ..Zeroable::ZERO -}; - -pub static VMSTATE_PL011: VMStateDescription = VMStateDescription { - name: c"pl011".as_ptr(), - version_id: 2, - minimum_version_id: 2, - post_load: Some(pl011_post_load), - fields: vmstate_fields! { - vmstate_unused!(core::mem::size_of::<u32>()), - vmstate_struct!(PL011State, regs, &VMSTATE_PL011_REGS, BqlRefCell<PL011Registers>), - }, - subsections: vmstate_subsections! { - VMSTATE_PL011_CLOCK - }, - ..Zeroable::ZERO -}; - -qemu_api::declare_properties! { - PL011_PROPERTIES, - qemu_api::define_property!( - c"chardev", - PL011State, - char_backend, - unsafe { &qdev_prop_chr }, - CharBackend - ), - qemu_api::define_property!( - c"migrate-clk", - PL011State, - migrate_clock, - unsafe { &qdev_prop_bool }, - bool, - default = true - ), -} +static VMSTATE_PL011_CLOCK: VMStateDescription<PL011State> = + VMStateDescriptionBuilder::<PL011State>::new() + .name(c"pl011/clock") + .version_id(1) + .minimum_version_id(1) + .needed(&PL011State::clock_needed) + .fields(vmstate_fields! { + vmstate_of!(PL011State, clock), + }) + .build(); + +impl_vmstate_struct!( + PL011Registers, + VMStateDescriptionBuilder::<PL011Registers>::new() + .name(c"pl011/regs") + .version_id(2) + .minimum_version_id(2) + .fields(vmstate_fields! { + vmstate_of!(PL011Registers, flags), + vmstate_of!(PL011Registers, line_control), + vmstate_of!(PL011Registers, receive_status_error_clear), + vmstate_of!(PL011Registers, control), + vmstate_of!(PL011Registers, dmacr), + vmstate_of!(PL011Registers, int_enabled), + vmstate_of!(PL011Registers, int_level), + vmstate_of!(PL011Registers, read_fifo), + vmstate_of!(PL011Registers, ilpr), + vmstate_of!(PL011Registers, ibrd), + vmstate_of!(PL011Registers, fbrd), + vmstate_of!(PL011Registers, ifl), + vmstate_of!(PL011Registers, read_pos), + vmstate_of!(PL011Registers, read_count), + vmstate_of!(PL011Registers, read_trigger), + }) + .build() +); + +pub const VMSTATE_PL011: VMStateDescription<PL011State> = + VMStateDescriptionBuilder::<PL011State>::new() + .name(c"pl011") + .version_id(2) + .minimum_version_id(2) + .post_load(&PL011State::post_load) + .fields(vmstate_fields! { + vmstate_unused!(core::mem::size_of::<u32>()), + vmstate_of!(PL011State, regs), + }) + .subsections(vmstate_subsections! { + VMSTATE_PL011_CLOCK + }) + .build(); |