From nobody Thu Aug 20 22:14:43 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 4hQyRF0WTZz6pcCw for ; Thu, 20 Aug 2026 22:14:49 +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 4hQyRD5vyjz3kLZ for ; Thu, 20 Aug 2026 22:14:48 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787264088; 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=RCp2RLCeuNNx3VF8lKokA2UpNeQP1qCPDimF/jip7R+T1brVPvhVjRqWDRkUrOxAK8yDX2 7J5N22PpmJO3OFJDXtTK2Dc1SCtE06acb8zbOVDTi1DNWqpbumYf1JzALL3lkxI5Im6ZQ5 8/kL6kSM9hPTlVSXw+8O+8Rp23/v1BetZeSB50GJkfNCJtEhV85FStKInXOXqraXwICplz uf6D1OaWjm7oMq8lKK+IW8l3WaqpuE/A+oh/TI5WdUpnxsSogqzD2isOmHog44pyNni1rt ZvXVuzvr8MbuHCFwmKY+8KXUOSjI7nrDldXTt2/vOdlJ0oc8V/y1ho/CUxVRbQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1787264088; a=rsa-sha256; cv=none; b=yLjmoS/t673JzxDZF65FVNsZFsAjD+2OSZS7QyIJOWhgPwJ09Oq8AtUPIanJKxIc+zAUnQ W2x1vTzIO8sgfuRj1g9JFkLY3A7QTnoJmOmJaMdLmNh3G7hwOOiKBS5oQ/B0vqQa+qKQYU H82bjM7AlD3+bezBjEu8gZ1lUi1q2gF6cs4L+GAuoMa6D2EgsabZck8qRyCaQ+f1GfTEP4 WukJGJLdC4DnUc9mnrfawVmIE3IbDMXFtCRwd8/BAwevbrXNLNezuGI+XOBQ7mFBta8S97 i0qmbgQZeFpWE1WIjbMPZY5bEuvSkKisOSIWk/JewXYDJ3giVcJxgUQTHp87ow== 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=1787264088; 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=hvFEDBDH6e2fTKNz+o48HUhzkKKv1EyijX4mYKMB1SNJsSpOsBNACq4y36jUPly3lcqKJy KPb3g9Mh6cSsgTZ88ZnA5aQq6oW09Hhy9vslQjeSju2jzp7RYTu2gmcw6+s6aOGFIkDtRb NLJyslD1jE1h/Kp7K5whQyXRz7BN28nEKpUf1AMXoxE6lIy3nj+Md7iHRTQKgobYQHK6b/ XqEkk7jawclRJxaAs+D5QEyLFgvy7e/GKN3wE9+MirzjwtSeu2k52azWl0ZuwEHXRQ76bw O38vYzxcIo3M8Enn+QWC53gkBIxbJ6aVf+kzlXmNR/TyufP+VIpe7p5SiZhHEw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hQyRD4XmlzbyG for ; Thu, 20 Aug 2026 22:14:48 +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 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: 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