qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@web.de>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH] 8250: more realistic TX-done IRQ rate
Date: Sat, 12 Apr 2008 16:56:46 +0200	[thread overview]
Message-ID: <4800CDAE.3090606@web.de> (raw)

[-- Attachment #1: Type: text/plain, Size: 3648 bytes --]

The 8250 UART emulation currently raises a TX-done IRQ immediately when the guest writes out some character. This is problematic for guests like Linux which may flush its output buffer in a loop from IRQ context, because they may then enter a tight loop with IRQs disabled. In fact, Linux breaks out of this loop after some iterations and issue the well-known [1] "too much work for irq..." warning. And in case the console output is on the very same serial port, the console output is utterly corrupted.

Patch below addresses the issue by delaying the TX-done IRQ more realistically, ie. according to the currently set baudrate.

Jan

[1] http://lkml.org/lkml/2008/1/12/135

Signed-off-by: Jan Kiszka <jan.kiszka@web.de>

---
 hw/serial.c |   39 ++++++++++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 11 deletions(-)

Index: b/hw/serial.c
===================================================================
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -25,6 +25,7 @@
 #include "qemu-char.h"
 #include "isa.h"
 #include "pc.h"
+#include "qemu-timer.h"
 
 //#define DEBUG_SERIAL
 
@@ -91,6 +92,8 @@ struct SerialState {
     int last_break_enable;
     target_phys_addr_t base;
     int it_shift;
+    QEMUTimer *tx_timer;
+    char tx_buf;
 };
 
 static void serial_receive_byte(SerialState *s, int ch);
@@ -111,6 +114,20 @@ static void serial_update_irq(SerialStat
     }
 }
 
+static void serial_tx_done(void *opaque)
+{
+    SerialState *s = opaque;
+
+    s->thr_ipending = 1;
+    s->lsr |= UART_LSR_THRE;
+    s->lsr |= UART_LSR_TEMT;
+    serial_update_irq(s);
+    if (s->mcr & UART_MCR_LOOP) {
+        /* in loopback mode, say that we just received a char */
+        serial_receive_byte(s, s->tx_buf);
+    }
+}
+
 static void serial_update_parameters(SerialState *s)
 {
     int speed, parity, data_bits, stop_bits;
@@ -146,7 +163,6 @@ static void serial_update_parameters(Ser
 static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 {
     SerialState *s = opaque;
-    unsigned char ch;
 
     addr &= 7;
 #ifdef DEBUG_SERIAL
@@ -162,19 +178,12 @@ static void serial_ioport_write(void *op
             s->thr_ipending = 0;
             s->lsr &= ~UART_LSR_THRE;
             serial_update_irq(s);
-            ch = val;
+            s->tx_buf = val;
             if (!(s->mcr & UART_MCR_LOOP)) {
                 /* when not in loopback mode, send the char */
-                qemu_chr_write(s->chr, &ch, 1);
-            }
-            s->thr_ipending = 1;
-            s->lsr |= UART_LSR_THRE;
-            s->lsr |= UART_LSR_TEMT;
-            serial_update_irq(s);
-            if (s->mcr & UART_MCR_LOOP) {
-                /* in loopback mode, say that we just received a char */
-                serial_receive_byte(s, ch);
+                qemu_chr_write(s->chr, &s->tx_buf, 1);
             }
+            qemu_mod_timer(s->tx_timer, 1000 / (11520 / s->divider));
         }
         break;
     case 1:
@@ -387,6 +396,10 @@ SerialState *serial_init(int base, qemu_
         return NULL;
     s->irq = irq;
 
+    s->tx_timer = qemu_new_timer(vm_clock, serial_tx_done, s);
+    if (!s->tx_timer)
+        return NULL;
+
     qemu_register_reset(serial_reset, s);
     serial_reset(s);
 
@@ -486,6 +499,10 @@ SerialState *serial_mm_init (target_phys
     s->base = base;
     s->it_shift = it_shift;
 
+    s->tx_timer = qemu_new_timer(vm_clock, serial_tx_done, s);
+    if (!s->tx_timer)
+        return NULL;
+
     qemu_register_reset(serial_reset, s);
     serial_reset(s);
 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 254 bytes --]

             reply	other threads:[~2008-04-12 14:56 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-12 14:56 Jan Kiszka [this message]
2008-04-12 16:47 ` [Qemu-devel] Re: [PATCH] 8250: more realistic TX-done IRQ rate Jan Kiszka
2008-04-12 16:48 ` [Qemu-devel] " Paul Brook
2008-04-12 17:11   ` Jan Kiszka
2008-04-13  8:05     ` Jan Kiszka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4800CDAE.3090606@web.de \
    --to=jan.kiszka@web.de \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).