From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Jkh9z-000198-DW for qemu-devel@nongnu.org; Sat, 12 Apr 2008 10:56:55 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Jkh9x-00018Z-CV for qemu-devel@nongnu.org; Sat, 12 Apr 2008 10:56:54 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Jkh9x-00018U-94 for qemu-devel@nongnu.org; Sat, 12 Apr 2008 10:56:53 -0400 Received: from fmmailgate03.web.de ([217.72.192.234]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Jkh9w-0007CS-OK for qemu-devel@nongnu.org; Sat, 12 Apr 2008 10:56:53 -0400 Received: from smtp07.web.de (fmsmtp07.dlan.cinetic.de [172.20.5.215]) by fmmailgate03.web.de (Postfix) with ESMTP id 1FBC3D6D7399 for ; Sat, 12 Apr 2008 16:56:51 +0200 (CEST) Received: from [88.65.46.55] (helo=[192.168.1.198]) by smtp07.web.de with asmtp (TLSv1:AES256-SHA:256) (WEB.DE 4.109 #226) id 1Jkh9u-0008E1-00 for qemu-devel@nongnu.org; Sat, 12 Apr 2008 16:56:51 +0200 Message-ID: <4800CDAE.3090606@web.de> Date: Sat, 12 Apr 2008 16:56:46 +0200 From: Jan Kiszka MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="------------enig527F841DC5110FC671A68CFF" Sender: jan.kiszka@web.de Subject: [Qemu-devel] [PATCH] 8250: more realistic TX-done IRQ rate Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enig527F841DC5110FC671A68CFF Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: quoted-printable The 8250 UART emulation currently raises a TX-done IRQ immediately when t= he guest writes out some character. This is problematic for guests like L= inux which may flush its output buffer in a loop from IRQ context, becaus= e they may then enter a tight loop with IRQs disabled. In fact, Linux bre= aks 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 t= he very same serial port, the console output is utterly corrupted. Patch below addresses the issue by delaying the TX-done IRQ more realisti= cally, ie. according to the currently set baudrate. Jan [1] http://lkml.org/lkml/2008/1/12/135 Signed-off-by: Jan Kiszka --- hw/serial.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) Index: b/hw/serial.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 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" =20 //#define DEBUG_SERIAL =20 @@ -91,6 +92,8 @@ struct SerialState { int last_break_enable; target_phys_addr_t base; int it_shift; + QEMUTimer *tx_timer; + char tx_buf; }; =20 static void serial_receive_byte(SerialState *s, int ch); @@ -111,6 +114,20 @@ static void serial_update_irq(SerialStat } } =20 +static void serial_tx_done(void *opaque) +{ + SerialState *s =3D opaque; + + s->thr_ipending =3D 1; + s->lsr |=3D UART_LSR_THRE; + s->lsr |=3D 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 va= l) { SerialState *s =3D opaque; - unsigned char ch; =20 addr &=3D 7; #ifdef DEBUG_SERIAL @@ -162,19 +178,12 @@ static void serial_ioport_write(void *op s->thr_ipending =3D 0; s->lsr &=3D ~UART_LSR_THRE; serial_update_irq(s); - ch =3D val; + s->tx_buf =3D 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 =3D 1; - s->lsr |=3D UART_LSR_THRE; - s->lsr |=3D 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 =3D irq; =20 + s->tx_timer =3D qemu_new_timer(vm_clock, serial_tx_done, s); + if (!s->tx_timer) + return NULL; + qemu_register_reset(serial_reset, s); serial_reset(s); =20 @@ -486,6 +499,10 @@ SerialState *serial_mm_init (target_phys s->base =3D base; s->it_shift =3D it_shift; =20 + s->tx_timer =3D qemu_new_timer(vm_clock, serial_tx_done, s); + if (!s->tx_timer) + return NULL; + qemu_register_reset(serial_reset, s); serial_reset(s); =20 --------------enig527F841DC5110FC671A68CFF Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.4-svn0 (GNU/Linux) Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org iD8DBQFIAM2yniDOoMHTA+kRAsG0AJ45uDhDEcFY23qt4hwJ0etOdP48XQCdHCz2 a4UQtoGklEPdCgGgFoEakoU= =AzaS -----END PGP SIGNATURE----- --------------enig527F841DC5110FC671A68CFF--