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];
|
||||
|
||||
/// 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;
|
||||
|
||||
/// QEMU sourced constant.
|
||||
|
@ -492,6 +498,27 @@ impl PL011State {
|
|||
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 ?
|
||||
|
|
|
@ -2,16 +2,77 @@
|
|||
// Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
||||
// 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 {
|
||||
name: PL011State::TYPE_INFO.name,
|
||||
unmigratable: true,
|
||||
name: c"pl011".as_ptr(),
|
||||
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
|
||||
};
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
clippy::cognitive_complexity,
|
||||
clippy::missing_safety_doc,
|
||||
)]
|
||||
#![allow(clippy::result_unit_err)]
|
||||
|
||||
extern crate bilge;
|
||||
extern crate bilge_impl;
|
||||
|
|
Loading…
Reference in New Issue