QEMU is a FAST! processor emulator
CentOS Sources
2017-06-13 b28c6438a68632f04532ce24d7d14f4e4bb12be3
import qemu-kvm-1.5.3-126.el7_3.9
20 files added
1 files modified
1928 ■■■■■ changed files
SOURCES/kvm-char-change-qemu_chr_fe_add_watch-to-return-unsigned.patch 106 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-char-serial-Fix-emptyness-check.patch 46 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-char-serial-Fix-emptyness-handling.patch 54 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-char-serial-Use-generic-Fifo8.patch 290 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-char-serial-cosmetic-fixes.patch 95 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-char-serial-fix-copy-paste-error-fifo8_is_full-vs-em.patch 46 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-char-serial-serial_ioport_write-Factor-out-common-co.patch 62 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-qemu-char-ignore-flow-control-if-a-PTY-s-slave-is-no.patch 61 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-serial-change-retry-logic-to-avoid-concurrency.patch 143 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-serial-check-if-backed-by-a-physical-serial-port-at-.patch 63 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-serial-clean-up-THRE-TEMT-handling.patch 125 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-serial-make-tsr_retry-unsigned.patch 97 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-serial-only-resample-THR-interrupt-on-rising-edge-of.patch 87 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-serial-poll-the-serial-console-with-G_IO_HUP.patch 124 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-serial-remove-watch-on-reset.patch 87 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-serial-reset-thri_pending-on-IER-writes-with-THRI-0.patch 85 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-serial-separate-serial_xmit-and-serial_watch_cb.patch 102 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-serial-simplify-tsr_retry-reset.patch 49 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-serial-update-LSR-on-enabling-disabling-FIFOs.patch 63 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-spice-fix-spice_chr_add_watch-pre-condition.patch 49 ●●●●● patch | view | raw | blame | history
SPECS/qemu-kvm.spec 94 ●●●●● patch | view | raw | blame | history
SOURCES/kvm-char-change-qemu_chr_fe_add_watch-to-return-unsigned.patch
New file
@@ -0,0 +1,106 @@
From 357b8e45c81e79a1547f65ea4109b0882050b1e9 Mon Sep 17 00:00:00 2001
From: Eduardo Habkost <ehabkost@redhat.com>
Date: Tue, 23 May 2017 14:15:10 +0200
Subject: [PATCH] char: change qemu_chr_fe_add_watch to return unsigned
RH-Author: Eduardo Habkost <ehabkost@redhat.com>
Message-id: <20170523141510.24762-1-ehabkost@redhat.com>
Patchwork-id: 75397
O-Subject: [RHEL-7.3.z qemu-kvm PATCH] char: change qemu_chr_fe_add_watch to return unsigned
Bugzilla: 1452332
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1452332
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=13257135
g_source_attach can return any value between 1 and UINT_MAX if you let
QEMU run long enough.  However, qemu_chr_fe_add_watch can also return
a negative errno value when the device is disconnected or does not
support chr_add_watch.  Change it to return zero to avoid overloading
these values.
Fix the cadence_uart which asserts in this case (easily obtained with
"-serial pty").
Backport notes:
  This is the same patch submitted to the 7.4 branch.
7.4 backport conflicts:
    hw/char/cadence_uart.c (no qemu_chr_fe_add_watch() call)
    net/vhost-user.c (doesn't exit)
    qemu-char.c (trivial conflict)
Tested-by: Bret Ketchum <bcketchum@gmail.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 6f1de6b70d857d5e316ae6fd908f52818b827b08)
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 include/sysemu/char.h | 16 ++++++++++++++--
 qemu-char.c           |  8 ++++----
 2 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index ad101d9..c0e5b25 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -147,8 +147,20 @@ void qemu_chr_fe_set_open(struct CharDriverState *chr, int fe_open);
 void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
     GCC_FMT_ATTR(2, 3);
-int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
-                          GIOFunc func, void *user_data);
+/**
+ * @qemu_chr_fe_add_watch:
+ *
+ * If the backend is connected, create and add a #GSource that fires
+ * when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP)
+ * is active; return the #GSource's tag.  If it is disconnected,
+ * return 0.
+ *
+ * @cond the condition to poll for
+ * @func the function to call when the condition happens
+ * @user_data the opaque pointer to pass to @func
+ */
+guint qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
+                            GIOFunc func, void *user_data);
 /**
  * @qemu_chr_fe_write:
diff --git a/qemu-char.c b/qemu-char.c
index 08cb959..5edca0a 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3373,19 +3373,19 @@ void qemu_chr_fe_set_open(struct CharDriverState *chr, int fe_open)
     }
 }
-int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
-                          GIOFunc func, void *user_data)
+guint qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
+                            GIOFunc func, void *user_data)
 {
     GSource *src;
     guint tag;
     if (s->chr_add_watch == NULL) {
-        return -ENOSYS;
+        return 0;
     }
     src = s->chr_add_watch(s, cond);
     if (!src) {
-        return -EINVAL;
+        return 0;
     }
     g_source_set_callback(src, (GSourceFunc)func, user_data, NULL);
--
1.8.3.1
SOURCES/kvm-char-serial-Fix-emptyness-check.patch
New file
@@ -0,0 +1,46 @@
From c9b0af3739fc5b79a20bf2492b5e8c1dea055dc0 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:10 +0200
Subject: [PATCH 05/18] char/serial: Fix emptyness check
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-6-famz@redhat.com>
Patchwork-id: 75361
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 05/18] char/serial: Fix emptyness check
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
This was guarding against a full fifo rather than an empty fifo when
popping. Fix.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit 88c1ee73d3231c74ff90bcfc084a7589670ec244)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/char/serial.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 3345de1..489a885 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -225,7 +225,7 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
     if (s->tsr_retry <= 0) {
         if (s->fcr & UART_FCR_FE) {
-            s->tsr = fifo8_is_full(&s->xmit_fifo) ?
+            s->tsr = fifo8_is_empty(&s->xmit_fifo) ?
                         0 : fifo8_pop(&s->xmit_fifo);
             if (!s->xmit_fifo.num) {
                 s->lsr |= UART_LSR_THRE;
--
1.8.3.1
SOURCES/kvm-char-serial-Fix-emptyness-handling.patch
New file
@@ -0,0 +1,54 @@
From a14715c6b64f4764259028923a9c04ae7844c546 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:11 +0200
Subject: [PATCH 06/18] char/serial: Fix emptyness handling
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-7-famz@redhat.com>
Patchwork-id: 75359
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 06/18] char/serial: Fix emptyness handling
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Don Slutz <dslutz@verizon.com>
The commit 88c1ee73d3231c74ff90bcfc084a7589670ec244
char/serial: Fix emptyness check
Still causes extra NULL byte(s) to be sent.
So if the fifo is empty, do not send an extra NULL byte.
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Don Slutz <dslutz@verizon.com>
Message-id: 1395160174-16006-1-git-send-email-dslutz@verizon.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit dffacd4654ec8bf2898aed230852154c6ed755ed)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/char/serial.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 489a885..e020b0e 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -225,8 +225,10 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
     if (s->tsr_retry <= 0) {
         if (s->fcr & UART_FCR_FE) {
-            s->tsr = fifo8_is_empty(&s->xmit_fifo) ?
-                        0 : fifo8_pop(&s->xmit_fifo);
+            if (fifo8_is_empty(&s->xmit_fifo)) {
+                return FALSE;
+            }
+            s->tsr = fifo8_pop(&s->xmit_fifo);
             if (!s->xmit_fifo.num) {
                 s->lsr |= UART_LSR_THRE;
             }
--
1.8.3.1
SOURCES/kvm-char-serial-Use-generic-Fifo8.patch
New file
@@ -0,0 +1,290 @@
From 462caff619f890c56194ac50b70b095c26cd133e Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:07 +0200
Subject: [PATCH 02/18] char/serial: Use generic Fifo8
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-3-famz@redhat.com>
Patchwork-id: 75358
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 02/18] char/serial: Use generic Fifo8
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Use the generic Fifo8 helper provided by QEMU, rather than re-implement
privately.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit 8e8638fa87ff045f5dadec7342301bf10de776ff)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
    hw/char/serial.c
Conflict because in downstream we've got 4df7961faa out of order.
---
 hw/char/serial.c         | 98 +++++++++++++++++-------------------------------
 include/hw/char/serial.h | 15 +++-----
 2 files changed, 39 insertions(+), 74 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 7866b0f..0d4450e 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -93,8 +93,6 @@
 #define UART_FCR_RFR        0x02    /* RCVR Fifo Reset */
 #define UART_FCR_FE         0x01    /* FIFO Enable */
-#define XMIT_FIFO           0
-#define RECV_FIFO           1
 #define MAX_XMIT_RETRY      4
 #ifdef DEBUG_SERIAL
@@ -107,50 +105,14 @@ do {} while (0)
 static void serial_receive1(void *opaque, const uint8_t *buf, int size);
-static void fifo_clear(SerialState *s, int fifo)
+static inline void recv_fifo_put(SerialState *s, uint8_t chr)
 {
-    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
-    memset(f->data, 0, UART_FIFO_LENGTH);
-    f->count = 0;
-    f->head = 0;
-    f->tail = 0;
-}
-
-static int fifo_put(SerialState *s, int fifo, uint8_t chr)
-{
-    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
-
     /* Receive overruns do not overwrite FIFO contents. */
-    if (fifo == XMIT_FIFO || f->count < UART_FIFO_LENGTH) {
-
-        f->data[f->head++] = chr;
-
-        if (f->head == UART_FIFO_LENGTH)
-            f->head = 0;
-    }
-
-    if (f->count < UART_FIFO_LENGTH)
-        f->count++;
-    else if (fifo == RECV_FIFO)
+    if (!fifo8_is_full(&s->recv_fifo)) {
+        fifo8_push(&s->recv_fifo, chr);
+    } else {
         s->lsr |= UART_LSR_OE;
-
-    return 1;
-}
-
-static uint8_t fifo_get(SerialState *s, int fifo)
-{
-    SerialFIFO *f = (fifo) ? &s->recv_fifo : &s->xmit_fifo;
-    uint8_t c;
-
-    if(f->count == 0)
-        return 0;
-
-    c = f->data[f->tail++];
-    if (f->tail == UART_FIFO_LENGTH)
-        f->tail = 0;
-    f->count--;
-
-    return c;
+    }
 }
 static void serial_update_irq(SerialState *s)
@@ -166,7 +128,7 @@ static void serial_update_irq(SerialState *s)
         tmp_iir = UART_IIR_CTI;
     } else if ((s->ier & UART_IER_RDI) && (s->lsr & UART_LSR_DR) &&
                (!(s->fcr & UART_FCR_FE) ||
-                s->recv_fifo.count >= s->recv_fifo.itl)) {
+                s->recv_fifo.num >= s->recv_fifo_itl)) {
         tmp_iir = UART_IIR_RDI;
     } else if ((s->ier & UART_IER_THRI) && s->thr_ipending) {
         tmp_iir = UART_IIR_THRI;
@@ -263,8 +225,9 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
     if (s->tsr_retry <= 0) {
         if (s->fcr & UART_FCR_FE) {
-            s->tsr = fifo_get(s,XMIT_FIFO);
-            if (!s->xmit_fifo.count) {
+            s->tsr = fifo8_is_full(&s->xmit_fifo) ?
+                        0 : fifo8_pop(&s->xmit_fifo);
+            if (!s->xmit_fifo.num) {
                 s->lsr |= UART_LSR_THRE;
             }
         } else if ((s->lsr & UART_LSR_THRE)) {
@@ -318,7 +281,11 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
         } else {
             s->thr = (uint8_t) val;
             if(s->fcr & UART_FCR_FE) {
-                fifo_put(s, XMIT_FIFO, s->thr);
+                /* xmit overruns overwrite data, so make space if needed */
+                if (fifo8_is_full(&s->xmit_fifo)) {
+                    fifo8_pop(&s->xmit_fifo);
+                }
+                fifo8_push(&s->xmit_fifo, s->thr);
                 s->thr_ipending = 0;
                 s->lsr &= ~UART_LSR_TEMT;
                 s->lsr &= ~UART_LSR_THRE;
@@ -369,28 +336,28 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
         if (val & UART_FCR_RFR) {
             qemu_del_timer(s->fifo_timeout_timer);
             s->timeout_ipending=0;
-            fifo_clear(s,RECV_FIFO);
+            fifo8_reset(&s->recv_fifo);
         }
         if (val & UART_FCR_XFR) {
-            fifo_clear(s,XMIT_FIFO);
+            fifo8_reset(&s->xmit_fifo);
         }
         if (val & UART_FCR_FE) {
             s->iir |= UART_IIR_FE;
-            /* Set RECV_FIFO trigger Level */
+            /* Set recv_fifo trigger Level */
             switch (val & 0xC0) {
             case UART_FCR_ITL_1:
-                s->recv_fifo.itl = 1;
+                s->recv_fifo_itl = 1;
                 break;
             case UART_FCR_ITL_2:
-                s->recv_fifo.itl = 4;
+                s->recv_fifo_itl = 4;
                 break;
             case UART_FCR_ITL_3:
-                s->recv_fifo.itl = 8;
+                s->recv_fifo_itl = 8;
                 break;
             case UART_FCR_ITL_4:
-                s->recv_fifo.itl = 14;
+                s->recv_fifo_itl = 14;
                 break;
             }
         } else
@@ -462,8 +429,9 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
             ret = s->divider & 0xff;
         } else {
             if(s->fcr & UART_FCR_FE) {
-                ret = fifo_get(s,RECV_FIFO);
-                if (s->recv_fifo.count == 0) {
+                ret = fifo8_is_full(&s->recv_fifo) ?
+                            0 : fifo8_pop(&s->recv_fifo);
+                if (s->recv_fifo.num == 0) {
                     s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
                 } else {
                     qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
@@ -537,7 +505,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
 static int serial_can_receive(SerialState *s)
 {
     if(s->fcr & UART_FCR_FE) {
-        if (s->recv_fifo.count < UART_FIFO_LENGTH) {
+        if (s->recv_fifo.num < UART_FIFO_LENGTH) {
             /*
              * Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1
              * if above. If UART_FIFO_LENGTH - fifo.count is advertised the
@@ -545,8 +513,8 @@ static int serial_can_receive(SerialState *s)
              * the guest has a chance to respond, effectively overriding the ITL
              * that the guest has set.
              */
-            return (s->recv_fifo.count <= s->recv_fifo.itl) ?
-                        s->recv_fifo.itl - s->recv_fifo.count : 1;
+            return (s->recv_fifo.num <= s->recv_fifo_itl) ?
+                        s->recv_fifo_itl - s->recv_fifo.num : 1;
         } else {
             return 0;
         }
@@ -559,7 +527,7 @@ static void serial_receive_break(SerialState *s)
 {
     s->rbr = 0;
     /* When the LSR_DR is set a null byte is pushed into the fifo */
-    fifo_put(s, RECV_FIFO, '\0');
+    recv_fifo_put(s, '\0');
     s->lsr |= UART_LSR_BI | UART_LSR_DR;
     serial_update_irq(s);
 }
@@ -567,7 +535,7 @@ static void serial_receive_break(SerialState *s)
 /* There's data in recv_fifo and s->rbr has not been read for 4 char transmit times */
 static void fifo_timeout_int (void *opaque) {
     SerialState *s = opaque;
-    if (s->recv_fifo.count) {
+    if (s->recv_fifo.num) {
         s->timeout_ipending = 1;
         serial_update_irq(s);
     }
@@ -589,7 +557,7 @@ static void serial_receive1(void *opaque, const uint8_t *buf, int size)
     if(s->fcr & UART_FCR_FE) {
         int i;
         for (i = 0; i < size; i++) {
-            fifo_put(s, RECV_FIFO, buf[i]);
+            recv_fifo_put(s, buf[i]);
         }
         s->lsr |= UART_LSR_DR;
         /* call the timeout receive callback in 4 char transmit time */
@@ -669,8 +637,8 @@ static void serial_reset(void *opaque)
     s->char_transmit_time = (get_ticks_per_sec() / 9600) * 10;
     s->poll_msl = 0;
-    fifo_clear(s,RECV_FIFO);
-    fifo_clear(s,XMIT_FIFO);
+    fifo8_reset(&s->recv_fifo);
+    fifo8_reset(&s->xmit_fifo);
     s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
@@ -693,6 +661,8 @@ void serial_init_core(SerialState *s)
     qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
                           serial_event, s);
+    fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
+    fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
     serial_reset(s);
 }
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index bca79f1..9ab81f6 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -28,17 +28,10 @@
 #include "hw/hw.h"
 #include "sysemu/sysemu.h"
 #include "exec/memory.h"
+#include "qemu/fifo8.h"
 #define UART_FIFO_LENGTH    16      /* 16550A Fifo Length */
-typedef struct SerialFIFO {
-    uint8_t data[UART_FIFO_LENGTH];
-    uint8_t count;
-    uint8_t itl;                        /* Interrupt Trigger Level */
-    uint8_t tail;
-    uint8_t head;
-} SerialFIFO;
-
 struct SerialState {
     uint16_t divider;
     uint8_t rbr; /* receive register */
@@ -67,8 +60,10 @@ struct SerialState {
     /* Time when the last byte was successfully sent out of the tsr */
     uint64_t last_xmit_ts;
-    SerialFIFO recv_fifo;
-    SerialFIFO xmit_fifo;
+    Fifo8 recv_fifo;
+    Fifo8 xmit_fifo;
+    /* Interrupt trigger level for recv_fifo */
+    uint8_t recv_fifo_itl;
     struct QEMUTimer *fifo_timeout_timer;
     int timeout_ipending;           /* timeout interrupt pending state */
--
1.8.3.1
SOURCES/kvm-char-serial-cosmetic-fixes.patch
New file
@@ -0,0 +1,95 @@
From f3c1372702f7cac6d8b405cf8c51e15eabc7c054 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:06 +0200
Subject: [PATCH 01/18] char/serial: cosmetic fixes.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-2-famz@redhat.com>
Patchwork-id: 75356
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 01/18] char/serial: cosmetic fixes.
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Some cosmetic fixes to char/serial fixing some checkpatch errors.
Cc: qemu-trivial@nongnu.org
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit 7f4f0a227fe0b24c35d0898f9ae7d5909fb51137)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/char/serial.c | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 2383c31..7866b0f 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -264,8 +264,9 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
     if (s->tsr_retry <= 0) {
         if (s->fcr & UART_FCR_FE) {
             s->tsr = fifo_get(s,XMIT_FIFO);
-            if (!s->xmit_fifo.count)
+            if (!s->xmit_fifo.count) {
                 s->lsr |= UART_LSR_THRE;
+            }
         } else if ((s->lsr & UART_LSR_THRE)) {
             return FALSE;
         } else {
@@ -462,10 +463,11 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
         } else {
             if(s->fcr & UART_FCR_FE) {
                 ret = fifo_get(s,RECV_FIFO);
-                if (s->recv_fifo.count == 0)
+                if (s->recv_fifo.count == 0) {
                     s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
-                else
+                } else {
                     qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock_ns (vm_clock) + s->char_transmit_time * 4);
+                }
                 s->timeout_ipending = 0;
             } else {
                 ret = s->rbr;
@@ -535,15 +537,21 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
 static int serial_can_receive(SerialState *s)
 {
     if(s->fcr & UART_FCR_FE) {
-        if(s->recv_fifo.count < UART_FIFO_LENGTH)
-        /* Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1 if above. If UART_FIFO_LENGTH - fifo.count is
-        advertised the effect will be to almost always fill the fifo completely before the guest has a chance to respond,
-        effectively overriding the ITL that the guest has set. */
-             return (s->recv_fifo.count <= s->recv_fifo.itl) ? s->recv_fifo.itl - s->recv_fifo.count : 1;
-        else
-             return 0;
+        if (s->recv_fifo.count < UART_FIFO_LENGTH) {
+            /*
+             * Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1
+             * if above. If UART_FIFO_LENGTH - fifo.count is advertised the
+             * effect will be to almost always fill the fifo completely before
+             * the guest has a chance to respond, effectively overriding the ITL
+             * that the guest has set.
+             */
+            return (s->recv_fifo.count <= s->recv_fifo.itl) ?
+                        s->recv_fifo.itl - s->recv_fifo.count : 1;
+        } else {
+            return 0;
+        }
     } else {
-    return !(s->lsr & UART_LSR_DR);
+        return !(s->lsr & UART_LSR_DR);
     }
 }
--
1.8.3.1
SOURCES/kvm-char-serial-fix-copy-paste-error-fifo8_is_full-vs-em.patch
New file
@@ -0,0 +1,46 @@
From a04a0d4cf131163600ebede71d223d9d01a32511 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:09 +0200
Subject: [PATCH 04/18] char/serial: fix copy&paste error (fifo8_is_full vs
 empty)
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-5-famz@redhat.com>
Patchwork-id: 75360
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 04/18] char/serial: fix copy&paste error (fifo8_is_full vs empty)
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Vladimir Senkov <hangup@gmail.com>
Copy&paste error in serial.c causes a crash when attempting
to read from UART (if there is no data to be read)
Signed-off-by: Vladimir Senkov <hangup@gmail.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit b165b0d8e62bb65a02d7670d75ebb77a9280bde1)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/char/serial.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 72112cc..3345de1 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -425,7 +425,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
             ret = s->divider & 0xff;
         } else {
             if(s->fcr & UART_FCR_FE) {
-                ret = fifo8_is_full(&s->recv_fifo) ?
+                ret = fifo8_is_empty(&s->recv_fifo) ?
                             0 : fifo8_pop(&s->recv_fifo);
                 if (s->recv_fifo.num == 0) {
                     s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
--
1.8.3.1
SOURCES/kvm-char-serial-serial_ioport_write-Factor-out-common-co.patch
New file
@@ -0,0 +1,62 @@
From 5114efc4a077a1fdfa9873e6f44a00d5f8101f65 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:08 +0200
Subject: [PATCH 03/18] char/serial: serial_ioport_write: Factor out common
 code
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-4-famz@redhat.com>
Patchwork-id: 75357
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 03/18] char/serial: serial_ioport_write: Factor out common code
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
These three lines are common to both FIFO and regular mode. Just factor
them out to outside the if rather than replicate the same lines inside
both if and else.
Cc: qemu-trivial@nongnu.org
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(cherry picked from commit b5601df7624b461759651c49ac72a189951780b9)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/char/serial.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 0d4450e..72112cc 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -286,15 +286,11 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
                     fifo8_pop(&s->xmit_fifo);
                 }
                 fifo8_push(&s->xmit_fifo, s->thr);
-                s->thr_ipending = 0;
                 s->lsr &= ~UART_LSR_TEMT;
-                s->lsr &= ~UART_LSR_THRE;
-                serial_update_irq(s);
-            } else {
-                s->thr_ipending = 0;
-                s->lsr &= ~UART_LSR_THRE;
-                serial_update_irq(s);
             }
+            s->thr_ipending = 0;
+            s->lsr &= ~UART_LSR_THRE;
+            serial_update_irq(s);
             serial_xmit(NULL, G_IO_OUT, s);
         }
         break;
--
1.8.3.1
SOURCES/kvm-qemu-char-ignore-flow-control-if-a-PTY-s-slave-is-no.patch
New file
@@ -0,0 +1,61 @@
From 1e2929d890fb4cc88162b9771ed93b1c61f89b33 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:14 +0200
Subject: [PATCH 09/18] qemu-char: ignore flow control if a PTY's slave is not
 connected
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-10-famz@redhat.com>
Patchwork-id: 75364
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 09/18] qemu-char: ignore flow control if a PTY's slave is not connected
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
After commit f702e62 (serial: change retry logic to avoid concurrency,
2014-07-11), guest boot hangs if the backend is an unconnected PTY.
The reason is that PTYs do not support G_IO_HUP, and serial_xmit is
never called.  To fix this, simply invoke serial_xmit immediately
(via g_idle_source_new) when this happens.
Tested-by: Pavel Hrdina <phrdina@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 62c339c5272ce8fbe8ca52695cee8ff40da7872e)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 qemu-char.c | 7 +++++++
 1 file changed, 7 insertions(+)
diff --git a/qemu-char.c b/qemu-char.c
index 47ac55a..08cb959 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1068,6 +1068,9 @@ static int pty_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 static GSource *pty_chr_add_watch(CharDriverState *chr, GIOCondition cond)
 {
     PtyCharDriver *s = chr->opaque;
+    if (!s->connected) {
+        return NULL;
+    }
     return g_io_create_watch(s->fd, cond);
 }
@@ -3381,6 +3384,10 @@ int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
     }
     src = s->chr_add_watch(s, cond);
+    if (!src) {
+        return -EINVAL;
+    }
+
     g_source_set_callback(src, (GSourceFunc)func, user_data, NULL);
     tag = g_source_attach(src, NULL);
     g_source_unref(src);
--
1.8.3.1
SOURCES/kvm-serial-change-retry-logic-to-avoid-concurrency.patch
New file
@@ -0,0 +1,143 @@
From 3ddb1809fc188f9aca337b19a81b40da5b992057 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:13 +0200
Subject: [PATCH 08/18] serial: change retry logic to avoid concurrency
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-9-famz@redhat.com>
Patchwork-id: 75362
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 08/18] serial: change retry logic to avoid concurrency
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Kirill Batuzov <batuzovk@ispras.ru>
Whenever serial_xmit fails to transmit a byte it adds a watch that would
call it again when the "line" becomes ready. This results in a retry
chain:
  serial_xmit -> add_watch -> serial_xmit
Each chain is able to transmit one character, and for every character
passed to serial by the guest driver a new chain is spawned.
The problem lays with the fact that a new chain is spawned even when
there is one already waiting on the watch. So there can be several retry
chains waiting concurrently on one "line". Every chain tries to transmit
current character, so character order is not messed up. But also every
chain increases retry counter (tsr_retry). If there are enough
concurrent chains this counter will hit MAX_XMIT_RETRY value and
the character will be dropped.
To reproduce this bug you need to feed serial output to some program
consuming it slowly enough. A python script from bug #1335444
description is an example of such program.
This commit changes retry logic in the following way to avoid
concurrency: instead of spawning a new chain for each character being
transmitted spawn only one and make it transmit characters until FIFO is
empty.
The change consists of two parts:
 - add a do {} while () loop in serial_xmit (diff is a bit erratic
   for this part, diff -w will show actual change),
 - do not call serial_xmit from serial_ioport_write if there is one
   waiting on the watch already.
This should fix another issue causing bug #1335444.
Signed-off-by: Kirill Batuzov <batuzovk@ispras.ru>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit f702e62a193e9ddb41cef95068717e5582b39a64)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/char/serial.c | 59 +++++++++++++++++++++++++++++++-------------------------
 1 file changed, 33 insertions(+), 26 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index add4738..33e06fb 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -223,37 +223,42 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
 {
     SerialState *s = opaque;
-    if (s->tsr_retry <= 0) {
-        if (s->fcr & UART_FCR_FE) {
-            if (fifo8_is_empty(&s->xmit_fifo)) {
+    do {
+        if (s->tsr_retry <= 0) {
+            if (s->fcr & UART_FCR_FE) {
+                if (fifo8_is_empty(&s->xmit_fifo)) {
+                    return FALSE;
+                }
+                s->tsr = fifo8_pop(&s->xmit_fifo);
+                if (!s->xmit_fifo.num) {
+                    s->lsr |= UART_LSR_THRE;
+                }
+            } else if ((s->lsr & UART_LSR_THRE)) {
                 return FALSE;
-            }
-            s->tsr = fifo8_pop(&s->xmit_fifo);
-            if (!s->xmit_fifo.num) {
+            } else {
+                s->tsr = s->thr;
                 s->lsr |= UART_LSR_THRE;
+                s->lsr &= ~UART_LSR_TEMT;
             }
-        } else if ((s->lsr & UART_LSR_THRE)) {
-            return FALSE;
-        } else {
-            s->tsr = s->thr;
-            s->lsr |= UART_LSR_THRE;
-            s->lsr &= ~UART_LSR_TEMT;
         }
-    }
-    if (s->mcr & UART_MCR_LOOP) {
-        /* in loopback mode, say that we just received a char */
-        serial_receive1(s, &s->tsr, 1);
-    } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
-        if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
-            qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, serial_xmit, s) > 0) {
-            s->tsr_retry++;
-            return FALSE;
+        if (s->mcr & UART_MCR_LOOP) {
+            /* in loopback mode, say that we just received a char */
+            serial_receive1(s, &s->tsr, 1);
+        } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
+            if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
+                qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
+                                      serial_xmit, s) > 0) {
+                s->tsr_retry++;
+                return FALSE;
+            }
+            s->tsr_retry = 0;
+        } else {
+            s->tsr_retry = 0;
         }
-        s->tsr_retry = 0;
-    } else {
-        s->tsr_retry = 0;
-    }
+        /* Transmit another byte if it is already available. It is only
+           possible when FIFO is enabled and not empty. */
+    } while ((s->fcr & UART_FCR_FE) && !fifo8_is_empty(&s->xmit_fifo));
     s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
@@ -293,7 +298,9 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
             s->thr_ipending = 0;
             s->lsr &= ~UART_LSR_THRE;
             serial_update_irq(s);
-            serial_xmit(NULL, G_IO_OUT, s);
+            if (s->tsr_retry <= 0) {
+                serial_xmit(NULL, G_IO_OUT, s);
+            }
         }
         break;
     case 1:
--
1.8.3.1
SOURCES/kvm-serial-check-if-backed-by-a-physical-serial-port-at-.patch
New file
@@ -0,0 +1,63 @@
From 1882bb1a0967e7d513b0d5bd060fa214bc44efcb Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:15 +0200
Subject: [PATCH 10/18] serial: check if backed by a physical serial port at
 realize time
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-11-famz@redhat.com>
Patchwork-id: 75366
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 10/18] serial: check if backed by a physical serial port at realize time
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
Right now, s->poll_msl may linger at "0" value for an arbitrarily long
time, until serial_update_msl is called for the first time.  This is
unnecessary, and will lead to the s->poll_msl field being unnecessarily
migrated.
We can call serial_update_msl immediately at realize time (via
serial_reset) and be done with it.  The memory-mapped UART was already
doing that, but not the ISA and PCI variants.
Regarding the delta bits, be consistent with what serial_reset does when
the serial port is not backed by a physical serial port, and always clear
them at reset time.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit a30cf8760f4a59797fc060c3c5a13b7749551d0c)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/char/serial.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 33e06fb..5ef9b95 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -650,6 +650,9 @@ static void serial_reset(void *opaque)
     s->thr_ipending = 0;
     s->last_break_enable = 0;
     qemu_irq_lower(s->irq);
+
+    serial_update_msl(s);
+    s->msr &= ~UART_MSR_ANY_DELTA;
 }
 void serial_init_core(SerialState *s)
@@ -768,7 +771,5 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
     memory_region_init_io(&s->io, &serial_mm_ops[end], s,
                           "serial", 8 << it_shift);
     memory_region_add_subregion(address_space, base, &s->io);
-
-    serial_update_msl(s);
     return s;
 }
--
1.8.3.1
SOURCES/kvm-serial-clean-up-THRE-TEMT-handling.patch
New file
@@ -0,0 +1,125 @@
From 9afba2b1b9f8c2af3165fb0d9b68888996fe2330 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:17 +0200
Subject: [PATCH 12/18] serial: clean up THRE/TEMT handling
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-13-famz@redhat.com>
Patchwork-id: 75367
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 12/18] serial: clean up THRE/TEMT handling
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
- assert TEMT is cleared before sending a character; we'll get one from
TSR if tsr_retry > 0, from the FIFO or THR otherwise
- assert THRE cleared and FIFO not empty (if enabled) before fetching a
character to send.  This effectively reverts dffacd46, but the check
makes no sense and commit f702e62 (serial: change retry logic to avoid
concurrency, 2014-07-11) must have made it unnecessary.  The commit
message for f702e62 talks about multiple calls to qemu_chr_fe_add_watch
triggering s->tsr_retry >= MAX_XMIT_RETRY, but other failures were
possible.  For example, if you have multiple calls, the subsequent ones
will see s->tsr_retry == 0 and will find THRE and/or TEMT on entry.
- for clarity, raise THRI immediately after the code sets THRE
- check THRE to see if another character has to be sent.  This makes
the assertions more obvious and also means TEMT has to be set as soon as
the loop ends.  It makes the loop send both TSR and THR if flow-control
happens in non-FIFO mode.  Previously, THR would be lost.
- clear TEMT together with THRE even in the non-FIFO case
The last two items are bugfixes, but they were just found by inspection
and do not squash known bugs.
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 0d931d706266d6ada3bf22d3afca1afdc8d12fa9)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
    hw/char/serial.c
Contextual conflict because upstream has the new timer API
qemu_clock_get_ns, but downstream still uses qemu_get_clock_ns.
---
 hw/char/serial.c | 26 ++++++++++++--------------
 1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 15c628f..c2be4bd 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -224,21 +224,23 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
     SerialState *s = opaque;
     do {
+        assert(!(s->lsr & UART_LSR_TEMT));
         if (s->tsr_retry <= 0) {
+            assert(!(s->lsr & UART_LSR_THRE));
+
             if (s->fcr & UART_FCR_FE) {
-                if (fifo8_is_empty(&s->xmit_fifo)) {
-                    return FALSE;
-                }
+                assert(!fifo8_is_empty(&s->xmit_fifo));
                 s->tsr = fifo8_pop(&s->xmit_fifo);
                 if (!s->xmit_fifo.num) {
                     s->lsr |= UART_LSR_THRE;
                 }
-            } else if ((s->lsr & UART_LSR_THRE)) {
-                return FALSE;
             } else {
                 s->tsr = s->thr;
                 s->lsr |= UART_LSR_THRE;
-                s->lsr &= ~UART_LSR_TEMT;
+            }
+            if ((s->lsr & UART_LSR_THRE) && !s->thr_ipending) {
+                s->thr_ipending = 1;
+                serial_update_irq(s);
             }
         }
@@ -256,17 +258,13 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
         } else {
             s->tsr_retry = 0;
         }
+
         /* Transmit another byte if it is already available. It is only
            possible when FIFO is enabled and not empty. */
-    } while ((s->fcr & UART_FCR_FE) && !fifo8_is_empty(&s->xmit_fifo));
+    } while (!(s->lsr & UART_LSR_THRE));
     s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
-
-    if (s->lsr & UART_LSR_THRE) {
-        s->lsr |= UART_LSR_TEMT;
-        s->thr_ipending = 1;
-        serial_update_irq(s);
-    }
+    s->lsr |= UART_LSR_TEMT;
     return FALSE;
 }
@@ -293,10 +291,10 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
                     fifo8_pop(&s->xmit_fifo);
                 }
                 fifo8_push(&s->xmit_fifo, s->thr);
-                s->lsr &= ~UART_LSR_TEMT;
             }
             s->thr_ipending = 0;
             s->lsr &= ~UART_LSR_THRE;
+            s->lsr &= ~UART_LSR_TEMT;
             serial_update_irq(s);
             if (s->tsr_retry <= 0) {
                 serial_xmit(NULL, G_IO_OUT, s);
--
1.8.3.1
SOURCES/kvm-serial-make-tsr_retry-unsigned.patch
New file
@@ -0,0 +1,97 @@
From fece1f0b57a8daa08e04338baab90202d75766ec Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:20 +0200
Subject: [PATCH 15/18] serial: make tsr_retry unsigned
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-16-famz@redhat.com>
Patchwork-id: 75371
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 15/18] serial: make tsr_retry unsigned
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
It can never become negative; reflect this in the type of the field
and simplify the conditions.
Tested-by: Bret Ketchum <bcketchum@gmail.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 807464d8a7326e1025a2f392bf41636b0809d6da)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
    hw/char/serial.c
Downstream doesn't have 7385b275d9, so dropped the vmstate_serial_tsr
hunk because the structure doesn't exist.
The serial_post_load hunk is backported because it's safe, and good for
the future backport of 7385b275d9 if there will be.
---
 hw/char/serial.c         | 10 +++++++---
 include/hw/char/serial.h |  2 +-
 2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 9986adf..afa1932 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -225,7 +225,7 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
     do {
         assert(!(s->lsr & UART_LSR_TEMT));
-        if (s->tsr_retry <= 0) {
+        if (s->tsr_retry == 0) {
             assert(!(s->lsr & UART_LSR_THRE));
             if (s->fcr & UART_FCR_FE) {
@@ -248,7 +248,7 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
             /* in loopback mode, say that we just received a char */
             serial_receive1(s, &s->tsr, 1);
         } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
-            if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
+            if (s->tsr_retry < MAX_XMIT_RETRY &&
                 qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
                                       serial_xmit, s) > 0) {
                 s->tsr_retry++;
@@ -296,7 +296,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
             s->lsr &= ~UART_LSR_THRE;
             s->lsr &= ~UART_LSR_TEMT;
             serial_update_irq(s);
-            if (s->tsr_retry <= 0) {
+            if (s->tsr_retry == 0) {
                 serial_xmit(NULL, G_IO_OUT, s);
             }
         }
@@ -619,6 +619,10 @@ static int serial_post_load(void *opaque, int version_id)
     if (version_id < 3) {
         s->fcr_vmstate = 0;
     }
+    if (s->tsr_retry > MAX_XMIT_RETRY) {
+        s->tsr_retry = MAX_XMIT_RETRY;
+    }
+
     /* Initialize fcr via setter to perform essential side-effects */
     serial_ioport_write(s, 0x02, s->fcr_vmstate, 1);
     serial_update_parameters(s);
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index 9ab81f6..2661f8c 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -55,7 +55,7 @@ struct SerialState {
     int last_break_enable;
     int it_shift;
     int baudbase;
-    int tsr_retry;
+    uint32_t tsr_retry;
     uint32_t wakeup;
     /* Time when the last byte was successfully sent out of the tsr */
--
1.8.3.1
SOURCES/kvm-serial-only-resample-THR-interrupt-on-rising-edge-of.patch
New file
@@ -0,0 +1,87 @@
From 95388b9e0745ca0125012f050c53f651811b5189 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:19 +0200
Subject: [PATCH 14/18] serial: only resample THR interrupt on rising edge of
 IER.THRI
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-15-famz@redhat.com>
Patchwork-id: 75370
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 14/18] serial: only resample THR interrupt on rising edge of IER.THRI
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
There is disagreement on whether LSR.THRE should be resampled when
IER.THRI goes from 1 to 1.  Bochs only does it if IER.THRI goes from 0
to 1; PCE does it even if IER.THRI is unchanged.  But the Windows driver
seems to always go from 1 to 0 and back to 1, so do things in agreement
with Bochs, because the handling of thr_ipending was reported in 2010
(https://lists.gnu.org/archive/html/qemu-devel/2010-03/msg01914.html)
as breaking DR-DOS Plus.
Reported-by: Roy Tam <roytam@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 1645b8eee558ffe2389a081bf61d08a864c36d2c)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/char/serial.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index e0d29a8..9986adf 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -306,10 +306,12 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
             s->divider = (s->divider & 0x00ff) | (val << 8);
             serial_update_parameters(s);
         } else {
+            uint8_t changed = (s->ier ^ val) & 0x0f;
             s->ier = val & 0x0f;
             /* If the backend device is a real serial port, turn polling of the modem
-               status lines on physical port on or off depending on UART_IER_MSI state */
-            if (s->poll_msl >= 0) {
+             * status lines on physical port on or off depending on UART_IER_MSI state.
+             */
+            if ((changed & UART_IER_MSI) && s->poll_msl >= 0) {
                 if (s->ier & UART_IER_MSI) {
                      s->poll_msl = 1;
                      serial_update_msl(s);
@@ -324,18 +326,23 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
              * This is not in the datasheet, but Windows relies on it.  It is
              * unclear if THRE has to be resampled every time THRI becomes
              * 1, or only on the rising edge.  Bochs does the latter, and Windows
-             * always toggles IER to all zeroes and back to all ones.  But for
-             * now leave it as it has always been in QEMU.
+             * always toggles IER to all zeroes and back to all ones, so do the
+             * same.
              *
              * If IER.THRI is zero, thr_ipending is not used.  Set it to zero
              * so that the thr_ipending subsection is not migrated.
              */
-            if ((s->ier & UART_IER_THRI) && (s->lsr & UART_LSR_THRE)) {
-                s->thr_ipending = 1;
-            } else {
-                s->thr_ipending = 0;
+            if (changed & UART_IER_THRI) {
+                if ((s->ier & UART_IER_THRI) && (s->lsr & UART_LSR_THRE)) {
+                    s->thr_ipending = 1;
+                } else {
+                    s->thr_ipending = 0;
+                }
+            }
+
+            if (changed) {
+                serial_update_irq(s);
             }
-            serial_update_irq(s);
         }
         break;
     case 2:
--
1.8.3.1
SOURCES/kvm-serial-poll-the-serial-console-with-G_IO_HUP.patch
New file
@@ -0,0 +1,124 @@
From 3ca9dc028e21f6e66e4ad21d6b2948e23691d2ae Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:12 +0200
Subject: [PATCH 07/18] serial: poll the serial console with G_IO_HUP
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-8-famz@redhat.com>
Patchwork-id: 75363
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 07/18] serial: poll the serial console with G_IO_HUP
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Roger Pau Monne <roger.pau@citrix.com>
On FreeBSD polling a master pty while the other end is not connected
with G_IO_OUT only results in an endless wait. This is different from
the Linux behaviour, that returns immediately. In order to demonstrate
this, I have the following example code:
http://xenbits.xen.org/people/royger/test_poll.c
When executed on Linux:
$ ./test_poll
In callback
On FreeBSD instead, the callback never gets called:
$ ./test_poll
So, in order to workaround this, poll the source with G_IO_HUP (which
makes the code behave the same way on both Linux and FreeBSD).
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Cc: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Cc: Michael Tokarev <mjt@tls.msk.ru>
Cc: "Andreas Färber" <afaerber@suse.de>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: xen-devel@lists.xenproject.org
[Add hw/char/cadence_uart.c too. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit e02bc6de30c44fd668dc0d6e1cd1804f2eed3ed3)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
    hw/char/cadence_uart.c
Downstream doesn't use qemu_chr_fe_add_watch because we don't have
38acd64b1c etc.
    monitor.c
The changed line is different because we don't have 6cff3e8594 (monitor:
protect outbuf and mux_out with mutex).
---
 hw/char/serial.c         | 2 +-
 hw/char/virtio-console.c | 3 ++-
 hw/usb/redirect.c        | 2 +-
 monitor.c                | 2 +-
 4 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index e020b0e..add4738 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -246,7 +246,7 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
         serial_receive1(s, &s->tsr, 1);
     } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
         if (s->tsr_retry >= 0 && s->tsr_retry < MAX_XMIT_RETRY &&
-            qemu_chr_fe_add_watch(s->chr, G_IO_OUT, serial_xmit, s) > 0) {
+            qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP, serial_xmit, s) > 0) {
             s->tsr_retry++;
             return FALSE;
         }
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index 1b01dcd..69dd95a 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -66,7 +66,8 @@ static ssize_t flush_buf(VirtIOSerialPort *port,
         if (!k->is_console) {
             virtio_serial_throttle_port(port, true);
             if (!vcon->watch) {
-                vcon->watch = qemu_chr_fe_add_watch(vcon->chr, G_IO_OUT,
+                vcon->watch = qemu_chr_fe_add_watch(vcon->chr,
+                                                    G_IO_OUT|G_IO_HUP,
                                                     chr_write_unblocked, vcon);
             }
         }
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index e3b9f32..3fe2106 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -284,7 +284,7 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
     r = qemu_chr_fe_write(dev->cs, data, count);
     if (r < count) {
         if (!dev->watch) {
-            dev->watch = qemu_chr_fe_add_watch(dev->cs, G_IO_OUT,
+            dev->watch = qemu_chr_fe_add_watch(dev->cs, G_IO_OUT|G_IO_HUP,
                                                usbredir_write_unblocked, dev);
         }
         if (r < 0) {
diff --git a/monitor.c b/monitor.c
index 1b28ff3..393a508 100644
--- a/monitor.c
+++ b/monitor.c
@@ -300,7 +300,7 @@ void monitor_flush(Monitor *mon)
             mon->outbuf = tmp;
         }
         if (mon->watch == 0) {
-            mon->watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT,
+            mon->watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT|G_IO_HUP,
                                                monitor_unblocked, mon);
         }
     }
--
1.8.3.1
SOURCES/kvm-serial-remove-watch-on-reset.patch
New file
@@ -0,0 +1,87 @@
From ac39e63d788b8bcb748f08347312b0fccde7ce0e Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:23 +0200
Subject: [PATCH 18/18] serial: remove watch on reset
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-19-famz@redhat.com>
Patchwork-id: 75373
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 18/18] serial: remove watch on reset
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
Otherwise, this can cause serial_xmit to be entered with LSR.TEMT=0,
which is invalid and causes an assertion failure.
Reported-by: Bret Ketchum <bcketchum@gmail.com>
Tested-by: Bret Ketchum <bcketchum@gmail.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit a1df76da57aa8772a75e7c49f8e3829d07b4c46c)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/char/serial.c         | 16 ++++++++++++----
 include/hw/char/serial.h |  1 +
 2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 69fefb2..39de1ca 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -224,6 +224,7 @@ static gboolean serial_watch_cb(GIOChannel *chan, GIOCondition cond,
                                 void *opaque)
 {
     SerialState *s = opaque;
+    s->watch_tag = 0;
     serial_xmit(s);
     return FALSE;
 }
@@ -254,10 +255,12 @@ static void serial_xmit(SerialState *s)
         if (s->mcr & UART_MCR_LOOP) {
             /* in loopback mode, say that we just received a char */
             serial_receive1(s, &s->tsr, 1);
-        } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
-            if (s->tsr_retry < MAX_XMIT_RETRY &&
-                qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
-                                      serial_watch_cb, s) > 0) {
+        } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1 &&
+                   s->tsr_retry < MAX_XMIT_RETRY) {
+            assert(s->watch_tag == 0);
+            s->watch_tag = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
+                                                 serial_watch_cb, s);
+            if (s->watch_tag > 0) {
                 s->tsr_retry++;
                 return;
             }
@@ -656,6 +659,11 @@ static void serial_reset(void *opaque)
 {
     SerialState *s = opaque;
+    if (s->watch_tag > 0) {
+        g_source_remove(s->watch_tag);
+        s->watch_tag = 0;
+    }
+
     s->rbr = 0;
     s->ier = 0;
     s->iir = UART_IIR_NO_INT;
diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h
index 2661f8c..19c7763 100644
--- a/include/hw/char/serial.h
+++ b/include/hw/char/serial.h
@@ -56,6 +56,7 @@ struct SerialState {
     int it_shift;
     int baudbase;
     uint32_t tsr_retry;
+    guint watch_tag;
     uint32_t wakeup;
     /* Time when the last byte was successfully sent out of the tsr */
--
1.8.3.1
SOURCES/kvm-serial-reset-thri_pending-on-IER-writes-with-THRI-0.patch
New file
@@ -0,0 +1,85 @@
From 6d2a5ef7994e753197bb9653872601db4e6cff5d Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:16 +0200
Subject: [PATCH 11/18] serial: reset thri_pending on IER writes with THRI=0
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-12-famz@redhat.com>
Patchwork-id: 75365
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 11/18] serial: reset thri_pending on IER writes with THRI=0
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
This is responsible for failure of migration from 2.2 to 2.1, because
thr_ipending is always one in practice.
serial.c is setting thr_ipending unconditionally.  However, thr_ipending
is not used at all if THRI=0, and it will be overwritten again the next
time THRE or THRI changes.  For that reason, we can set thr_ipending to
zero every time THRI is reset.
There is disagreement on whether LSR.THRE should be resampled when IER.THRI
goes from 1 to 1.  This patch does not touch the code, leaving that for
QEMU 2.3+.
This has no semantic change and is enough to fix migration in the common
case where the interrupt is not pending or is reported in IIR.  It does not
change the migration format, so 2.2.0 -> 2.1 will remain broken but we
can fix 2.2.1 -> 2.1 without breaking 2.2.1 <-> 2.2.0.
The case that remains broken (the one in which the subsection is strictly
necessary) is when THRE=1, the THRI interrupt has *not* been acknowledged
yet, and a higher-priority interrupt comes.  In this case, you need the
subsection to tell the source that the lower-priority THRI interrupt is
pending.  The subsection's breakage of migration, in this case, prevents
continuing the VM on the destination with an invalid state.
Cc: qemu-stable@nongnu.org
Reported-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 4e02b0fcf5c97579d0d3261c80c65abcf92870fe)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/char/serial.c | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 5ef9b95..15c628f 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -320,10 +320,24 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
                      s->poll_msl = 0;
                 }
             }
-            if (s->lsr & UART_LSR_THRE) {
+
+            /* Turning on the THRE interrupt on IER can trigger the interrupt
+             * if LSR.THRE=1, even if it had been masked before by reading IIR.
+             * This is not in the datasheet, but Windows relies on it.  It is
+             * unclear if THRE has to be resampled every time THRI becomes
+             * 1, or only on the rising edge.  Bochs does the latter, and Windows
+             * always toggles IER to all zeroes and back to all ones.  But for
+             * now leave it as it has always been in QEMU.
+             *
+             * If IER.THRI is zero, thr_ipending is not used.  Set it to zero
+             * so that the thr_ipending subsection is not migrated.
+             */
+            if ((s->ier & UART_IER_THRI) && (s->lsr & UART_LSR_THRE)) {
                 s->thr_ipending = 1;
-                serial_update_irq(s);
+            } else {
+                s->thr_ipending = 0;
             }
+            serial_update_irq(s);
         }
         break;
     case 2:
--
1.8.3.1
SOURCES/kvm-serial-separate-serial_xmit-and-serial_watch_cb.patch
New file
@@ -0,0 +1,102 @@
From 2600e8a94c5434d07e820c7cf5bcd62d69849099 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:22 +0200
Subject: [PATCH 17/18] serial: separate serial_xmit and serial_watch_cb
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-18-famz@redhat.com>
Patchwork-id: 75368
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 17/18] serial: separate serial_xmit and serial_watch_cb
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
serial_xmit starts transmission of whatever is in the transmitter
register, THR or FIFO; serial_watch_cb is a wrapper around it and is
only used as a qemu_chr_fe_add_watch callback.
Tested-by: Bret Ketchum <bcketchum@gmail.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit b0585e7e07982daa578c3bfef7f6843c89f110a8)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
    hw/char/serial.c
Contextual conflict because the surrounding migration code around the
touched functions is different.
---
 hw/char/serial.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index fdda802..69fefb2 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -104,6 +104,7 @@ do {} while (0)
 #endif
 static void serial_receive1(void *opaque, const uint8_t *buf, int size);
+static void serial_xmit(SerialState *s);
 static inline void recv_fifo_put(SerialState *s, uint8_t chr)
 {
@@ -219,10 +220,16 @@ static void serial_update_msl(SerialState *s)
         qemu_mod_timer(s->modem_status_poll, qemu_get_clock_ns(vm_clock) + get_ticks_per_sec() / 100);
 }
-static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
+static gboolean serial_watch_cb(GIOChannel *chan, GIOCondition cond,
+                                void *opaque)
 {
     SerialState *s = opaque;
+    serial_xmit(s);
+    return FALSE;
+}
+static void serial_xmit(SerialState *s)
+{
     do {
         assert(!(s->lsr & UART_LSR_TEMT));
         if (s->tsr_retry == 0) {
@@ -250,9 +257,9 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
         } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1) {
             if (s->tsr_retry < MAX_XMIT_RETRY &&
                 qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
-                                      serial_xmit, s) > 0) {
+                                      serial_watch_cb, s) > 0) {
                 s->tsr_retry++;
-                return FALSE;
+                return;
             }
         }
         s->tsr_retry = 0;
@@ -263,11 +270,8 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
     s->last_xmit_ts = qemu_get_clock_ns(vm_clock);
     s->lsr |= UART_LSR_TEMT;
-
-    return FALSE;
 }
-
 static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
                                 unsigned size)
 {
@@ -295,7 +299,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
             s->lsr &= ~UART_LSR_TEMT;
             serial_update_irq(s);
             if (s->tsr_retry == 0) {
-                serial_xmit(NULL, G_IO_OUT, s);
+                serial_xmit(s);
             }
         }
         break;
--
1.8.3.1
SOURCES/kvm-serial-simplify-tsr_retry-reset.patch
New file
@@ -0,0 +1,49 @@
From 4a5819d1786be74df4b2393f72d6901e05d0eb4a Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:21 +0200
Subject: [PATCH 16/18] serial: simplify tsr_retry reset
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-17-famz@redhat.com>
Patchwork-id: 75372
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 16/18] serial: simplify tsr_retry reset
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
Move common code outside the if, and reset tsr_retry even in loopback mode.
Right now it cannot become non-zero, but it will be possible as soon as
we start respecting the baud rate.
Tested-by: Bret Ketchum <bcketchum@gmail.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit bce933b85a34514fe34fa559be1d8ccd1f39f954)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/char/serial.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index afa1932..fdda802 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -254,10 +254,8 @@ static gboolean serial_xmit(GIOChannel *chan, GIOCondition cond, void *opaque)
                 s->tsr_retry++;
                 return FALSE;
             }
-            s->tsr_retry = 0;
-        } else {
-            s->tsr_retry = 0;
         }
+        s->tsr_retry = 0;
         /* Transmit another byte if it is already available. It is only
            possible when FIFO is enabled and not empty. */
--
1.8.3.1
SOURCES/kvm-serial-update-LSR-on-enabling-disabling-FIFOs.patch
New file
@@ -0,0 +1,63 @@
From 727ebf3f24a6f519aab1306bad6e63014c76aec5 Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Fri, 19 May 2017 00:35:18 +0200
Subject: [PATCH 13/18] serial: update LSR on enabling/disabling FIFOs
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170519003523.21163-14-famz@redhat.com>
Patchwork-id: 75369
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 13/18] serial: update LSR on enabling/disabling FIFOs
Bugzilla: 1452332
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
From: Paolo Bonzini <pbonzini@redhat.com>
When the transmit FIFO is emptied or enabled, the transmitter
hold register is empty.  When it is disabled, it is also emptied and
in addition the previous contents of the transmitter hold register
are discarded.  In either case, the THRE bit in LSR must be set and
THRI raised.
When the receive FIFO is emptied or enabled, the data ready and break
bits must be cleared in LSR.  Likewise when the receive FIFO is disabled.
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
(cherry picked from commit 023c3a9707d0d9259a1e858cdf7804dd10973fca)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
Conflicts:
    hw/char/serial.c
Contextual conflict because upstream uses new timer API timer_del while
downstream still uses qemu_del_timer.
---
 hw/char/serial.c | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/hw/char/serial.c b/hw/char/serial.c
index c2be4bd..e0d29a8 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -351,12 +351,15 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
         /* FIFO clear */
         if (val & UART_FCR_RFR) {
+            s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
             qemu_del_timer(s->fifo_timeout_timer);
             s->timeout_ipending=0;
             fifo8_reset(&s->recv_fifo);
         }
         if (val & UART_FCR_XFR) {
+            s->lsr |= UART_LSR_THRE;
+            s->thr_ipending = 1;
             fifo8_reset(&s->xmit_fifo);
         }
--
1.8.3.1
SOURCES/kvm-spice-fix-spice_chr_add_watch-pre-condition.patch
New file
@@ -0,0 +1,49 @@
From 9b379db2f11257f5ef88979fdf9660eaa0ad6b4b Mon Sep 17 00:00:00 2001
From: Fam Zheng <famz@redhat.com>
Date: Tue, 6 Jun 2017 06:16:56 +0200
Subject: [PATCH] spice: fix spice_chr_add_watch() pre-condition
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Fam Zheng <famz@redhat.com>
Message-id: <20170606061656.29212-2-famz@redhat.com>
Patchwork-id: 75488
O-Subject: [RHEL-7.3.z qemu-kvm PATCH 1/1] spice: fix spice_chr_add_watch() pre-condition
Bugzilla: 1452332
RH-Acked-by: John Snow <jsnow@redhat.com>
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
From: Marc-André Lureau <marcandre.lureau@gmail.com>
Since e02bc6de30c44fd668dc0d6e1cd1804f2eed3ed3, add_watch() is called
with G_IO_HUP. Even if spice-qemu-char ignores this flag, the
precondition must be changed.
https://bugzilla.redhat.com/show_bug.cgi?id=1128992
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit f7a8beb5e6a13dc924895244777d9ef08b23b367)
Signed-off-by: Fam Zheng <famz@redhat.com>
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 spice-qemu-char.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 6d147a7..079c214 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -171,7 +171,7 @@ static GSource *spice_chr_add_watch(CharDriverState *chr, GIOCondition cond)
     SpiceCharDriver *scd = chr->opaque;
     SpiceCharSource *src;
-    assert(cond == G_IO_OUT);
+    assert(cond & G_IO_OUT);
     src = (SpiceCharSource *)g_source_new(&SpiceCharSourceFuncs,
                                           sizeof(SpiceCharSource));
--
1.8.3.1
SPECS/qemu-kvm.spec
@@ -76,7 +76,7 @@
Summary: QEMU is a FAST! processor emulator
Name: %{pkgname}%{?pkgsuffix}
Version: 1.5.3
Release: 126%{?dist}.6
Release: 126%{?dist}.9
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
Epoch: 10
License: GPLv2+ and LGPLv2+ and BSD
@@ -3446,6 +3446,46 @@
Patch1694: kvm-cirrus-stop-passing-around-src-pointers-in-the-blitt.patch
# For bz#1430059 - CVE-2016-9603 qemu-kvm: Qemu: cirrus: heap buffer overflow via vnc connection [rhel-7.3.z]
Patch1695: kvm-cirrus-fix-off-by-one-in-cirrus_bitblt_rop_bkwd_tran.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1696: kvm-char-serial-cosmetic-fixes.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1697: kvm-char-serial-Use-generic-Fifo8.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1698: kvm-char-serial-serial_ioport_write-Factor-out-common-co.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1699: kvm-char-serial-fix-copy-paste-error-fifo8_is_full-vs-em.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1700: kvm-char-serial-Fix-emptyness-check.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1701: kvm-char-serial-Fix-emptyness-handling.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1702: kvm-serial-poll-the-serial-console-with-G_IO_HUP.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1703: kvm-serial-change-retry-logic-to-avoid-concurrency.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1704: kvm-qemu-char-ignore-flow-control-if-a-PTY-s-slave-is-no.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1705: kvm-serial-check-if-backed-by-a-physical-serial-port-at-.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1706: kvm-serial-reset-thri_pending-on-IER-writes-with-THRI-0.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1707: kvm-serial-clean-up-THRE-TEMT-handling.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1708: kvm-serial-update-LSR-on-enabling-disabling-FIFOs.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1709: kvm-serial-only-resample-THR-interrupt-on-rising-edge-of.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1710: kvm-serial-make-tsr_retry-unsigned.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1711: kvm-serial-simplify-tsr_retry-reset.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1712: kvm-serial-separate-serial_xmit-and-serial_watch_cb.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1713: kvm-serial-remove-watch-on-reset.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1714: kvm-char-change-qemu_chr_fe_add_watch-to-return-unsigned.patch
# For bz#1452332 - RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop
Patch1715: kvm-spice-fix-spice_chr_add_watch-pre-condition.patch
BuildRequires: zlib-devel
@@ -5321,6 +5361,26 @@
%patch1693 -p1
%patch1694 -p1
%patch1695 -p1
%patch1696 -p1
%patch1697 -p1
%patch1698 -p1
%patch1699 -p1
%patch1700 -p1
%patch1701 -p1
%patch1702 -p1
%patch1703 -p1
%patch1704 -p1
%patch1705 -p1
%patch1706 -p1
%patch1707 -p1
%patch1708 -p1
%patch1709 -p1
%patch1710 -p1
%patch1711 -p1
%patch1712 -p1
%patch1713 -p1
%patch1714 -p1
%patch1715 -p1
%build
buildarch="%{kvm_target}-softmmu"
@@ -5766,6 +5826,38 @@
%{_mandir}/man8/qemu-nbd.8*
%changelog
* Tue Jun 06 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.9
- kvm-spice-fix-spice_chr_add_watch-pre-condition.patch [bz#1452332]
- Resolves: bz#1452332
  (RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop)
* Wed May 24 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.8
- kvm-char-change-qemu_chr_fe_add_watch-to-return-unsigned.patch [bz#1452332]
- Resolves: bz#1452332
  (RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop)
* Mon May 22 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.7
- kvm-char-serial-cosmetic-fixes.patch [bz#1452332]
- kvm-char-serial-Use-generic-Fifo8.patch [bz#1452332]
- kvm-char-serial-serial_ioport_write-Factor-out-common-co.patch [bz#1452332]
- kvm-char-serial-fix-copy-paste-error-fifo8_is_full-vs-em.patch [bz#1452332]
- kvm-char-serial-Fix-emptyness-check.patch [bz#1452332]
- kvm-char-serial-Fix-emptyness-handling.patch [bz#1452332]
- kvm-serial-poll-the-serial-console-with-G_IO_HUP.patch [bz#1452332]
- kvm-serial-change-retry-logic-to-avoid-concurrency.patch [bz#1452332]
- kvm-qemu-char-ignore-flow-control-if-a-PTY-s-slave-is-no.patch [bz#1452332]
- kvm-serial-check-if-backed-by-a-physical-serial-port-at-.patch [bz#1452332]
- kvm-serial-reset-thri_pending-on-IER-writes-with-THRI-0.patch [bz#1452332]
- kvm-serial-clean-up-THRE-TEMT-handling.patch [bz#1452332]
- kvm-serial-update-LSR-on-enabling-disabling-FIFOs.patch [bz#1452332]
- kvm-serial-only-resample-THR-interrupt-on-rising-edge-of.patch [bz#1452332]
- kvm-serial-make-tsr_retry-unsigned.patch [bz#1452332]
- kvm-serial-simplify-tsr_retry-reset.patch [bz#1452332]
- kvm-serial-separate-serial_xmit-and-serial_watch_cb.patch [bz#1452332]
- kvm-serial-remove-watch-on-reset.patch [bz#1452332]
- Resolves: bz#1452332
  (RHEL 7.2 based VM (Virtual Machine) hung for several hours apparently waiting for lock held by main_loop)
* Fri Mar 24 2017 Miroslav Rezanina <mrezanin@redhat.com> - 1.5.3-126.el7_3.6
- kvm-fix-cirrus_vga-fix-OOB-read-case-qemu-Segmentation-f.patch [bz#1430059]
- kvm-cirrus-vnc-zap-bitblit-support-from-console-code.patch [bz#1430059]