aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Lugou <florian.lugou@provenrun.com>2025-06-05 12:12:54 +0200
committerAlistair Francis <alistair.francis@wdc.com>2025-07-04 21:09:48 +1000
commit61240e3a06dc622d249b530557d5ce03c5854592 (patch)
tree2e750296e880c4e8619e714c87d417c02acb6dcb
parent2b027e73eefab0f9d3a0048564d1b653ba1d7703 (diff)
downloadqemu-61240e3a06dc622d249b530557d5ce03c5854592.zip
qemu-61240e3a06dc622d249b530557d5ce03c5854592.tar.gz
qemu-61240e3a06dc622d249b530557d5ce03c5854592.tar.bz2
hw/char: sifive_uart: Avoid infinite delay of async xmit function
The current handler for TXFIFO writes schedules an async callback to pop characters from the queue. When software writes to TXFIFO faster than the async callback delay (100ns), the timer may be pushed back while the previous character has not be dequeued yet. This happens in particular when using -icount with small shift values. This is especially worrysome when software repetitively issues amoor.w instructions (as suggested by SiFive specification) and the FIFO is full, leading to the callback being infinitly pushed back. This commit fixes the issue by never pushing back the timer, only updating it if it is not already active. Signed-off-by: Florian Lugou <florian.lugou@provenrun.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20250605101255.797162-1-florian.lugou@provenrun.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
-rw-r--r--hw/char/sifive_uart.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/hw/char/sifive_uart.c b/hw/char/sifive_uart.c
index 0fc89e7..9bc697a 100644
--- a/hw/char/sifive_uart.c
+++ b/hw/char/sifive_uart.c
@@ -128,8 +128,10 @@ static void sifive_uart_write_tx_fifo(SiFiveUARTState *s, const uint8_t *buf,
s->txfifo |= SIFIVE_UART_TXFIFO_FULL;
}
- timer_mod(s->fifo_trigger_handle, current_time +
- TX_INTERRUPT_TRIGGER_DELAY_NS);
+ if (!timer_pending(s->fifo_trigger_handle)) {
+ timer_mod(s->fifo_trigger_handle, current_time +
+ TX_INTERRUPT_TRIGGER_DELAY_NS);
+ }
}
static uint64_t