From nobody Thu Aug 20 22:14:43 2026 X-Original-To: dev-commits-src-main@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 4hQyR75tKsz6pc9F for ; Thu, 20 Aug 2026 22:14:43 +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 4hQyR75N6Hz3kKk for ; Thu, 20 Aug 2026 22:14:43 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787264083; 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=vWoOprflO8CsupUY1GxWrTvaIC4P8C1i5jJlSnHVMhs=; b=W6dEI+KVDjwH6NEHMzQeZjgHGBCdz3ww241AUtNNZCcQJkQv4W7kbOxdOJJxdxISFIXYQn P1/1PTkviFTF7dzzfkh2jslnE4i52+7ksKj5Ma3qLsAZF4jDOaH4tjVkVY9ByJCa2XjfDv gqDqW7W1uuxiKbPOzmEpVo2MhmC4o4pRX4c212qxAge4v8OwAAVYe3lCQnS7xN2uUup1hV pWqGoEfbDDn9KUMs32ZpMDfu3JqCgKsOOmLvq67nldaw2gsXRqaGtp5mqrIymkE9VeI6UM 8cSys7JKSsBxuCFfPr7wRGxf+w7y78GdFDWIsKwmvw6xkEhW5HSUuyrPTTOPfg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1787264083; a=rsa-sha256; cv=none; b=t1Zc5KyQTGbfxUVwr8uIwvExnqf27TWWs2aV3X4w1Y+oISZ3buNbnMzfVm08UJ1Vmyw6Ud acssIoIuVPNfGSdwvXnRzxUCC10dHSbQ/U9RCop9+UFso9OX7+Hc7kd3a1adtQD2FR0N7t fMAyd5w1IcU8dRw544V77J47yoa9BqO7w1lXlms7ieiEn9hc9MKjm6ixl0T1z8YmiQUMzr qf9OsfLyorhXm3Z9L4LS9TyS8VfwM6OmCv2UHZYLxo0LZz8IT9lhNnHGd+BoENOmJxptto GSVlr+TqLwP0wJ/hDgav6LMzyM8tW9UoGBhmXhMtFUZjRM0/7je3Ddc/3RS8Ig== 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=1787264083; 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=vWoOprflO8CsupUY1GxWrTvaIC4P8C1i5jJlSnHVMhs=; b=hvaQkybCiZzCpW1qELXJQ7uRKNoZ1qgd1fl4Jy+/UMy+GVVCUZW/oKc4Dt9CjI2Kr9hFRk rVjaS5tndMWutK3CcuD6qziCxemsj3OZIQ5XG/b0rp4PGQhUtJk1QaFDOvM54KscRYrbIq ywozh17YY/AT3RhVbWvH3eMtbHZvj1LPO57c/kP0MIcr9qn0ApOIdQmTmySWLGSupwsorN 4kFquiw53phnz9b8X/Ik/CroIXYa3+MbAQoUsBciTgal1o1iXXCQCTXR9FaKQJe3Xlow9G RHHxAiFd4E7jccKuVBpFEQPP6u/UVC8tiqWq/g5A8DPcAlncRd9HTdUxnFbABQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hQyR7432CzcYs for ; Thu, 20 Aug 2026 22:14:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3ba1d by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 20 Aug 2026 22:14:43 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 3b90096cf9bc - main - bhyve: Keep passthrough PCI power state virtual List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@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: 3b90096cf9bcaec70b717e9ff0a9e23d14b600b6 Auto-Submitted: auto-generated Date: Thu, 20 Aug 2026 22:14:43 +0000 Message-Id: <6a877c53.3ba1d.5088bd4e@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=3b90096cf9bcaec70b717e9ff0a9e23d14b600b6 commit 3b90096cf9bcaec70b717e9ff0a9e23d14b600b6 Author: Kevin Bowling AuthorDate: 2026-08-17 17:09:23 +0000 Commit: Kevin Bowling CommitDate: 2026-08-20 22:13:36 +0000 bhyve: Keep passthrough PCI power state virtual The passthrough Command register is emulated, but PMCSR writes were sent directly to the physical function. A guest D3hot-to-D0 transition can perform an internal reset and clear physical Command while its emulated copy remains enabled. Cache the Power Management capability and keep the physical D-state host-owned. Emulate the guest D-state and advertise No_Soft_Reset so the guest is not promised a function reset by a virtual power cycle. Restore the assignment-time virtual state after a managed FLR. Reviewed by: markj MFC after: 2 weeks Sponsored by: BBOX.io --- usr.sbin/bhyve/pci_passthru.c | 53 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c index a78ca06c9d83..24d96764964d 100644 --- a/usr.sbin/bhyve/pci_passthru.c +++ b/usr.sbin/bhyve/pci_passthru.c @@ -100,6 +100,11 @@ struct passthru_softc { struct { int capoff; } psc_msix; + struct { + int capoff; + uint16_t pmcsr; + uint16_t reset_pmcsr; + } psc_pm; struct { int capoff; uint16_t devctl; @@ -331,6 +336,8 @@ cfginitcaps(struct passthru_softc *sc) capptr += 4; msixcap_ptr += 4; } + } else if (cap == PCIY_PMG) { + sc->psc_pm.capoff = ptr; } else if (cap == PCIY_EXPRESS) { sc->psc_pcie.capoff = ptr; } @@ -338,6 +345,13 @@ cfginitcaps(struct passthru_softc *sc) 1); } } + if (sc->psc_pm.capoff != 0) { + sc->psc_pm.pmcsr = passthru_read_config(&sel, + sc->psc_pm.capoff + PCIR_POWER_STATUS, 2); + /* The physical function remains in its host-owned power state. */ + sc->psc_pm.pmcsr |= PCIM_PSTAT_NOSOFTRESET; + sc->psc_pm.reset_pmcsr = sc->psc_pm.pmcsr; + } if (sc->psc_pcie.capoff != 0) { sc->psc_pcie.devctl = passthru_read_config(&sel, sc->psc_pcie.capoff + PCIER_DEVICE_CTL, 2); @@ -1120,6 +1134,8 @@ msixcap_access(struct passthru_softc *sc, int coff) #define PASSTHRU_DEVCTL_NO_WRITE PCIEM_CTL_PHANTHOM_FUNCS #define PASSTHRU_DEVCTL2_VIRT (PCIEM_CTL2_COMP_TIMO_VAL | \ PCIEM_CTL2_COMP_TIMO_DISABLE) +#define PASSTHRU_PMCSR_VIRT (PCIM_PSTAT_DMASK | \ + PCIM_PSTAT_NOSOFTRESET) static uint32_t passthru_cfg_field_mask(int coff, int bytes, int fieldoff, uint16_t mask) @@ -1243,6 +1259,8 @@ passthru_reset_capability_state(struct passthru_softc *sc) (sc->psc_pcie.reset_devctl & ~PCIEM_CTL_MAX_PAYLOAD) | guest_mps; if (sc->psc_pcie.has_devctl2) sc->psc_pcie.devctl2 = sc->psc_pcie.reset_devctl2; + if (sc->psc_pm.capoff != 0) + sc->psc_pm.pmcsr = sc->psc_pm.reset_pmcsr; } static int @@ -1320,6 +1338,13 @@ passthru_cfgread_default(struct passthru_softc *sc, /* Everything else just read from the device's config space. */ *rv = passthru_read_config(&sc->psc_sel, coff, bytes); + if (sc->psc_pm.capoff != 0) { + int pmcsr; + + pmcsr = sc->psc_pm.capoff + PCIR_POWER_STATUS; + *rv = passthru_cfg_overlay_field(coff, bytes, *rv, pmcsr, + sc->psc_pm.pmcsr, PASSTHRU_PMCSR_VIRT); + } if (sc->psc_pcie.capoff != 0) { int devctl; @@ -1362,8 +1387,8 @@ passthru_cfgwrite_default(struct passthru_softc *sc, struct pci_devinst *pi, int coff, int bytes, uint32_t val) { uint32_t flr_mask, transport_mask; - uint16_t physical_devctl; - int devctl, devctl2, host_mps, guest_mrrs; + uint16_t physical_devctl, physical_pmcsr; + int devctl, devctl2, host_mps, guest_mrrs, pmcsr; int error, msix_table_entries, i; uint16_t cmd_old; @@ -1408,6 +1433,30 @@ passthru_cfgwrite_default(struct passthru_softc *sc, struct pci_devinst *pi, return (0); } + /* + * A physical D3hot-to-D0 transition may reset the function and clear + * Command behind bhyve's emulated copy. Keep the physical D-state + * host-owned, emulate the guest D-state, and advertise No_Soft_Reset so + * the guest does not rely on this cycle as a function reset. + */ + pmcsr = sc->psc_pm.capoff + PCIR_POWER_STATUS; + if (sc->psc_pm.capoff != 0 && coff < pmcsr + 2 && + coff + bytes > pmcsr) { + physical_pmcsr = passthru_read_config(&sc->psc_sel, pmcsr, 2); + if (physical_pmcsr == 0xffff) { + warnx("configuration space unavailable for passthru " + "device %d/%d/%d", sc->psc_sel.pc_bus, + sc->psc_sel.pc_dev, sc->psc_sel.pc_func); + return (0); + } + passthru_cfg_update_field(coff, bytes, val, pmcsr, + PCIM_PSTAT_DMASK, &sc->psc_pm.pmcsr); + val = passthru_cfg_overlay_field(coff, bytes, val, pmcsr, + physical_pmcsr, PASSTHRU_PMCSR_VIRT); + passthru_write_config(&sc->psc_sel, coff, bytes, val); + return (0); + } + /* * A direct FLR would clear physical Command while the guest sees its * emulated copy remain enabled. Route FLR through ppt so it restores