On 19/04/2019 17:40, Stephen Checkoway wrote: > The SCC/ESCC will briefly stop asserting an interrupt when the > transmit FIFO is filled. > > This code doesn't model the transmit FIFO/shift register so the > pending transmit interrupt is never deasserted which means that an > edge-triggered interrupt controller will never see the low-to-high > transition it needs to raise another interrupt. The practical > consequence of this is that guest firmware with an interrupt service > routine for the ESCC that does not send all of the data it has > immediately will stop sending data if the following sequence of > events occurs: > 1. Disable processor interrupts > 2. Write a character to the ESCC > 3. Add additional characters to a buffer which is drained by the ISR > 4. Enable processor interrupts > > In this case, the first character will be sent, the interrupt will > fire and the ISR will output the second character. Since the pending > transmit interrupt remains asserted, no additional interrupts will > ever fire. > > This behavior was triggered by firmware for an embedded system with a > Z85C30 which necessitated this patch. > > This patch fixes that situation by explicitly lowering the IRQ when a > character is written to the buffer and no other interrupts are currently > pending. > > Signed-off-by: Stephen Checkoway <stephen.checko...@oberlin.edu> > Reviewed-by: Philippe Mathieu-Daudé <phi...@redhat.com> > --- > > I added a sentence about the Z85C30 necessitating this to the commit message. > > hw/char/escc.c | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/hw/char/escc.c b/hw/char/escc.c > index 628f5f81f7..c5b05a63f1 100644 > --- a/hw/char/escc.c > +++ b/hw/char/escc.c > @@ -509,6 +509,13 @@ static void escc_mem_write(void *opaque, hwaddr addr, > break; > case SERIAL_DATA: > trace_escc_mem_writeb_data(CHN_C(s), val); > + /* > + * Lower the irq when data is written to the Tx buffer and no other > + * interrupts are currently pending. The irq will be raised again > once > + * the Tx buffer becomes empty below. > + */ > + s->txint = 0; > + escc_update_irq(s); > s->tx = val; > if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled > if (qemu_chr_fe_backend_connected(&s->chr)) { >
Applied to my trivial-patches branch. Paolo, Marc-André, if you disagree with this change or prefer to take it through one of your queues, I can remove it from mine. Let me know. Thanks, Laurent