mirror of https://github.com/xemu-project/xemu.git
rust/pl011: add support for migration
Declare the vmstate description of the PL011 device. Based on a patch by Manos Pitsidianakis (https://lore.kernel.org/qemu-devel/20241024-rust-round-2-v1-4-051e7a25b978@linaro.org/). Signed-off-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Link: https://lore.kernel.org/r/20241024-rust-round-2-v1-4-051e7a25b978@linaro.org
This commit is contained in:
parent
113c668852
commit
93243319db
|
@ -20,6 +20,12 @@ use crate::{
|
||||||
|
|
||||||
static PL011_ID_ARM: [c_uchar; 8] = [0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
|
static PL011_ID_ARM: [c_uchar; 8] = [0x11, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1];
|
||||||
|
|
||||||
|
/// Integer Baud Rate Divider, `UARTIBRD`
|
||||||
|
const IBRD_MASK: u32 = 0x3f;
|
||||||
|
|
||||||
|
/// Fractional Baud Rate Divider, `UARTFBRD`
|
||||||
|
const FBRD_MASK: u32 = 0xffff;
|
||||||
|
|
||||||
const DATA_BREAK: u32 = 1 << 10;
|
const DATA_BREAK: u32 = 1 << 10;
|
||||||
|
|
||||||
/// QEMU sourced constant.
|
/// QEMU sourced constant.
|
||||||
|
@ -492,6 +498,27 @@ impl PL011State {
|
||||||
unsafe { qemu_set_irq(*irq, i32::from(flags & i != 0)) };
|
unsafe { qemu_set_irq(*irq, i32::from(flags & i != 0)) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn post_load(&mut self, _version_id: u32) -> Result<(), ()> {
|
||||||
|
/* Sanity-check input state */
|
||||||
|
if self.read_pos >= self.read_fifo.len() || self.read_count > self.read_fifo.len() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.fifo_enabled() && self.read_count > 0 && self.read_pos > 0 {
|
||||||
|
// Older versions of PL011 didn't ensure that the single
|
||||||
|
// character in the FIFO in FIFO-disabled mode is in
|
||||||
|
// element 0 of the array; convert to follow the current
|
||||||
|
// code's assumptions.
|
||||||
|
self.read_fifo[0] = self.read_fifo[self.read_pos];
|
||||||
|
self.read_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ibrd &= IBRD_MASK;
|
||||||
|
self.fbrd &= FBRD_MASK;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Which bits in the interrupt status matter for each outbound IRQ line ?
|
/// Which bits in the interrupt status matter for each outbound IRQ line ?
|
||||||
|
|
|
@ -2,16 +2,77 @@
|
||||||
// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
use core::ptr::NonNull;
|
use core::{
|
||||||
|
ffi::{c_int, c_void},
|
||||||
|
ptr::NonNull,
|
||||||
|
};
|
||||||
|
|
||||||
use qemu_api::{bindings::*, definitions::ObjectImpl, zeroable::Zeroable};
|
use qemu_api::{
|
||||||
|
bindings::*, vmstate_clock, vmstate_fields, vmstate_int32, vmstate_subsections, vmstate_uint32,
|
||||||
|
vmstate_uint32_array, vmstate_unused, zeroable::Zeroable,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::device::PL011State;
|
use crate::device::{PL011State, PL011_FIFO_DEPTH};
|
||||||
|
|
||||||
|
extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool {
|
||||||
|
unsafe {
|
||||||
|
debug_assert!(!opaque.is_null());
|
||||||
|
let state = NonNull::new_unchecked(opaque.cast::<PL011State>());
|
||||||
|
state.as_ref().migrate_clock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Migration subsection for [`PL011State`] clock.
|
||||||
|
pub static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription {
|
||||||
|
name: c"pl011/clock".as_ptr(),
|
||||||
|
version_id: 1,
|
||||||
|
minimum_version_id: 1,
|
||||||
|
needed: Some(pl011_clock_needed),
|
||||||
|
fields: vmstate_fields! {
|
||||||
|
vmstate_clock!(clock, PL011State),
|
||||||
|
},
|
||||||
|
..Zeroable::ZERO
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {
|
||||||
|
unsafe {
|
||||||
|
debug_assert!(!opaque.is_null());
|
||||||
|
let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>());
|
||||||
|
let result = state.as_mut().post_load(version_id as u32);
|
||||||
|
if result.is_err() {
|
||||||
|
-1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[used]
|
|
||||||
pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
|
pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
|
||||||
name: PL011State::TYPE_INFO.name,
|
name: c"pl011".as_ptr(),
|
||||||
unmigratable: true,
|
version_id: 2,
|
||||||
|
minimum_version_id: 2,
|
||||||
|
post_load: Some(pl011_post_load),
|
||||||
|
fields: vmstate_fields! {
|
||||||
|
vmstate_unused!(core::mem::size_of::<u32>()),
|
||||||
|
vmstate_uint32!(flags, PL011State),
|
||||||
|
vmstate_uint32!(line_control, PL011State),
|
||||||
|
vmstate_uint32!(receive_status_error_clear, PL011State),
|
||||||
|
vmstate_uint32!(control, PL011State),
|
||||||
|
vmstate_uint32!(dmacr, PL011State),
|
||||||
|
vmstate_uint32!(int_enabled, PL011State),
|
||||||
|
vmstate_uint32!(int_level, PL011State),
|
||||||
|
vmstate_uint32_array!(read_fifo, PL011State, PL011_FIFO_DEPTH),
|
||||||
|
vmstate_uint32!(ilpr, PL011State),
|
||||||
|
vmstate_uint32!(ibrd, PL011State),
|
||||||
|
vmstate_uint32!(fbrd, PL011State),
|
||||||
|
vmstate_uint32!(ifl, PL011State),
|
||||||
|
vmstate_int32!(read_pos, PL011State),
|
||||||
|
vmstate_int32!(read_count, PL011State),
|
||||||
|
vmstate_int32!(read_trigger, PL011State),
|
||||||
|
},
|
||||||
|
subsections: vmstate_subsections! {
|
||||||
|
VMSTATE_PL011_CLOCK
|
||||||
|
},
|
||||||
..Zeroable::ZERO
|
..Zeroable::ZERO
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
clippy::cognitive_complexity,
|
clippy::cognitive_complexity,
|
||||||
clippy::missing_safety_doc,
|
clippy::missing_safety_doc,
|
||||||
)]
|
)]
|
||||||
|
#![allow(clippy::result_unit_err)]
|
||||||
|
|
||||||
extern crate bilge;
|
extern crate bilge;
|
||||||
extern crate bilge_impl;
|
extern crate bilge_impl;
|
||||||
|
|
Loading…
Reference in New Issue