From nobody Sun Nov 9 23:29:57 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1552461204823140.40284602067857; Wed, 13 Mar 2019 00:13:24 -0700 (PDT) Received: from localhost ([127.0.0.1]:39611 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h3y4n-0005UX-KZ for importer@patchew.org; Wed, 13 Mar 2019 03:13:21 -0400 Received: from eggs.gnu.org ([209.51.188.92]:60008) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1h3y2w-0004KT-Us for qemu-devel@nongnu.org; Wed, 13 Mar 2019 03:11:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1h3xpA-0008CP-Nq for qemu-devel@nongnu.org; Wed, 13 Mar 2019 02:57:13 -0400 Received: from mail.synology.com ([211.23.38.101]:39239 helo=synology.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1h3xp9-000807-Jj for qemu-devel@nongnu.org; Wed, 13 Mar 2019 02:57:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synology.com; s=123; t=1552460218; bh=mJGYaJPCbUKYgxZtfFLqkKwu4WNoiZCBniGDaW8559Y=; h=From:To:Cc:Subject:Date; b=P0JCHXybeEYkY/I3wt65hzW4ojJbwOLm7/MA+YEBeN5ShpgOktm1Pq+7mizBsA5RD YBQ3l7zs5waBWjhXdy4qzbhXpbZiMJx6rgw/5u/tZr4xWB9st2+hizRoQnF7Y8dUf6 mXjrFA8Nh41BK0ldrBLI4bccWSYFMOdPxj1pp+rs= To: qemu-devel@nongnu.org Date: Wed, 13 Mar 2019 06:56:49 +0000 Message-Id: <20190313065649.19067-1-yuchenlin@synology.com> X-Synology-MCP-Status: no X-Synology-Spam-Flag: no X-Synology-Spam-Status: score=0, required 6, WHITELIST_FROM_ADDRESS 0 X-Synology-Virus-Status: no X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 211.23.38.101 Subject: [Qemu-devel] [PATCH] e1000: Delay flush queue when receive RCTL X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: yuchenlin--- via Qemu-devel Reply-To: yuchenlin@synology.com Cc: jasowang@redhat.com, dmitry.fleytman@gmail.com, yuchenlin Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: yuchenlin Due to too early RCT0 interrput, win10x32 may hang on booting. This problem can be reproduced by doing power cycle on win10x32 guest. In our environment, we have 10 win10x32 and stress power cycle. The problem will happen about 20 rounds. Below shows some log with comment: The normal case: 22831@1551928392.984687:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 22831@1551928392.985655:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 22831@1551928392.985801:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: RCTL: 0, mac_reg[RCTL] =3D 0x0 22831@1551928393.056710:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: ICR read: 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: RCTL: 0, mac_reg[RCTL] =3D 0x0 22831@1551928393.077548:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: ICR read: 0 e1000: set_ics 2, ICR 0, IMR 0 e1000: set_ics 2, ICR 2, IMR 0 e1000: RCTL: 0, mac_reg[RCTL] =3D 0x0 22831@1551928393.102974:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 22831@1551928393.103267:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 e1000: RCTL: 255, mac_reg[RCTL] =3D 0x40002 <- win10x32 says it can handle RX now e1000: set_ics 0, ICR 2, IMR 9d <- unmask interrupt e1000: RCTL: 255, mac_reg[RCTL] =3D 0x48002 e1000: set_ics 80, ICR 2, IMR 9d <- interrupt and work! ... The bad case: 27744@1551930483.117766:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 27744@1551930483.118398:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: RCTL: 0, mac_reg[RCTL] =3D 0x0 27744@1551930483.198063:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: ICR read: 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: RCTL: 0, mac_reg[RCTL] =3D 0x0 27744@1551930483.218675:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 e1000: set_ics 0, ICR 0, IMR 0 e1000: ICR read: 0 e1000: set_ics 2, ICR 0, IMR 0 e1000: set_ics 2, ICR 2, IMR 0 e1000: RCTL: 0, mac_reg[RCTL] =3D 0x0 27744@1551930483.241768:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 27744@1551930483.241979:e1000x_rx_disabled Received packet dropped because receive is disabled RCTL =3D 0 e1000: RCTL: 255, mac_reg[RCTL] =3D 0x40002 <- win10x32 says it can handle RX now e1000: set_ics 80, ICR 2, IMR 0 <- flush queue (caused by setting RCTL) e1000: set_ics 0, ICR 82, IMR 9d <- unmask interrupt and because 0x82&0x9d !=3D 0 generate interrupt, hang on here... To workaround this problem, simply delay flush queue. Also stop receiving when timer is going to run. Tested on CentOS, Win7SP1x64 and Win10x32. Signed-off-by: yuchenlin Reviewed-by: Dmitry Fleytman > --- hw/net/e1000.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 5e144cb4e4..9b39bccfb2 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -120,6 +120,8 @@ typedef struct E1000State_st { bool mit_irq_level; /* Tracks interrupt pin level. */ uint32_t mit_ide; /* Tracks E1000_TXD_CMD_IDE bit. */ =20 + QEMUTimer *flush_queue_timer; + /* Compatibility flags for migration to/from qemu 1.3.0 and older */ #define E1000_FLAG_AUTONEG_BIT 0 #define E1000_FLAG_MIT_BIT 1 @@ -366,6 +368,7 @@ static void e1000_reset(void *opaque) =20 timer_del(d->autoneg_timer); timer_del(d->mit_timer); + timer_del(d->flush_queue_timer); d->mit_timer_on =3D 0; d->mit_irq_level =3D 0; d->mit_ide =3D 0; @@ -391,6 +394,14 @@ set_ctrl(E1000State *s, int index, uint32_t val) s->mac_reg[CTRL] =3D val & ~E1000_CTRL_RST; } =20 +static void +e1000_flush_queue_timer(void *opaque) +{ + E1000State *s =3D opaque; + + qemu_flush_queued_packets(qemu_get_queue(s->nic)); +} + static void set_rx_control(E1000State *s, int index, uint32_t val) { @@ -399,7 +410,8 @@ set_rx_control(E1000State *s, int index, uint32_t val) s->rxbuf_min_shift =3D ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1; DBGOUT(RX, "RCTL: %d, mac_reg[RCTL] =3D 0x%x\n", s->mac_reg[RDT], s->mac_reg[RCTL]); - qemu_flush_queued_packets(qemu_get_queue(s->nic)); + timer_mod(s->flush_queue_timer, + qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000); } =20 static void @@ -837,7 +849,7 @@ e1000_can_receive(NetClientState *nc) E1000State *s =3D qemu_get_nic_opaque(nc); =20 return e1000x_rx_ready(&s->parent_obj, s->mac_reg) && - e1000_has_rxbufs(s, 1); + e1000_has_rxbufs(s, 1) && !timer_pending(s->flush_queue_timer); } =20 static uint64_t rx_desc_base(E1000State *s) @@ -881,6 +893,10 @@ e1000_receive_iov(NetClientState *nc, const struct iov= ec *iov, int iovcnt) return -1; } =20 + if (timer_pending(s->flush_queue_timer)) { + return 0; + } + /* Pad to minimum Ethernet frame length */ if (size < sizeof(min_buf)) { iov_to_buf(iov, iovcnt, 0, min_buf, size); @@ -1637,6 +1653,8 @@ pci_e1000_uninit(PCIDevice *dev) timer_free(d->autoneg_timer); timer_del(d->mit_timer); timer_free(d->mit_timer); + timer_del(d->flush_queue_timer); + timer_free(d->flush_queue_timer); qemu_del_nic(d->nic); } =20 @@ -1700,6 +1718,8 @@ static void pci_e1000_realize(PCIDevice *pci_dev, Err= or **errp) =20 d->autoneg_timer =3D timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_ti= mer, d); d->mit_timer =3D timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d); + d->flush_queue_timer =3D timer_new_ms(QEMU_CLOCK_VIRTUAL, + e1000_flush_queue_timer, d); } =20 static void qdev_e1000_reset(DeviceState *dev) --=20 2.17.1