|
|
9ae3a8 |
From 09ff2706109ce647d1fe59e99f44f96810d80b7c Mon Sep 17 00:00:00 2001
|
|
|
9ae3a8 |
From: Fam Zheng <famz@redhat.com>
|
|
|
9ae3a8 |
Date: Thu, 18 May 2017 09:21:24 +0200
|
|
|
9ae3a8 |
Subject: [PATCH 11/18] serial: reset thri_pending on IER writes with THRI=0
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
RH-Author: Fam Zheng <famz@redhat.com>
|
|
|
9ae3a8 |
Message-id: <20170518092131.16571-12-famz@redhat.com>
|
|
|
9ae3a8 |
Patchwork-id: 75302
|
|
|
9ae3a8 |
O-Subject: [RHEL-7.4 qemu-kvm PATCH v3 11/18] serial: reset thri_pending on IER writes with THRI=0
|
|
|
9ae3a8 |
Bugzilla: 1451470
|
|
|
9ae3a8 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
|
9ae3a8 |
RH-Acked-by: Eduardo Habkost <ehabkost@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
This is responsible for failure of migration from 2.2 to 2.1, because
|
|
|
9ae3a8 |
thr_ipending is always one in practice.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
serial.c is setting thr_ipending unconditionally. However, thr_ipending
|
|
|
9ae3a8 |
is not used at all if THRI=0, and it will be overwritten again the next
|
|
|
9ae3a8 |
time THRE or THRI changes. For that reason, we can set thr_ipending to
|
|
|
9ae3a8 |
zero every time THRI is reset.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
There is disagreement on whether LSR.THRE should be resampled when IER.THRI
|
|
|
9ae3a8 |
goes from 1 to 1. This patch does not touch the code, leaving that for
|
|
|
9ae3a8 |
QEMU 2.3+.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
This has no semantic change and is enough to fix migration in the common
|
|
|
9ae3a8 |
case where the interrupt is not pending or is reported in IIR. It does not
|
|
|
9ae3a8 |
change the migration format, so 2.2.0 -> 2.1 will remain broken but we
|
|
|
9ae3a8 |
can fix 2.2.1 -> 2.1 without breaking 2.2.1 <-> 2.2.0.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
The case that remains broken (the one in which the subsection is strictly
|
|
|
9ae3a8 |
necessary) is when THRE=1, the THRI interrupt has *not* been acknowledged
|
|
|
9ae3a8 |
yet, and a higher-priority interrupt comes. In this case, you need the
|
|
|
9ae3a8 |
subsection to tell the source that the lower-priority THRI interrupt is
|
|
|
9ae3a8 |
pending. The subsection's breakage of migration, in this case, prevents
|
|
|
9ae3a8 |
continuing the VM on the destination with an invalid state.
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
Cc: qemu-stable@nongnu.org
|
|
|
9ae3a8 |
Reported-by: Igor Mammedov <imammedo@redhat.com>
|
|
|
9ae3a8 |
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
9ae3a8 |
(cherry picked from commit 4e02b0fcf5c97579d0d3261c80c65abcf92870fe)
|
|
|
9ae3a8 |
Signed-off-by: Fam Zheng <famz@redhat.com>
|
|
|
9ae3a8 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
9ae3a8 |
---
|
|
|
9ae3a8 |
hw/char/serial.c | 18 ++++++++++++++++--
|
|
|
9ae3a8 |
1 file changed, 16 insertions(+), 2 deletions(-)
|
|
|
9ae3a8 |
|
|
|
9ae3a8 |
diff --git a/hw/char/serial.c b/hw/char/serial.c
|
|
|
9ae3a8 |
index 5ef9b95..15c628f 100644
|
|
|
9ae3a8 |
--- a/hw/char/serial.c
|
|
|
9ae3a8 |
+++ b/hw/char/serial.c
|
|
|
9ae3a8 |
@@ -320,10 +320,24 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
|
|
|
9ae3a8 |
s->poll_msl = 0;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
- if (s->lsr & UART_LSR_THRE) {
|
|
|
9ae3a8 |
+
|
|
|
9ae3a8 |
+ /* Turning on the THRE interrupt on IER can trigger the interrupt
|
|
|
9ae3a8 |
+ * if LSR.THRE=1, even if it had been masked before by reading IIR.
|
|
|
9ae3a8 |
+ * This is not in the datasheet, but Windows relies on it. It is
|
|
|
9ae3a8 |
+ * unclear if THRE has to be resampled every time THRI becomes
|
|
|
9ae3a8 |
+ * 1, or only on the rising edge. Bochs does the latter, and Windows
|
|
|
9ae3a8 |
+ * always toggles IER to all zeroes and back to all ones. But for
|
|
|
9ae3a8 |
+ * now leave it as it has always been in QEMU.
|
|
|
9ae3a8 |
+ *
|
|
|
9ae3a8 |
+ * If IER.THRI is zero, thr_ipending is not used. Set it to zero
|
|
|
9ae3a8 |
+ * so that the thr_ipending subsection is not migrated.
|
|
|
9ae3a8 |
+ */
|
|
|
9ae3a8 |
+ if ((s->ier & UART_IER_THRI) && (s->lsr & UART_LSR_THRE)) {
|
|
|
9ae3a8 |
s->thr_ipending = 1;
|
|
|
9ae3a8 |
- serial_update_irq(s);
|
|
|
9ae3a8 |
+ } else {
|
|
|
9ae3a8 |
+ s->thr_ipending = 0;
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
+ serial_update_irq(s);
|
|
|
9ae3a8 |
}
|
|
|
9ae3a8 |
break;
|
|
|
9ae3a8 |
case 2:
|
|
|
9ae3a8 |
--
|
|
|
9ae3a8 |
1.8.3.1
|
|
|
9ae3a8 |
|