26ba25
From 6bbba130993de09d0623eafe648b978351cb49f9 Mon Sep 17 00:00:00 2001
26ba25
From: Xiao Wang <jasowang@redhat.com>
26ba25
Date: Thu, 16 Aug 2018 08:17:07 +0100
26ba25
Subject: [PATCH 2/4] e1000e: Prevent MSI/MSI-X storms
26ba25
26ba25
RH-Author: Xiao Wang <jasowang@redhat.com>
26ba25
Message-id: <1534407427-44794-3-git-send-email-jasowang@redhat.com>
26ba25
Patchwork-id: 81853
26ba25
O-Subject: [RHEL-8.0 qemu-kvm PATCH 2/2] e1000e: Prevent MSI/MSI-X storms
26ba25
Bugzilla: 1596024
26ba25
RH-Acked-by: wexu@redhat.com
26ba25
RH-Acked-by: Thomas Huth <thuth@redhat.com>
26ba25
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
26ba25
26ba25
From: Jan Kiszka <jan.kiszka@siemens.com>
26ba25
26ba25
Only signal MSI/MSI-X events on rising edges. So far we re-triggered the
26ba25
interrupt sources even if the guest did no consumed the pending one,
26ba25
easily causing interrupt storms.
26ba25
26ba25
Issue was observable with Linux 4.16 e1000e driver when MSI-X was used.
26ba25
Vector 2 was causing interrupt storms after the driver activated the
26ba25
device.
26ba25
26ba25
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
26ba25
Signed-off-by: Jason Wang <jasowang@redhat.com>
26ba25
(cherry picked from commit 4712c158c5276fd3c401152f4bb5c3fccf185946)
26ba25
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
26ba25
---
26ba25
 hw/net/e1000e_core.c | 11 +++++++++++
26ba25
 hw/net/e1000e_core.h |  2 ++
26ba25
 2 files changed, 13 insertions(+)
26ba25
26ba25
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
26ba25
index 9504891..2a221c2 100644
26ba25
--- a/hw/net/e1000e_core.c
26ba25
+++ b/hw/net/e1000e_core.c
26ba25
@@ -2023,6 +2023,7 @@ e1000e_msix_notify_one(E1000ECore *core, uint32_t cause, uint32_t int_cfg)
26ba25
     effective_eiac = core->mac[EIAC] & cause;
26ba25
 
26ba25
     core->mac[ICR] &= ~effective_eiac;
26ba25
+    core->msi_causes_pending &= ~effective_eiac;
26ba25
 
26ba25
     if (!(core->mac[CTRL_EXT] & E1000_CTRL_EXT_IAME)) {
26ba25
         core->mac[IMS] &= ~effective_eiac;
26ba25
@@ -2119,6 +2120,13 @@ e1000e_send_msi(E1000ECore *core, bool msix)
26ba25
 {
26ba25
     uint32_t causes = core->mac[ICR] & core->mac[IMS] & ~E1000_ICR_ASSERTED;
26ba25
 
26ba25
+    core->msi_causes_pending &= causes;
26ba25
+    causes ^= core->msi_causes_pending;
26ba25
+    if (causes == 0) {
26ba25
+        return;
26ba25
+    }
26ba25
+    core->msi_causes_pending |= causes;
26ba25
+
26ba25
     if (msix) {
26ba25
         e1000e_msix_notify(core, causes);
26ba25
     } else {
26ba25
@@ -2156,6 +2164,9 @@ e1000e_update_interrupt_state(E1000ECore *core)
26ba25
     core->mac[ICS] = core->mac[ICR];
26ba25
 
26ba25
     interrupts_pending = (core->mac[IMS] & core->mac[ICR]) ? true : false;
26ba25
+    if (!interrupts_pending) {
26ba25
+        core->msi_causes_pending = 0;
26ba25
+    }
26ba25
 
26ba25
     trace_e1000e_irq_pending_interrupts(core->mac[ICR] & core->mac[IMS],
26ba25
                                         core->mac[ICR], core->mac[IMS]);
26ba25
diff --git a/hw/net/e1000e_core.h b/hw/net/e1000e_core.h
26ba25
index 7d8ff41..63a1551 100644
26ba25
--- a/hw/net/e1000e_core.h
26ba25
+++ b/hw/net/e1000e_core.h
26ba25
@@ -109,6 +109,8 @@ struct E1000Core {
26ba25
     NICState *owner_nic;
26ba25
     PCIDevice *owner;
26ba25
     void (*owner_start_recv)(PCIDevice *d);
26ba25
+
26ba25
+    uint32_t msi_causes_pending;
26ba25
 };
26ba25
 
26ba25
 void
26ba25
-- 
26ba25
1.8.3.1
26ba25