From nobody Mon Jan 26 22:05:07 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 4f0Mz82dMrz6Pgxp for ; Mon, 26 Jan 2026 22:05:08 +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 "R13" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4f0Mz804lpz3Gmw for ; Mon, 26 Jan 2026 22:05:08 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1769465108; 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=iZXQaGY1TJrP9ItmRw0yT3BeySnw08rWbdJyUOILRgE=; b=pAWnhFcqkkxF4XZhNra/jofL6W78Dit/MDqxvAH3n1Hm/xpgZRWtNKGtuuZmoW+FRv0shX ymmA2700lB89SlD8nLPR/86MUbQtphxaxhSB90jRmbJVGVCHlxacHpq3d8qyV96R8+ilQq NsyGs5uwAlIYAIfWka1S5DTt+yY/Gl1pwQggzRDmeqiiFHNusg5cg6K2mopGUuLOmEt+Gn YsVY9hjcPY9wPca56sewmEMXUkDjtuUP/NVvBHUtathx6pBpQJ4ekmdfDiiulhC2em5KB3 XbAvburxvgaoOWoz7Ug5gesZJMdxiNTqvUK1kJCLZPNpWsbnLpxUwjl6DZkY1Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1769465108; 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=iZXQaGY1TJrP9ItmRw0yT3BeySnw08rWbdJyUOILRgE=; b=qSQMAKeE2piBu3s8fYzcOMR0+RW7ZYdFylLLAe8xu0PpudeQ/wHg1PZyXxAc8SIr6/wnSf hXRymb3BecmYvufujjHiikv/d4Wpg7ms12v0IO8SZf4vTCxIq+1bs4pv85XN4pq8onbBK/ QFhh6/mS8tpub1kNMGhUSmwbLVdKs4DRbN9LwiKOs6wNCg48PR+T2MGfgsaL25VTLUdIZS PXSp/g7snKHk3ousEuGiq5aOJNZIs2A/530JDbME5vNUQJql0+FgM9lB3Gp+le+EhlyRsU l+zb6i6TKs2Ah1VZKjgTtOMqGAP6o1t6ta4Jhs5YG/M3Hd7yiSLAFg/WxbsI6w== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1769465108; a=rsa-sha256; cv=none; b=xB7dMvqUrHZsRTx5uu0bGI/aEM0knECayFggQIHUp2zhqjydLiTlE10WKpIk9QYwyInrWP 4Aw75Yi95zUB93dKhmI3SJjFKLlnK7tK491Fv9Yb22D/+92PVtBLMTnSHDG4QDXN3IgjqM 4Qfje/aHEhgTSk3UhfRs1+2WG8IFArtzKIIjgb/4aTv9fK2llTTTC8vXEfZKqd7hhTXJkx FYBTG3Ih+Agj1SSM/fhNLOvo9N8zzN8EfyS+DzBdUWYO5q8fsdD63sze+ehknGFCdud7cC UtjAbbsfE5H84dxB7ZvDSzZ3A6XdYEuwpIgiy2WDtz/pT8zSDDYd6bIUi6g8sA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4f0Mz75y53zfjk for ; Mon, 26 Jan 2026 22:05:07 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3504f by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 26 Jan 2026 22:05:07 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mark Johnston Subject: git: 1db1e4bdc64f - main - bhyve: Use PCIOCGETCONF to find the host LPC bridge 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 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 1db1e4bdc64f29661592a47f2feb690d7cf37957 Auto-Submitted: auto-generated Date: Mon, 26 Jan 2026 22:05:07 +0000 Message-Id: <6977e513.3504f.d37eb76@gitrepo.freebsd.org> The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=1db1e4bdc64f29661592a47f2feb690d7cf37957 commit 1db1e4bdc64f29661592a47f2feb690d7cf37957 Author: Mark Johnston AuthorDate: 2026-01-26 21:05:06 +0000 Commit: Mark Johnston CommitDate: 2026-01-26 22:03:51 +0000 bhyve: Use PCIOCGETCONF to find the host LPC bridge pci_host_read_config() requires write access to /dev/pci so cannot be used with unprivileged bhyve. The lpc init code uses it to find the host system's LPC bridge device and so was generating warnings with bhyve running as a non-root user. Refactor the implementation to use PCIOCGETCONF instead, which doesn't require any special privileges. This isn't formally necessary, as we only care about copying the host system's identifiers in order to support Intel GPU passthrough (see commit f4ceaff56ddaa), but it's straightforward and lets an unprivileged user run bhyve without seeing warnings about failing to open /dev/pci with write permissions. Reviewed by: corvink, rew MFC after: 3 weeks Sponsored by: The FreeBSD Foundation Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D54851 --- usr.sbin/bhyve/amd64/pci_lpc.c | 79 +++++++++++++++++++++++++----------------- usr.sbin/bhyve/pci_emul.c | 22 ++++++------ usr.sbin/bhyve/pci_emul.h | 2 +- 3 files changed, 60 insertions(+), 43 deletions(-) diff --git a/usr.sbin/bhyve/amd64/pci_lpc.c b/usr.sbin/bhyve/amd64/pci_lpc.c index ed41a800a2ea..52e9faec22af 100644 --- a/usr.sbin/bhyve/amd64/pci_lpc.c +++ b/usr.sbin/bhyve/amd64/pci_lpc.c @@ -28,10 +28,12 @@ */ #include + #include #include #include +#include #include #include #include @@ -46,7 +48,6 @@ #include "pci_emul.h" #include "pci_irq.h" #include "pci_lpc.h" -#include "pci_passthru.h" #include "pctestdev.h" #include "tpm_device.h" #include "uart_emul.h" @@ -460,34 +461,48 @@ pci_lpc_read(struct pci_devinst *pi __unused, int baridx __unused, #define LPC_SUBDEV_0 0x0000 static int -pci_lpc_get_sel(struct pcisel *const sel) +pci_lpc_get_conf(struct pci_conf *conf) { - assert(sel != NULL); - - memset(sel, 0, sizeof(*sel)); - - for (uint8_t slot = 0; slot <= PCI_SLOTMAX; ++slot) { - uint8_t max_func = 0; - - sel->pc_dev = slot; - sel->pc_func = 0; + struct pci_conf_io pcio; + struct pci_match_conf pmc; + int pcifd; - if (pci_host_read_config(sel, PCIR_HDRTYPE, 1) & PCIM_MFDEV) - max_func = PCI_FUNCMAX; + pcifd = open("/dev/pci", O_RDONLY); + if (pcifd < 0) { + warn("%s: Unable to open /dev/pci", __func__); + return (-1); + } - for (uint8_t func = 0; func <= max_func; ++func) { - sel->pc_func = func; +restart: + memset(&pcio, 0, sizeof(pcio)); + memset(&pmc, 0, sizeof(pmc)); + pmc.pc_class = PCIC_BRIDGE; + pmc.flags = PCI_GETCONF_MATCH_CLASS; + do { + pcio.pat_buf_len = sizeof(pmc); + pcio.num_patterns = 1; + pcio.patterns = &pmc; + pcio.match_buf_len = sizeof(*conf); + pcio.matches = conf; + if (ioctl(pcifd, PCIOCGETCONF, &pcio) == -1) { + warn("%s: ioctl(PCIOCGETCONF) failed", __func__); + break; + } + if (pcio.num_matches == 0) + break; + if (pcio.status == PCI_GETCONF_LIST_CHANGED) + goto restart; - if (pci_host_read_config(sel, PCIR_CLASS, 1) == - PCIC_BRIDGE && - pci_host_read_config(sel, PCIR_SUBCLASS, 1) == - PCIS_BRIDGE_ISA) { - return (0); - } + if (conf->pc_class == PCIC_BRIDGE && + conf->pc_subclass == PCIS_BRIDGE_ISA) { + close(pcifd); + return (0); } - } + } while (pcio.status == PCI_GETCONF_MORE_DEVS); + + close(pcifd); - warnx("%s: Unable to find host selector of LPC bridge.", __func__); + warnx("%s: Unable to find host selector of LPC bridge", __func__); return (-1); } @@ -495,8 +510,7 @@ pci_lpc_get_sel(struct pcisel *const sel) static int pci_lpc_init(struct pci_devinst *pi, nvlist_t *nvl) { - struct pcisel sel = { 0 }; - struct pcisel *selp = NULL; + struct pci_conf conf, *confp; uint16_t device, subdevice, subvendor, vendor; uint8_t revid; @@ -521,15 +535,16 @@ pci_lpc_init(struct pci_devinst *pi, nvlist_t *nvl) if (lpc_init(pi->pi_vmctx) != 0) return (-1); - if (pci_lpc_get_sel(&sel) == 0) - selp = &sel; + confp = NULL; + if (pci_lpc_get_conf(&conf) == 0) + confp = &conf; - vendor = pci_config_read_reg(selp, nvl, PCIR_VENDOR, 2, LPC_VENDOR); - device = pci_config_read_reg(selp, nvl, PCIR_DEVICE, 2, LPC_DEV); - revid = pci_config_read_reg(selp, nvl, PCIR_REVID, 1, LPC_REVID); - subvendor = pci_config_read_reg(selp, nvl, PCIR_SUBVEND_0, 2, + vendor = pci_config_read_reg(confp, nvl, PCIR_VENDOR, 2, LPC_VENDOR); + device = pci_config_read_reg(confp, nvl, PCIR_DEVICE, 2, LPC_DEV); + revid = pci_config_read_reg(confp, nvl, PCIR_REVID, 1, LPC_REVID); + subvendor = pci_config_read_reg(confp, nvl, PCIR_SUBVEND_0, 2, LPC_SUBVEND_0); - subdevice = pci_config_read_reg(selp, nvl, PCIR_SUBDEV_0, 2, + subdevice = pci_config_read_reg(confp, nvl, PCIR_SUBDEV_0, 2, LPC_SUBDEV_0); /* initialize config space */ diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c index 9d6060e3e254..dc27402675ee 100644 --- a/usr.sbin/bhyve/pci_emul.c +++ b/usr.sbin/bhyve/pci_emul.c @@ -353,49 +353,51 @@ pci_print_supported_devices(void) } uint32_t -pci_config_read_reg(const struct pcisel *const host_sel, nvlist_t *nvl, +pci_config_read_reg(const struct pci_conf *host_conf, nvlist_t *nvl, const uint32_t reg, const uint8_t size, const uint32_t def) { const char *config; const nvlist_t *pci_regs; + uint32_t host; assert(size == 1 || size == 2 || size == 4); pci_regs = find_relative_config_node(nvl, "pcireg"); if (pci_regs == NULL) { - return def; + return (def); } switch (reg) { case PCIR_DEVICE: config = get_config_value_node(pci_regs, "device"); + host = host_conf != NULL ? host_conf->pc_device : 0; break; case PCIR_VENDOR: config = get_config_value_node(pci_regs, "vendor"); + host = host_conf != NULL ? host_conf->pc_vendor : 0; break; case PCIR_REVID: config = get_config_value_node(pci_regs, "revid"); + host = host_conf != NULL ? host_conf->pc_revid : 0; break; case PCIR_SUBVEND_0: config = get_config_value_node(pci_regs, "subvendor"); + host = host_conf != NULL ? host_conf->pc_subvendor : 0; break; case PCIR_SUBDEV_0: config = get_config_value_node(pci_regs, "subdevice"); + host = host_conf != NULL ? host_conf->pc_subdevice : 0; break; default: return (-1); } if (config == NULL) { - return def; - } else if (host_sel != NULL && strcmp(config, "host") == 0) { -#ifdef __amd64__ - return pci_host_read_config(host_sel, reg, size); -#else - errx(1, "cannot fetch host PCI configuration"); -#endif + return (def); + } else if (host_conf != NULL && strcmp(config, "host") == 0) { + return (host); } else { - return strtol(config, NULL, 16); + return (strtol(config, NULL, 16)); } } diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h index 063b4b84e044..29e9717c1593 100644 --- a/usr.sbin/bhyve/pci_emul.h +++ b/usr.sbin/bhyve/pci_emul.h @@ -230,7 +230,7 @@ void pci_walk_lintr(int bus, pci_lintr_cb cb, void *arg); int init_pci(struct vmctx *ctx); void pci_callback(void); -uint32_t pci_config_read_reg(const struct pcisel *host_sel, nvlist_t *nvl, +uint32_t pci_config_read_reg(const struct pci_conf *host_conf, nvlist_t *nvl, uint32_t reg, uint8_t size, uint32_t def); int pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, enum pcibar_type type, uint64_t size);