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