From nobody Mon Aug 31 15:27:04 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hYXsn5dHZz6qw5s for ; Mon, 31 Aug 2026 15:27:09 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hYXsn4plcz3q85 for ; Mon, 31 Aug 2026 15:27:09 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788190029; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=CAp1fX3Jx5Svi+4KWi/BfEWJMIO5bkUN9aXK8LfVw84=; b=YlwsFl+QSnZQhoSzQ9ZhXtM5Lfg9IHNNRuhsvyjkkSadGV/7n+aLtBDX9KSY3MvV4hBG+g oPSqbi3L5UsZKBc8vQKpipgbC+DRJ74Vtj/rp6MN7nsBhRtrD6Wta31uZtUArsnZEgNifI 2xW0t8Y5bf5jMu2cFqiEQBayLqn+PscNXljz519u9NGtw84ivc874mh3/ugXedlhJDJtmR 1Kj6DWCZqj9IpGFgB6Ibtt8cDtbh4sXAmJeBZb9piLYVw7C8nzrFugHFIZuoLXEgDFbxF7 gK0WbL/aNqBxgESwyy4C3w2fes6ehx9x4h2IAVZv/3nHKolI6mM7nOiLe7AHAg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788190029; a=rsa-sha256; cv=none; b=sq0NqjiDrtW5t70bQnBmuxJdIDIUnVf0OQxfwlVGyfDjU8AXcQrQRV0GfdpXyuBruVgFSL J+ScAHvfH/oPRbVKpVj/ksh9LWUPQelxaZU47JqNhqqZHdgx6mUno9LCRDT6KDmf8qk9BJ Q4A0/5LxqZ4jFik8hdU8uoJXDJAnShoXwDLMr5BXUjqeeepwsg8gjOfWweHPer0g/K9w1C 5MD8OKvSzfxuBvKqalwEUb7YLchduyo7fWKEolGOwkS9WDSV0zuS2LVp/zpmc9MBzZiRJZ YXJWO+LjleV1q8Kl50QrnOR9Qcl0oLja57ScYzsQ3ANkCMQpQ/V2qEGHxb8Oqw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788190029; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=CAp1fX3Jx5Svi+4KWi/BfEWJMIO5bkUN9aXK8LfVw84=; b=FI7cctduSNxmg0I5AYTzaxh6i5W+CA5T2S+mX6+PM7OWEwhV9AChQPOKxAO9RAsMw9viAZ 6EZDM1wSTmZ+TUn7dC8lMm4Xnw061tOmyVXHRfCsNgjtNmDya0e0V8aWjjdcNvqbiVsRze xXe/xrCYwXeCOdW/Vs1uW4VBRxBNWnEEwX8/QyndQUpMixvSKbtBzT+XoU4v8yTatTZ1y6 4l0ZoGifDiBZ6uOUM4yj7n0NV2CcnW/d5nuaEV1+czXlzL9QQ925Lj5fMNFjKsSaerr1Wq GY6fWgIPTobpHV8PFbTBEjrBRguY8QAYksnhvO3CsebRp4HW2RqDwWaxFQ7/jg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hYXsn3czwz2K7 for ; Mon, 31 Aug 2026 15:27:09 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 22cfa by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 31 Aug 2026 15:27:04 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 037d45a0526f - main - igbv: Fence DMA while sanitizing retained queues List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 037d45a0526f452d96f44059e88f735298a9063d Auto-Submitted: auto-generated Date: Mon, 31 Aug 2026 15:27:04 +0000 Message-Id: <6a959d48.22cfa.638e9833@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=037d45a0526f452d96f44059e88f735298a9063d commit 037d45a0526f452d96f44059e88f735298a9063d Author: Kevin Bowling AuthorDate: 2026-08-26 09:21:56 +0000 Commit: Kevin Bowling CommitDate: 2026-08-31 15:26:23 +0000 igbv: Fence DMA while sanitizing retained queues The 82576 and I350 retain VF queue enable and DMA address state across VFLR. iflib enables PCI bus mastering before driver attach, so stale state left by a previous owner can otherwise issue DMA before igbvf has completed its first reset and queue sanitization. Disable PCI bus mastering immediately after mapping the VF BAR. Keep it disabled until reset and queue sanitization succeed, verify both disable and enable through PCI command-register readback, and wait for pending transactions before treating the fence as complete. Resanitize on stop before iflib releases queue mappings. The sanitizer and recovery were exercised on I350 and 82576 VFs. Forced queue-disable failure left the VF down, and a later administrative down/up recovered it; successful I350 VFs passed bidirectional traffic with no errors or drops. Sponsored by: BBOX.io --- sys/dev/e1000/if_em.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++- sys/dev/e1000/if_em.h | 1 + sys/dev/e1000/if_igbv.c | 2 +- 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index e27b804a3cb4..97040cc49d94 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -429,6 +429,8 @@ static uint64_t em_if_get_vf_counter(if_ctx_t, ift_counter); static uint64_t em_if_get_counter(if_ctx_t, ift_counter); static void em_if_init(if_ctx_t); static void em_if_stop(if_ctx_t); +static void em_fence_pci_busmaster(struct e1000_softc *); +static int em_enable_pci_busmaster(struct e1000_softc *); static void em_if_media_status(if_ctx_t, struct ifmediareq *); static int em_if_media_change(if_ctx_t); static int em_if_mtu_set(if_ctx_t, uint32_t); @@ -1432,6 +1434,13 @@ em_if_attach_pre(if_ctx_t ctx) error = ENXIO; goto err_pci; } + /* + * A VF can retain queue enable bits and DMA addresses across VFLR. + * Fence bus mastering before the first mailbox reset so state left by + * a previous owner cannot issue DMA while the driver attaches. + */ + if (sc->vf_ifp) + em_fence_pci_busmaster(sc); /* * 82579 can lose a host CSR write while the Management Engine owns * the PCIm2PCI arbiter. Enable the OS register write interlock before @@ -1602,6 +1611,7 @@ em_if_attach_pre(if_ctx_t ctx) error == E1000_SUCCESS); if (error != E1000_SUCCESS) igbv_log_reset_failure(sc, error, true); + sc->vf_queues_sanitized = igbv_sanitize_queues(sc); } else if (error != E1000_SUCCESS) { device_printf(dev, "Hardware reset failed: %d\n", error); error = EIO; @@ -1952,6 +1962,7 @@ em_if_init(if_ctx_t ctx) * bounded callout retries initialization after iflib leaves the * failed initialization stopped. */ + em_fence_pci_busmaster(sc); igbv_queue_retry_failed(ctx); return; } @@ -1960,6 +1971,16 @@ em_if_init(if_ctx_t ctx) igbv_mbx_retry_failed(ctx); return; } + /* + * Keep a fail-closed device fenced until reset and VF queue + * sanitization have removed every stale DMA address. + */ + if (sc->vf_ifp && em_enable_pci_busmaster(sc) != 0) { + device_printf(sc->dev, + "Unable to enable PCI bus mastering\n"); + iflib_init_failed(ctx); + return; + } if (sc->vf_ifp) igbv_reconcile_mac(sc, ifp); /* Re-arm a link-up transition deferred for this reset. */ @@ -4028,6 +4049,65 @@ em_if_update_admin_status(if_ctx_t ctx) lem_smartspeed(sc); } +/* + * Last-resort DMA fence. iflib releases DMA mappings after the driver's + * stop callback, so continuing with bus mastering still enabled would turn + * a recoverable NIC failure into memory corruption. Treat failure of the + * PCI command bit as a fail-stop invariant violation. + */ +static void +em_fence_pci_busmaster(struct e1000_softc *sc) +{ + device_t dev; + u_int timeout; + u16 command; + int error; + + dev = sc->dev; + error = pci_disable_busmaster(dev); + command = pci_read_config(dev, PCIR_COMMAND, 2); + if (command != 0xffff && (command & PCIM_CMD_BUSMASTEREN) != 0) + panic("%s: unable to fence device DMA (error %d)", + device_get_nameunit(dev), error); + if (error != 0 && command != 0xffff) + device_printf(dev, + "PCI bus-master disable returned %d; readback is disabled\n", + error); + + timeout = max(pcie_get_max_completion_timeout(dev) / 1000, 10); + if (command != 0xffff && + !pcie_wait_for_pending_transactions(dev, timeout)) { + /* A function removed during the wait can no longer issue DMA. */ + command = pci_read_config(dev, PCIR_COMMAND, 2); + if (command != 0xffff) + panic("%s: DMA transactions remain pending after fencing", + device_get_nameunit(dev)); + } +} + +static int +em_enable_pci_busmaster(struct e1000_softc *sc) +{ + device_t dev; + u16 command; + int error; + + dev = sc->dev; + command = pci_read_config(dev, PCIR_COMMAND, 2); + if (command == 0xffff) + return (ENXIO); + if ((command & PCIM_CMD_BUSMASTEREN) != 0) + return (0); + + error = pci_enable_busmaster(dev); + command = pci_read_config(dev, PCIR_COMMAND, 2); + if (command == 0xffff) + return (ENXIO); + if ((command & PCIM_CMD_BUSMASTEREN) == 0) + return (error != 0 ? error : EIO); + return (0); +} + /********************************************************************* * * This routine disables all traffic on the adapter by issuing a @@ -4063,8 +4143,12 @@ em_if_stop(if_ctx_t ctx) return; } } - if (sc->vf_ifp) + if (sc->vf_ifp) { + sc->vf_queues_sanitized = igbv_sanitize_queues(sc); atomic_store_rel_32(&sc->vf_mbx_ready, 0); + if (!sc->vf_queues_sanitized) + em_fence_pci_busmaster(sc); + } if (sc->hw.mac.type >= e1000_82544 && !sc->vf_ifp) E1000_WRITE_REG(&sc->hw, E1000_WUFC, 0); diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h index 6e97d0420100..3f3663b8d9a0 100644 --- a/sys/dev/e1000/if_em.h +++ b/sys/dev/e1000/if_em.h @@ -757,6 +757,7 @@ void igbv_queue_retry_prepare(struct e1000_softc *); void igbv_queue_retry_stop(struct e1000_softc *); void igbv_reconcile_mac(struct e1000_softc *, if_t); bool igbv_reset(if_ctx_t); +bool igbv_sanitize_queues(struct e1000_softc *); void igbv_log_reset_failure(struct e1000_softc *, s32, bool); void igbv_update_uc_addr_list(struct e1000_softc *, if_t); void igbv_vlan_retry_add(struct e1000_softc *, u16); diff --git a/sys/dev/e1000/if_igbv.c b/sys/dev/e1000/if_igbv.c index 2d57a39f934e..9947f4c19e2e 100644 --- a/sys/dev/e1000/if_igbv.c +++ b/sys/dev/e1000/if_igbv.c @@ -531,7 +531,7 @@ igbv_tx_pending(struct e1000_softc *sc) return (false); } -static bool +bool igbv_sanitize_queues(struct e1000_softc *sc) { struct e1000_hw *hw;