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