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, vmstate_clock, vmstate_fields, vmstate_int32, vmstate_subsections,
10 vmstate_uint32, vmstate_uint32_array, vmstate_unused, zeroable::Zeroable,
11 };
12
13 use crate::device::{PL011State, PL011_FIFO_DEPTH};
14
pl011_clock_needed(opaque: *mut c_void) -> bool15 extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool {
16 unsafe {
17 debug_assert!(!opaque.is_null());
18 let state = NonNull::new_unchecked(opaque.cast::<PL011State>());
19 state.as_ref().migrate_clock
20 }
21 }
22
23 /// Migration subsection for [`PL011State`] clock.
24 pub static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription {
25 name: c_str!("pl011/clock").as_ptr(),
26 version_id: 1,
27 minimum_version_id: 1,
28 needed: Some(pl011_clock_needed),
29 fields: vmstate_fields! {
30 vmstate_clock!(clock, PL011State),
31 },
32 ..Zeroable::ZERO
33 };
34
pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int35 extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {
36 unsafe {
37 debug_assert!(!opaque.is_null());
38 let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>());
39 let result = state.as_mut().post_load(version_id as u32);
40 if result.is_err() {
41 -1
42 } else {
43 0
44 }
45 }
46 }
47
48 pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
49 name: c_str!("pl011").as_ptr(),
50 version_id: 2,
51 minimum_version_id: 2,
52 post_load: Some(pl011_post_load),
53 fields: vmstate_fields! {
54 vmstate_unused!(core::mem::size_of::<u32>()),
55 vmstate_uint32!(flags, PL011State),
56 vmstate_uint32!(line_control, PL011State),
57 vmstate_uint32!(receive_status_error_clear, PL011State),
58 vmstate_uint32!(control, PL011State),
59 vmstate_uint32!(dmacr, PL011State),
60 vmstate_uint32!(int_enabled, PL011State),
61 vmstate_uint32!(int_level, PL011State),
62 vmstate_uint32_array!(read_fifo, PL011State, PL011_FIFO_DEPTH),
63 vmstate_uint32!(ilpr, PL011State),
64 vmstate_uint32!(ibrd, PL011State),
65 vmstate_uint32!(fbrd, PL011State),
66 vmstate_uint32!(ifl, PL011State),
67 vmstate_int32!(read_pos, PL011State),
68 vmstate_int32!(read_count, PL011State),
69 vmstate_int32!(read_trigger, PL011State),
70 },
71 subsections: vmstate_subsections! {
72 VMSTATE_PL011_CLOCK
73 },
74 ..Zeroable::ZERO
75 };
76
77 qemu_api::declare_properties! {
78 PL011_PROPERTIES,
79 qemu_api::define_property!(
80 c_str!("chardev"),
81 PL011State,
82 char_backend,
83 unsafe { &qdev_prop_chr },
84 CharBackend
85 ),
86 qemu_api::define_property!(
87 c_str!("migrate-clk"),
88 PL011State,
89 migrate_clock,
90 unsafe { &qdev_prop_bool },
91 bool,
92 default = true
93 ),
94 }
95
96 qemu_api::device_class_init! {
97 pl011_class_init,
98 props => PL011_PROPERTIES,
99 realize_fn => Some(pl011_realize),
100 legacy_reset_fn => Some(pl011_reset),
101 vmsd => VMSTATE_PL011,
102 }
103
104 /// # Safety
105 ///
106 /// We expect the FFI user of this function to pass a valid pointer, that has
107 /// the same size as [`PL011State`]. We also expect the device is
108 /// readable/writeable from one thread at any time.
pl011_realize(dev: *mut DeviceState, _errp: *mut *mut Error)109 pub unsafe extern "C" fn pl011_realize(dev: *mut DeviceState, _errp: *mut *mut Error) {
110 unsafe {
111 assert!(!dev.is_null());
112 let mut state = NonNull::new_unchecked(dev.cast::<PL011State>());
113 state.as_mut().realize();
114 }
115 }
116
117 /// # Safety
118 ///
119 /// We expect the FFI user of this function to pass a valid pointer, that has
120 /// the same size as [`PL011State`]. We also expect the device is
121 /// readable/writeable from one thread at any time.
pl011_reset(dev: *mut DeviceState)122 pub unsafe extern "C" fn pl011_reset(dev: *mut DeviceState) {
123 unsafe {
124 assert!(!dev.is_null());
125 let mut state = NonNull::new_unchecked(dev.cast::<PL011State>());
126 state.as_mut().reset();
127 }
128 }
129