// Copyright 2024, Linaro Limited // Author(s): Manos Pitsidianakis // SPDX-License-Identifier: GPL-2.0-or-later use std::{ os::raw::{c_int, c_void}, ptr::NonNull, }; use qemu_api::{ bindings::{qdev_prop_bool, qdev_prop_chr}, c_str, prelude::*, vmstate::VMStateDescription, vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmstate_unused, zeroable::Zeroable, }; use crate::device::{PL011Registers, PL011State}; extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool { let state = NonNull::new(opaque).unwrap().cast::(); unsafe { state.as_ref().migrate_clock } } /// Migration subsection for [`PL011State`] clock. static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription { name: c_str!("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::(); 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_str!("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_str!("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::()), vmstate_struct!(PL011State, regs, &VMSTATE_PL011_REGS, BqlRefCell), }, subsections: vmstate_subsections! { VMSTATE_PL011_CLOCK }, ..Zeroable::ZERO }; qemu_api::declare_properties! { PL011_PROPERTIES, qemu_api::define_property!( c_str!("chardev"), PL011State, char_backend, unsafe { &qdev_prop_chr }, CharBackend ), qemu_api::define_property!( c_str!("migrate-clk"), PL011State, migrate_clock, unsafe { &qdev_prop_bool }, bool, default = true ), }