[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [IOEMU] Fix Linux smp guest hangs with complaint "BUG: soft lock detected on CPU#0"
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Node ID f516774cbb27d63aeaeb65085a73bb016e10c037 # Parent b1d436f094faa1a681f94497ddf6a84b15e7d493 [IOEMU] Fix Linux smp guest hangs with complaint "BUG: soft lock detected on CPU#0" When console=ttyS0 in guest grub configuration and serial='pty' in vmx configure file. The root cause to this bug is the characteristic of PTY emulator in Qemu. PTY has write/read end with some buffer. Write to a buffer will be failed after the buffer is full until read end reads the data from buffer. Previous to changeset 12026, write to serial port would fail quietly when buffer for pty is full. With changeset 12026, write to serial port would retry 3 times in 300ms if failed, even without notifying guest using serial irq. Smp guest will hang, waiting for an interrupt. For SMP guest, a watchdog thread should be executed periodically, otherwise soft lockup is detected. With this patch, an upper threshold of total consecutive retries is added and serial interrupt would be sent after retry 3 times for each write request, even if failed. Signed-off-by: Xinmei Huang <xinmei.huang@xxxxxxxxx> Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- tools/ioemu/hw/serial.c | 26 ++++++++++++++++++++------ 1 files changed, 20 insertions(+), 6 deletions(-) diff -r b1d436f094fa -r f516774cbb27 tools/ioemu/hw/serial.c --- a/tools/ioemu/hw/serial.c Sat Nov 11 01:40:16 2006 +0000 +++ b/tools/ioemu/hw/serial.c Mon Nov 13 09:46:05 2006 +0000 @@ -73,6 +73,11 @@ #define UART_LSR_OE 0x02 /* Overrun error indicator */ #define UART_LSR_DR 0x01 /* Receiver data ready */ +/* Maximum retries for a single byte transmit. */ +#define WRITE_MAX_SINGLE_RETRIES 3 +/* Maximum retries for a sequence of back-to-back unsuccessful transmits. */ +#define WRITE_MAX_TOTAL_RETRIES 10 + struct SerialState { uint8_t divider; uint8_t rbr; /* receive register */ @@ -98,8 +103,12 @@ struct SerialState { * If a character transmitted via UART cannot be written to its * destination immediately we remember it here and retry a few times via * a polling timer. + * - write_single_retries: Number of write retries for current byte. + * - write_total_retries: Number of write retries for back-to-back + * unsuccessful transmits. */ - int write_retries; + int write_single_retries; + int write_total_retries; char write_chr; QEMUTimer *write_retry_timer; }; @@ -217,16 +226,21 @@ static void serial_chr_write(void *opaqu { SerialState *s = opaque; + /* Cancel any outstanding retry if this is a new byte. */ qemu_del_timer(s->write_retry_timer); /* Retry every 100ms for 300ms total. */ if (qemu_chr_write(s->chr, &s->write_chr, 1) == -1) { - if (s->write_retries++ >= 3) - printf("serial: write error\n"); - else + s->write_total_retries++; + if (s->write_single_retries++ >= WRITE_MAX_SINGLE_RETRIES) + fprintf(stderr, "serial: write error\n"); + else if (s->write_total_retries <= WRITE_MAX_TOTAL_RETRIES) { qemu_mod_timer(s->write_retry_timer, qemu_get_clock(vm_clock) + ticks_per_sec / 10); - return; + return; + } + } else { + s->write_total_retries = 0; /* if successful then reset counter */ } /* Success: Notify guest that THR is empty. */ @@ -255,7 +269,7 @@ static void serial_ioport_write(void *op s->lsr &= ~UART_LSR_THRE; serial_update_irq(s); s->write_chr = val; - s->write_retries = 0; + s->write_single_retries = 0; serial_chr_write(s); } break; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |