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