1 // Copyright 2024, Linaro Limited 2 // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org> 3 // SPDX-License-Identifier: GPL-2.0-or-later 4 5 use std::{ 6 os::raw::{c_int, c_void}, 7 ptr::NonNull, 8 }; 9 10 use qemu_api::{ 11 bindings::*, c_str, prelude::*, vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct, 12 vmstate_subsections, vmstate_unused, zeroable::Zeroable, 13 }; 14 15 use crate::device::{PL011Registers, PL011State}; 16 17 extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool { 18 let state = NonNull::new(opaque).unwrap().cast::<PL011State>(); 19 unsafe { state.as_ref().migrate_clock } 20 } 21 22 /// Migration subsection for [`PL011State`] clock. 23 static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription { 24 name: c_str!("pl011/clock").as_ptr(), 25 version_id: 1, 26 minimum_version_id: 1, 27 needed: Some(pl011_clock_needed), 28 fields: vmstate_fields! { 29 vmstate_clock!(PL011State, clock), 30 }, 31 ..Zeroable::ZERO 32 }; 33 34 extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int { 35 let state = NonNull::new(opaque).unwrap().cast::<PL011State>(); 36 let result = unsafe { state.as_ref().post_load(version_id as u32) }; 37 if result.is_err() { 38 -1 39 } else { 40 0 41 } 42 } 43 44 static VMSTATE_PL011_REGS: VMStateDescription = VMStateDescription { 45 name: c_str!("pl011/regs").as_ptr(), 46 version_id: 2, 47 minimum_version_id: 2, 48 fields: vmstate_fields! { 49 vmstate_of!(PL011Registers, flags), 50 vmstate_of!(PL011Registers, line_control), 51 vmstate_of!(PL011Registers, receive_status_error_clear), 52 vmstate_of!(PL011Registers, control), 53 vmstate_of!(PL011Registers, dmacr), 54 vmstate_of!(PL011Registers, int_enabled), 55 vmstate_of!(PL011Registers, int_level), 56 vmstate_of!(PL011Registers, read_fifo), 57 vmstate_of!(PL011Registers, ilpr), 58 vmstate_of!(PL011Registers, ibrd), 59 vmstate_of!(PL011Registers, fbrd), 60 vmstate_of!(PL011Registers, ifl), 61 vmstate_of!(PL011Registers, read_pos), 62 vmstate_of!(PL011Registers, read_count), 63 vmstate_of!(PL011Registers, read_trigger), 64 }, 65 ..Zeroable::ZERO 66 }; 67 68 pub static VMSTATE_PL011: VMStateDescription = VMStateDescription { 69 name: c_str!("pl011").as_ptr(), 70 version_id: 2, 71 minimum_version_id: 2, 72 post_load: Some(pl011_post_load), 73 fields: vmstate_fields! { 74 vmstate_unused!(core::mem::size_of::<u32>()), 75 vmstate_struct!(PL011State, regs, &VMSTATE_PL011_REGS, BqlRefCell<PL011Registers>), 76 }, 77 subsections: vmstate_subsections! { 78 VMSTATE_PL011_CLOCK 79 }, 80 ..Zeroable::ZERO 81 }; 82 83 qemu_api::declare_properties! { 84 PL011_PROPERTIES, 85 qemu_api::define_property!( 86 c_str!("chardev"), 87 PL011State, 88 char_backend, 89 unsafe { &qdev_prop_chr }, 90 CharBackend 91 ), 92 qemu_api::define_property!( 93 c_str!("migrate-clk"), 94 PL011State, 95 migrate_clock, 96 unsafe { &qdev_prop_bool }, 97 bool, 98 default = true 99 ), 100 } 101