rust: pl011: add tracepoints
Finally bring parity between C and Rust versions of the PL011 device model. Changing some types of the arguments makes for nicer Rust code; C does not care. :) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Message-ID: <20250929154938.594389-12-pbonzini@redhat.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
fe791b4004
commit
357f926979
5 changed files with 50 additions and 24 deletions
1
rust/Cargo.lock
generated
1
rust/Cargo.lock
generated
|
|
@ -159,6 +159,7 @@ dependencies = [
|
|||
"migration",
|
||||
"qom",
|
||||
"system",
|
||||
"trace",
|
||||
"util",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ qom = { path = "../../../qom" }
|
|||
chardev = { path = "../../../chardev" }
|
||||
system = { path = "../../../system" }
|
||||
hwcore = { path = "../../../hw/core" }
|
||||
trace = { path = "../../../trace" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ _libpl011_rs = static_library(
|
|||
chardev_rs,
|
||||
system_rs,
|
||||
hwcore_rs,
|
||||
trace_rs
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ use util::{log::Log, log_mask_ln};
|
|||
|
||||
use crate::registers::{self, Interrupt, RegisterOffset};
|
||||
|
||||
::trace::include_trace!("hw_char");
|
||||
|
||||
// TODO: You must disable the UART before any of the control registers are
|
||||
// reprogrammed. When the UART is disabled in the middle of transmission or
|
||||
// reception, it completes the current character before stopping
|
||||
|
|
@ -208,13 +210,7 @@ impl PL011Registers {
|
|||
(update, result)
|
||||
}
|
||||
|
||||
pub(self) fn write(
|
||||
&mut self,
|
||||
offset: RegisterOffset,
|
||||
value: u32,
|
||||
char_backend: &CharBackend,
|
||||
) -> bool {
|
||||
// eprintln!("write offset {offset} value {value}");
|
||||
pub(self) fn write(&mut self, offset: RegisterOffset, value: u32, device: &PL011State) -> bool {
|
||||
use RegisterOffset::*;
|
||||
match offset {
|
||||
DR => return self.write_data_register(value),
|
||||
|
|
@ -229,9 +225,11 @@ impl PL011Registers {
|
|||
}
|
||||
IBRD => {
|
||||
self.ibrd = value;
|
||||
device.trace_baudrate_change(self.ibrd, self.fbrd);
|
||||
}
|
||||
FBRD => {
|
||||
self.fbrd = value;
|
||||
device.trace_baudrate_change(self.ibrd, self.fbrd);
|
||||
}
|
||||
LCR_H => {
|
||||
let new_val: registers::LineControl = value.into();
|
||||
|
|
@ -242,7 +240,7 @@ impl PL011Registers {
|
|||
}
|
||||
let update = (self.line_control.send_break() != new_val.send_break()) && {
|
||||
let break_enable = new_val.send_break();
|
||||
let _ = char_backend.send_break(break_enable);
|
||||
let _ = device.char_backend.send_break(break_enable);
|
||||
self.loopback_break(break_enable)
|
||||
};
|
||||
self.line_control = new_val;
|
||||
|
|
@ -279,12 +277,13 @@ impl PL011Registers {
|
|||
}
|
||||
|
||||
fn read_data_register(&mut self, update: &mut bool) -> u32 {
|
||||
let depth = self.fifo_depth();
|
||||
self.flags.set_receive_fifo_full(false);
|
||||
let c = self.read_fifo[self.read_pos];
|
||||
|
||||
if self.read_count > 0 {
|
||||
self.read_count -= 1;
|
||||
self.read_pos = (self.read_pos + 1) & (self.fifo_depth() - 1);
|
||||
self.read_pos = (self.read_pos + 1) & (depth - 1);
|
||||
}
|
||||
if self.read_count == 0 {
|
||||
self.flags.set_receive_fifo_empty(true);
|
||||
|
|
@ -292,6 +291,7 @@ impl PL011Registers {
|
|||
if self.read_count + 1 == self.read_trigger {
|
||||
self.int_level &= !Interrupt::RX;
|
||||
}
|
||||
trace::trace_pl011_read_fifo(self.read_count, depth);
|
||||
self.receive_status_error_clear.set_from_data(c);
|
||||
*update = true;
|
||||
u32::from(c)
|
||||
|
|
@ -447,7 +447,9 @@ impl PL011Registers {
|
|||
self.read_fifo[slot] = value;
|
||||
self.read_count += 1;
|
||||
self.flags.set_receive_fifo_empty(false);
|
||||
trace::trace_pl011_fifo_rx_put(value.into(), self.read_count, depth);
|
||||
if self.read_count == depth {
|
||||
trace::trace_pl011_fifo_rx_full();
|
||||
self.flags.set_receive_fifo_full(true);
|
||||
}
|
||||
|
||||
|
|
@ -516,8 +518,21 @@ impl PL011State {
|
|||
uninit_field_mut!(*this, clock).write(clock);
|
||||
}
|
||||
|
||||
const fn clock_update(&self, _event: ClockEvent) {
|
||||
/* pl011_trace_baudrate_change(s); */
|
||||
pub fn trace_baudrate_change(&self, ibrd: u32, fbrd: u32) {
|
||||
let divider = 4.0 / f64::from(ibrd * (FBRD_MASK + 1) + fbrd);
|
||||
let hz = self.clock.hz();
|
||||
let rate = if ibrd == 0 {
|
||||
0
|
||||
} else {
|
||||
((hz as f64) * divider) as u32
|
||||
};
|
||||
trace::trace_pl011_baudrate_change(rate, hz, ibrd, fbrd);
|
||||
}
|
||||
|
||||
fn clock_update(&self, _event: ClockEvent) {
|
||||
let regs = self.regs.borrow();
|
||||
let (ibrd, fbrd) = (regs.ibrd, regs.fbrd);
|
||||
self.trace_baudrate_change(ibrd, fbrd)
|
||||
}
|
||||
|
||||
pub fn clock_needed(&self) -> bool {
|
||||
|
|
@ -543,6 +558,7 @@ impl PL011State {
|
|||
}
|
||||
Ok(field) => {
|
||||
let (update_irq, result) = self.regs.borrow_mut().read(field);
|
||||
trace::trace_pl011_read(offset, result, c"");
|
||||
if update_irq {
|
||||
self.update();
|
||||
self.char_backend.accept_input();
|
||||
|
|
@ -557,6 +573,7 @@ impl PL011State {
|
|||
if let Ok(field) = RegisterOffset::try_from(offset) {
|
||||
// qemu_chr_fe_write_all() calls into the can_receive
|
||||
// callback, so handle writes before entering PL011Registers.
|
||||
trace::trace_pl011_write(offset, value as u32, c"");
|
||||
if field == RegisterOffset::DR {
|
||||
// ??? Check if transmitter is enabled.
|
||||
let ch: [u8; 1] = [value as u8];
|
||||
|
|
@ -565,10 +582,7 @@ impl PL011State {
|
|||
let _ = self.char_backend.write_all(&ch);
|
||||
}
|
||||
|
||||
update_irq = self
|
||||
.regs
|
||||
.borrow_mut()
|
||||
.write(field, value as u32, &self.char_backend);
|
||||
update_irq = self.regs.borrow_mut().write(field, value as u32, self);
|
||||
} else {
|
||||
log_mask_ln!(
|
||||
Log::GuestError,
|
||||
|
|
@ -582,11 +596,19 @@ impl PL011State {
|
|||
|
||||
fn can_receive(&self) -> u32 {
|
||||
let regs = self.regs.borrow();
|
||||
// trace_pl011_can_receive(s->lcr, s->read_count, r);
|
||||
regs.fifo_depth() - regs.read_count
|
||||
let fifo_available = regs.fifo_depth() - regs.read_count;
|
||||
trace::trace_pl011_can_receive(
|
||||
regs.line_control.into(),
|
||||
regs.read_count,
|
||||
regs.fifo_depth(),
|
||||
fifo_available,
|
||||
);
|
||||
fifo_available
|
||||
}
|
||||
|
||||
fn receive(&self, buf: &[u8]) {
|
||||
trace::trace_pl011_receive(buf.len());
|
||||
|
||||
let mut regs = self.regs.borrow_mut();
|
||||
if regs.loopback_enabled() {
|
||||
// In loopback mode, the RX input signal is internally disconnected
|
||||
|
|
@ -635,6 +657,7 @@ impl PL011State {
|
|||
fn update(&self) {
|
||||
let regs = self.regs.borrow();
|
||||
let flags = regs.int_level & regs.int_enabled;
|
||||
trace::trace_pl011_irq_state(flags != 0);
|
||||
for (irq, i) in self.interrupts.iter().zip(IRQMASK) {
|
||||
irq.set(flags.any_set(i));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue