xref: /qemu/rust/hw/char/pl011/src/device_class.rs (revision 9d4899496b555751c8ea4155d6da4fc3dbd7edae)
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_of, vmstate_subsections,
10     vmstate_unused, zeroable::Zeroable,
11 };
12 
13 use crate::device::PL011State;
14 
15 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 
35 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_of!(PL011State, flags),
56         vmstate_of!(PL011State, line_control),
57         vmstate_of!(PL011State, receive_status_error_clear),
58         vmstate_of!(PL011State, control),
59         vmstate_of!(PL011State, dmacr),
60         vmstate_of!(PL011State, int_enabled),
61         vmstate_of!(PL011State, int_level),
62         vmstate_of!(PL011State, read_fifo),
63         vmstate_of!(PL011State, ilpr),
64         vmstate_of!(PL011State, ibrd),
65         vmstate_of!(PL011State, fbrd),
66         vmstate_of!(PL011State, ifl),
67         vmstate_of!(PL011State, read_pos),
68         vmstate_of!(PL011State, read_count),
69         vmstate_of!(PL011State, read_trigger),
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