yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
76daa3
From fbe69a4c6ee947f375ac5b2572e0fc4ea9763095 Mon Sep 17 00:00:00 2001
76daa3
From: "sjubran@redhat.com" <sjubran@redhat.com>
76daa3
Date: Tue, 23 May 2017 14:35:59 +0200
76daa3
Subject: [PATCH 1/6] e1000e: Fix ICR "Other" causes clear logic
76daa3
76daa3
RH-Author: sjubran@redhat.com
76daa3
Message-id: <20170523143559.28622-1-sjubran@redhat.com>
76daa3
Patchwork-id: 75399
76daa3
O-Subject: [PATCH] e1000e: Fix ICR "Other" causes clear logic
76daa3
Bugzilla: 1449490
76daa3
RH-Acked-by: Dmitry Fleytman <dfleytma@redhat.com>
76daa3
RH-Acked-by: Vlad Yasevich <vyasevic@redhat.com>
76daa3
RH-Acked-by: Xiao Wang <jasowang@redhat.com>
76daa3
76daa3
From: Sameeh Jubran <sameeh@daynix.com>
76daa3
76daa3
BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1449490
76daa3
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=13256116
76daa3
upstream: maintainer's tree
76daa3
76daa3
This commit fixes a bug which causes the guest to hang. The bug was
76daa3
observed upon a "receive overrun" (bit #6 of the ICR register)
76daa3
interrupt which could be triggered post migration in a heavy traffic
76daa3
environment. Even though the "receive overrun" bit (#6) is masked out
76daa3
by the IMS register (refer to the log below) the driver still receives
76daa3
an interrupt as the "receive overrun" bit (#6) causes the "Other" -
76daa3
bit #24 of the ICR register - bit to be set as documented below. The
76daa3
driver handles the interrupt and clears the "Other" bit (#24) but
76daa3
doesn't clear the "receive overrun" bit (#6) which leads to an
76daa3
infinite loop. Apparently the Windows driver expects that the "receive
76daa3
overrun" bit and other ones - documented below - to be cleared when
76daa3
the "Other" bit (#24) is cleared.
76daa3
76daa3
So to sum that up:
76daa3
1. Bit #6 of the ICR register is set by heavy traffic
76daa3
2. As a results of setting bit #6, bit #24 is set
76daa3
3. The driver receives an interrupt for bit 24 (it doesn't receieve an
76daa3
   interrupt for bit #6 as it is masked out by IMS)
76daa3
4. The driver handles and clears the interrupt of bit #24
76daa3
5. Bit #6 is still set.
76daa3
6. 2 happens all over again
76daa3
76daa3
The Interrupt Cause Read - ICR register:
76daa3
76daa3
The ICR has the "Other" bit - bit #24 - that is set when one or more
76daa3
of the following ICR register's bits are set:
76daa3
76daa3
LSC - bit #2, RXO - bit #6, MDAC - bit #9, SRPD - bit #16, ACK - bit
76daa3
76daa3
This bug can occur with any of these bits depending on the driver's
76daa3
behaviour and the way it configures the device. However, trying to
76daa3
reproduce it with any bit other than RX0 is challenging and came to
76daa3
failure as the drivers don't implement most of these bits, trying to
76daa3
reproduce it with LSC (Link Status Change - bit #2) bit didn't succeed
76daa3
too as it seems that Windows handles this bit differently.
76daa3
76daa3
Log sample of the storm:
76daa3
76daa3
27563@1494850819.411877:e1000e_irq_pending_interrupts ICR PENDING: 0x1000000 (ICR: 0x815000c2, IMS: 0x1a00004)
76daa3
27563@1494850819.411900:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
76daa3
27563@1494850819.411915:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
76daa3
27563@1494850819.412380:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
76daa3
27563@1494850819.412395:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
76daa3
27563@1494850819.412436:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
76daa3
27563@1494850819.412441:e1000e_irq_pending_interrupts ICR PENDING: 0x0 (ICR: 0x815000c2, IMS: 0xa00004)
76daa3
27563@1494850819.412998:e1000e_irq_pending_interrupts ICR PENDING: 0x1000000 (ICR: 0x815000c2, IMS: 0x1a00004)
76daa3
76daa3
* This bug behaviour wasn't observed with the Linux driver.
76daa3
76daa3
This commit solves:
76daa3
https://bugzilla.redhat.com/show_bug.cgi?id=1447935
76daa3
https://bugzilla.redhat.com/show_bug.cgi?id=1449490
76daa3
76daa3
Cc: qemu-stable@nongnu.org
76daa3
Signed-off-by: Sameeh Jubran <sjubran@redhat.com>
76daa3
Signed-off-by: Jason Wang <jasowang@redhat.com>
76daa3
(cherry picked from commit 82342e91b60a4a078811df4e1a545e57abffa11d)
76daa3
Signed-off-by: Sameeh Jubran <sjubran@redhat.com>
76daa3
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
76daa3
---
76daa3
 hw/net/e1000e_core.c | 10 ++++++++--
76daa3
 1 file changed, 8 insertions(+), 2 deletions(-)
76daa3
76daa3
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
76daa3
index 28c5be1..8140564 100644
76daa3
--- a/hw/net/e1000e_core.c
76daa3
+++ b/hw/net/e1000e_core.c
76daa3
@@ -2454,14 +2454,20 @@ e1000e_set_ics(E1000ECore *core, int index, uint32_t val)
76daa3
 static void
76daa3
 e1000e_set_icr(E1000ECore *core, int index, uint32_t val)
76daa3
 {
76daa3
+    uint32_t icr = 0;
76daa3
     if ((core->mac[ICR] & E1000_ICR_ASSERTED) &&
76daa3
         (core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME)) {
76daa3
         trace_e1000e_irq_icr_process_iame();
76daa3
         e1000e_clear_ims_bits(core, core->mac[IAM]);
76daa3
     }
76daa3
 
76daa3
-    trace_e1000e_irq_icr_write(val, core->mac[ICR], core->mac[ICR] & ~val);
76daa3
-    core->mac[ICR] &= ~val;
76daa3
+    icr = core->mac[ICR] & ~val;
76daa3
+    /* Windows driver expects that the "receive overrun" bit and other
76daa3
+     * ones to be cleared when the "Other" bit (#24) is cleared.
76daa3
+     */
76daa3
+    icr = (val & E1000_ICR_OTHER) ? (icr & ~E1000_ICR_OTHER_CAUSES) : icr;
76daa3
+    trace_e1000e_irq_icr_write(val, core->mac[ICR], icr);
76daa3
+    core->mac[ICR] = icr;
76daa3
     e1000e_update_interrupt_state(core);
76daa3
 }
76daa3
 
76daa3
-- 
76daa3
1.8.3.1
76daa3