xref: /qemu/rust/hw/char/pl011/src/device_class.rs (revision c5f122fdcc280a82e7c5f31de890f985aa7ba773)
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 
pl011_clock_needed(opaque: *mut c_void) -> bool20 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 
pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int37 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