From nobody Mon Aug 24 09:14:18 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 4hT4wp6NxPz6p6bw for ; Mon, 24 Aug 2026 09:14:18 +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 4hT4wp3x2kz3vq6 for ; Mon, 24 Aug 2026 09:14:18 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787562858; 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=JN+nLNomCFdRYAJwd2Sw0yiiMitHIyAxA8YQZOKVtJg=; b=TMbz6oSs8q36+HuCC/zH0qI9andjgjjq6M6r9O0D6H9zRLwvHGetVdcuVf2BYaD2pbJK/C TLBaG+TW9MietuW6bTyHanuMROmv3PnDLVpxZzyOrcy90tsjePLWABcw5uhqUgpXKVKbzs fEhakxTMrmE6DDKk8QpVaHZLLQZ/t/BzOQARsLy/lAXDIvMt5S7ovqMrfEmlJyjHNfSBdG o+PTIuFoYhdWW3KMN++h/FlT8+oAMoJ0tyd7OQoGag5ne6vcmdfRaXfVPAfXbST0f3Gg24 c+aiBl2orIJ9v3m7D00Nd0qM0mdZWVT2UcpvX7ohPBR4Jss14olY50sgMDYgCA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1787562858; a=rsa-sha256; cv=none; b=hkVL/bMyT59VFO0cnQ2oQZ35ClH01csDBSX4Tava4lo8j0ebKuCulIbej5ljaYc5attrz3 GyEDEy6a+Qvr5hdtXQTrKzzzkVTzNjw+PGpEnMUG00xQu7TC3uy6q7eHP4SiUFKjqDF2zI SThsBHqJ6+wOENhbdVKs0At7SOK1HNKHrrYbD9pE80qcYXtLAAhsSXKBCjqmPFfj8ZrLfr AM4RbWK4qh21IRIpSmX5T/kg36QvhzP9wS8uZq67l59RnNAUEzlWef+gABFw6vqxcFkd8T F7yyaKaU1K+5ZQFEJPDmV5CIhpeJADyVZevPmyL6G2zlfjLlS+O+zCZz8AZlTQ== 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=1787562858; 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=JN+nLNomCFdRYAJwd2Sw0yiiMitHIyAxA8YQZOKVtJg=; b=k0L76zLCpNXf2XtC4hywMhbZA7yO9n8lQB9hAMbTMZXKdjZ+wrgvy49tgaVRfnqhOGGQB4 Xohs5l1HF8TlZQ9TgKLxOd1l1cCcjlN2lv8wHfRsH5ND+/4evrwJZmhiohfh4C2WhyD8uz aTZIgR9wyxBueg8lwvCWPPLTv5jxIV5dDK0GQhlBFYMY3jckhmDE+BrOJvipsk6Sm31qEB FVhzVIPp42h3QZjMILVoEhfKkFrM49Y6nMtAvb3OA8V2nvsKAiSLUTRMrZHthueOEuL6qy OUZ6xwoAhMGX0IlyLV5LdGNqGftlDkA7+ObijofnbfWVccJq7vwbt3Ejd7/swg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hT4wp2r6lzyf5 for ; Mon, 24 Aug 2026 09:14:18 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 47f79 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 24 Aug 2026 09:14:18 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: 3e8b8afbb6e9 - stable/14 - ixl: Track and recover MDD-blocked VFs 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/stable/14 X-Git-Reftype: branch X-Git-Commit: 3e8b8afbb6e99f1f5e0a9a299b15e639deb33329 Auto-Submitted: auto-generated Date: Mon, 24 Aug 2026 09:14:18 +0000 Message-Id: <6a8c0b6a.47f79.2af63f2@gitrepo.freebsd.org> The branch stable/14 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=3e8b8afbb6e99f1f5e0a9a299b15e639deb33329 commit 3e8b8afbb6e99f1f5e0a9a299b15e639deb33329 Author: Kevin Bowling AuthorDate: 2026-08-10 03:46:24 +0000 Commit: Kevin Bowling CommitDate: 2026-08-24 09:12:22 +0000 ixl: Track and recover MDD-blocked VFs The hardware identifies each VF with TX and RX malicious-driver status latches, but the driver combined all events into one counter and reported only the last VF found. Consume every PF and VF latch, keep per-direction VF counters, and rate-limit per-VF diagnostics. Keep the software block until a successful VF or PF reset reconstructs its resources. Match Linux i40e policy by leaving a detected VF blocked by default. Add an opt-in hw.ixl.mdd_auto_reset_vf tunable that notifies and resets the VF for installations that prefer availability. DPDK provides the register clear and per-VF attribution precedent; Linux provides the recovery policy. (cherry picked from commit 93f1065920d806400ace6b60b025faf91926bdaa) --- share/man/man4/ixl.4 | 6 +++ sys/dev/ixl/if_ixl.c | 8 ++- sys/dev/ixl/ixl_pf.h | 9 +++- sys/dev/ixl/ixl_pf_iov.c | 30 +++++++++++ sys/dev/ixl/ixl_pf_main.c | 132 ++++++++++++++++++++++------------------------ 5 files changed, 115 insertions(+), 70 deletions(-) diff --git a/share/man/man4/ixl.4 b/share/man/man4/ixl.4 index ef52b9f8b456..37d8c0cf5db8 100644 --- a/share/man/man4/ixl.4 +++ b/share/man/man4/ixl.4 @@ -213,6 +213,12 @@ use a value written to memory by the hardware instead of scanning the descriptor ring for completed descriptors. Enabled by default; disable to mimic the TX behavior found in .Xr ix 4 . +.It Va hw.ixl.mdd_auto_reset_vf +Automatically reset a VF after malicious-driver detection blocks it. +This is disabled by default so a non-cooperative VF remains unable to issue +traffic until it performs an FLR or the SR-IOV configuration is recreated. +Enabling this tunable favors availability but allows a persistently faulty or +hostile VF to resume after each reset. .El .Sh SYSCTL PROCEDURES .Bl -tag -width indent diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c index bc929753944b..a0e1fefe09fc 100644 --- a/sys/dev/ixl/if_ixl.c +++ b/sys/dev/ixl/if_ixl.c @@ -251,6 +251,12 @@ SYSCTL_INT(_hw_ixl, OID_AUTO, enable_vf_loopback, CTLFLAG_RDTUN, &ixl_enable_vf_loopback, 0, IXL_SYSCTL_HELP_VF_LOOPBACK); +static int ixl_mdd_auto_reset_vf; +TUNABLE_INT("hw.ixl.mdd_auto_reset_vf", &ixl_mdd_auto_reset_vf); +SYSCTL_INT(_hw_ixl, OID_AUTO, mdd_auto_reset_vf, CTLFLAG_RDTUN, + &ixl_mdd_auto_reset_vf, 0, + "Automatically reset VFs blocked by malicious-driver detection"); + /* * Different method for processing TX descriptor * completion. @@ -1938,6 +1944,7 @@ ixl_save_pf_tunables(struct ixl_pf *pf) pf->hw.debug_mask = ixl_shared_debug_mask; pf->vsi.enable_head_writeback = !!(ixl_enable_head_writeback); pf->enable_vf_loopback = !!(ixl_enable_vf_loopback); + pf->mdd_auto_reset_vf = !!(ixl_mdd_auto_reset_vf); #if 0 pf->dynamic_rx_itr = ixl_dynamic_rx_itr; pf->dynamic_tx_itr = ixl_dynamic_tx_itr; @@ -1987,4 +1994,3 @@ ixl_save_pf_tunables(struct ixl_pf *pf) pf->fc = ixl_flow_control; } } - diff --git a/sys/dev/ixl/ixl_pf.h b/sys/dev/ixl/ixl_pf.h index 695fc8858140..f7bcf121683f 100644 --- a/sys/dev/ixl/ixl_pf.h +++ b/sys/dev/ixl/ixl_pf.h @@ -103,7 +103,12 @@ enum ixl_state { struct ixl_vf { struct ixl_vsi vsi; u32 vf_flags; - u32 num_mdd_events; + u64 mdd_tx_events; + u64 mdd_rx_events; + struct timeval last_mdd_log; + bool mdd_blocked; + bool mdd_event_pending; + bool mdd_reset_pending; u8 mac[ETHER_ADDR_LEN]; u8 mac_filters[IXL_VF_MAX_MAC_FILTERS][ETHER_ADDR_LEN]; @@ -151,6 +156,7 @@ struct ixl_pf { int tx_itr; int rx_itr; int enable_vf_loopback; + int mdd_auto_reset_vf; bool link_up; int advertised_speed; @@ -384,6 +390,7 @@ int ixl_pf_reset(struct ixl_pf *); #ifdef PCI_IOV void ixl_notify_vfs_reset(struct ixl_pf *); int ixl_rebuild_vfs_after_reset(struct ixl_pf *); +int ixl_reset_vf_on_mdd(struct ixl_pf *, uint16_t); #endif void ixl_set_queue_rx_itr(struct ixl_rx_queue *); diff --git a/sys/dev/ixl/ixl_pf_iov.c b/sys/dev/ixl/ixl_pf_iov.c index aefb01cfadb9..560b559f40e2 100644 --- a/sys/dev/ixl/ixl_pf_iov.c +++ b/sys/dev/ixl/ixl_pf_iov.c @@ -497,6 +497,9 @@ ixl_reinit_vf(struct ixl_pf *pf, struct ixl_vf *vf) wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_num), VIRTCHNL_VFR_VFACTIVE); ixl_flush(hw); + vf->mdd_blocked = false; + vf->mdd_event_pending = false; + vf->mdd_reset_pending = false; return (0); } @@ -1766,6 +1769,10 @@ ixl_handle_vf_msg(struct ixl_pf *pf, struct i40e_arq_event_info *event) (vf->vf_flags & VF_FLAG_ENABLED) ? " " : " disabled ", vf_num, msg_size); + /* Only a reset outside the virtchnl dispatcher may unblock the VF. */ + if (vf->mdd_blocked) + return; + /* Perform basic checks on the msg */ err = virtchnl_vc_validate_vf_msg(&vf->version, opcode, msg, msg_size); if (err) { @@ -2036,6 +2043,26 @@ ixl_notify_vfs_reset(struct ixl_pf *pf) } } +int +ixl_reset_vf_on_mdd(struct ixl_pf *pf, uint16_t vfnum) +{ + struct virtchnl_pf_event event; + struct ixl_vf *vf; + + if (vfnum >= pf->num_vfs) + return (EINVAL); + vf = &pf->vfs[vfnum]; + if (!(vf->vf_flags & VF_FLAG_ENABLED)) + return (ENXIO); + + bzero(&event, sizeof(event)); + event.event = VIRTCHNL_EVENT_RESET_IMPENDING; + event.severity = PF_EVENT_SEVERITY_CERTAIN_DOOM; + ixl_send_vf_msg(pf, vf, VIRTCHNL_OP_EVENT, I40E_SUCCESS, + &event, sizeof(event)); + return (ixl_reset_vf(pf, vf)); +} + int ixl_rebuild_vfs_after_reset(struct ixl_pf *pf) { @@ -2064,6 +2091,9 @@ ixl_rebuild_vfs_after_reset(struct ixl_pf *pf) bit_nclear(vf->vsi.vlans_map, 0, IXL_VLANS_MAP_LEN - 1); vf->num_mac_filters = 0; + vf->mdd_blocked = false; + vf->mdd_event_pending = false; + vf->mdd_reset_pending = false; } error = ixl_setup_iov_switch(pf); diff --git a/sys/dev/ixl/ixl_pf_main.c b/sys/dev/ixl/ixl_pf_main.c index 092718a12d10..b06188545116 100644 --- a/sys/dev/ixl/ixl_pf_main.c +++ b/sys/dev/ixl/ixl_pf_main.c @@ -1853,12 +1853,8 @@ ixl_handle_tx_mdd_event(struct ixl_pf *pf) struct i40e_hw *hw = &pf->hw; device_t dev = pf->dev; struct ixl_vf *vf; - bool mdd_detected = false; - bool pf_mdd_detected = false; - bool vf_mdd_detected = false; u16 vf_num, queue; u8 pf_num, event; - u8 pf_mdet_num, vp_mdet_num; u32 reg; /* find what triggered the MDD event */ @@ -1872,18 +1868,20 @@ ixl_handle_tx_mdd_event(struct ixl_pf *pf) I40E_GL_MDET_TX_EVENT_SHIFT; queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK) >> I40E_GL_MDET_TX_QUEUE_SHIFT; + if (queue >= hw->func_caps.base_queue) + queue -= hw->func_caps.base_queue; + device_printf(dev, + "last TX malicious-driver cause %#x on queue %u, " + "PF %#x, VF %#x\n", event, queue, pf_num, vf_num); wr32(hw, I40E_GL_MDET_TX, 0xffffffff); - mdd_detected = true; } - if (!mdd_detected) - return; - reg = rd32(hw, I40E_PF_MDET_TX); if (reg & I40E_PF_MDET_TX_VALID_MASK) { wr32(hw, I40E_PF_MDET_TX, 0xFFFF); - pf_mdet_num = hw->pf_id; - pf_mdd_detected = true; + device_printf(dev, + "TX malicious-driver issue detected on PF-%u\n", + hw->pf_id); } /* Check if MDD was caused by a VF */ @@ -1892,32 +1890,16 @@ ixl_handle_tx_mdd_event(struct ixl_pf *pf) reg = rd32(hw, I40E_VP_MDET_TX(i)); if (reg & I40E_VP_MDET_TX_VALID_MASK) { wr32(hw, I40E_VP_MDET_TX(i), 0xFFFF); - vp_mdet_num = i; - vf->num_mdd_events++; - vf_mdd_detected = true; + if (!(vf->vf_flags & VF_FLAG_ENABLED)) + continue; + vf->mdd_tx_events++; + vf->mdd_event_pending = true; + if (!vf->mdd_blocked) { + vf->mdd_blocked = true; + vf->mdd_reset_pending = true; + } } } - - /* Print out an error message */ - if (vf_mdd_detected && pf_mdd_detected) - device_printf(dev, - "Malicious Driver Detection event %d" - " on TX queue %d, pf number %d (PF-%d), vf number %d (VF-%d)\n", - event, queue, pf_num, pf_mdet_num, vf_num, vp_mdet_num); - else if (vf_mdd_detected && !pf_mdd_detected) - device_printf(dev, - "Malicious Driver Detection event %d" - " on TX queue %d, pf number %d, vf number %d (VF-%d)\n", - event, queue, pf_num, vf_num, vp_mdet_num); - else if (!vf_mdd_detected && pf_mdd_detected) - device_printf(dev, - "Malicious Driver Detection event %d" - " on TX queue %d, pf number %d (PF-%d)\n", - event, queue, pf_num, pf_mdet_num); - /* Theoretically shouldn't happen */ - else - device_printf(dev, - "TX Malicious Driver Detection event (unknown)\n"); } static void @@ -1926,12 +1908,8 @@ ixl_handle_rx_mdd_event(struct ixl_pf *pf) struct i40e_hw *hw = &pf->hw; device_t dev = pf->dev; struct ixl_vf *vf; - bool mdd_detected = false; - bool pf_mdd_detected = false; - bool vf_mdd_detected = false; u16 queue; u8 pf_num, event; - u8 pf_mdet_num, vp_mdet_num; u32 reg; /* @@ -1946,18 +1924,20 @@ ixl_handle_rx_mdd_event(struct ixl_pf *pf) I40E_GL_MDET_RX_EVENT_SHIFT; queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK) >> I40E_GL_MDET_RX_QUEUE_SHIFT; + if (queue >= hw->func_caps.base_queue) + queue -= hw->func_caps.base_queue; + device_printf(dev, + "last RX malicious-driver cause %#x on queue %u, " + "function %#x\n", event, queue, pf_num); wr32(hw, I40E_GL_MDET_RX, 0xffffffff); - mdd_detected = true; } - if (!mdd_detected) - return; - reg = rd32(hw, I40E_PF_MDET_RX); if (reg & I40E_PF_MDET_RX_VALID_MASK) { wr32(hw, I40E_PF_MDET_RX, 0xFFFF); - pf_mdet_num = hw->pf_id; - pf_mdd_detected = true; + device_printf(dev, + "RX malicious-driver issue detected on PF-%u\n", + hw->pf_id); } /* Check if MDD was caused by a VF */ @@ -1966,32 +1946,16 @@ ixl_handle_rx_mdd_event(struct ixl_pf *pf) reg = rd32(hw, I40E_VP_MDET_RX(i)); if (reg & I40E_VP_MDET_RX_VALID_MASK) { wr32(hw, I40E_VP_MDET_RX(i), 0xFFFF); - vp_mdet_num = i; - vf->num_mdd_events++; - vf_mdd_detected = true; + if (!(vf->vf_flags & VF_FLAG_ENABLED)) + continue; + vf->mdd_rx_events++; + vf->mdd_event_pending = true; + if (!vf->mdd_blocked) { + vf->mdd_blocked = true; + vf->mdd_reset_pending = true; + } } } - - /* Print out an error message */ - if (vf_mdd_detected && pf_mdd_detected) - device_printf(dev, - "Malicious Driver Detection event %d" - " on RX queue %d, pf number %d (PF-%d), (VF-%d)\n", - event, queue, pf_num, pf_mdet_num, vp_mdet_num); - else if (vf_mdd_detected && !pf_mdd_detected) - device_printf(dev, - "Malicious Driver Detection event %d" - " on RX queue %d, pf number %d, (VF-%d)\n", - event, queue, pf_num, vp_mdet_num); - else if (!vf_mdd_detected && pf_mdd_detected) - device_printf(dev, - "Malicious Driver Detection event %d" - " on RX queue %d, pf number %d (PF-%d)\n", - event, queue, pf_num, pf_mdet_num); - /* Theoretically shouldn't happen */ - else - device_printf(dev, - "RX Malicious Driver Detection event (unknown)\n"); } /** @@ -2004,6 +1968,10 @@ void ixl_handle_mdd_event(struct ixl_pf *pf) { struct i40e_hw *hw = &pf->hw; + struct ixl_vf *vf; + static const struct timeval log_interval = { 2, 0 }; + bool reset; + int i; u32 reg; /* @@ -2012,6 +1980,34 @@ ixl_handle_mdd_event(struct ixl_pf *pf) */ ixl_handle_tx_mdd_event(pf); ixl_handle_rx_mdd_event(pf); + for (i = 0; i < pf->num_vfs; i++) { + vf = &pf->vfs[i]; + if (!vf->mdd_event_pending) + continue; + vf->mdd_event_pending = false; + reset = vf->mdd_reset_pending; + vf->mdd_reset_pending = false; + if (ratecheck(&vf->last_mdd_log, &log_interval)) { + device_printf(pf->dev, + "malicious-driver event from VF-%d " + "(tx %ju, rx %ju); %s\n", i, + (uintmax_t)vf->mdd_tx_events, + (uintmax_t)vf->mdd_rx_events, + pf->mdd_auto_reset_vf && reset ? + "resetting VF" : "VF remains blocked"); + } +#ifdef PCI_IOV + if (pf->mdd_auto_reset_vf && reset) { + int error; + + error = ixl_reset_vf_on_mdd(pf, i); + if (error != 0) + device_printf(pf->dev, + "failed to reset MDD-blocked VF-%d: %d\n", + i, error); + } +#endif + } ixl_clear_state(&pf->state, IXL_STATE_MDD_PENDING);