git: 7c6d3eb00932 - stable/13 - bhyve: export funcs for read/write pci config

From: Emmanuel Vadot <manu_at_FreeBSD.org>
Date: Mon, 16 May 2022 12:50:10 UTC
The branch stable/13 has been updated by manu:

URL: https://cgit.FreeBSD.org/src/commit/?id=7c6d3eb00932e79296664ed561f51cf618af03fd

commit 7c6d3eb00932e79296664ed561f51cf618af03fd
Author:     Corvin Köhne <CorvinK@beckhoff.com>
AuthorDate: 2022-03-10 10:26:19 +0000
Commit:     Emmanuel Vadot <manu@FreeBSD.org>
CommitDate: 2022-05-16 12:41:14 +0000

    bhyve: export funcs for read/write pci config
    
    Export functions for reading and writing the pci config space from passthru
    device to be used by other devices.
    This is required for lpc devices to set their vendor/device ids to their
    physical values.
    Otherwise, GPU passthrough for integrated Intel GPUs won't work properly.
    
    Differential Revision:  https://reviews.freebsd.org/D33769
    Reviewed by:    markj
    Sponsored by:   Beckhoff Automation GmbH & Co. KG
    MFC after:      1 month
    
    (cherry picked from commit 563fd2240e13cfb53f6e5d50e9d1dc738b7c441e)
---
 usr.sbin/bhyve/pci_passthru.c | 62 +++++++++++++++++++++++++------------------
 usr.sbin/bhyve/pci_passthru.h | 15 +++++++++++
 2 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c
index 586a2da8aa05..3fe446f42eee 100644
--- a/usr.sbin/bhyve/pci_passthru.c
+++ b/usr.sbin/bhyve/pci_passthru.c
@@ -61,12 +61,11 @@ __FBSDID("$FreeBSD$");
 #include <unistd.h>
 
 #include <machine/vmm.h>
-#include <vmmapi.h>
 
 #include "config.h"
 #include "debug.h"
-#include "pci_emul.h"
 #include "mem.h"
+#include "pci_passthru.h"
 
 #ifndef _PATH_DEVPCI
 #define	_PATH_DEVPCI	"/dev/pci"
@@ -115,9 +114,36 @@ msi_caplen(int msgctrl)
 	return (len);
 }
 
-static uint32_t
+static int
+pcifd_init() {
+	pcifd = open(_PATH_DEVPCI, O_RDWR, 0);
+	if (pcifd < 0) {
+		warn("failed to open %s", _PATH_DEVPCI);
+		return (1);
+	}
+
+#ifndef WITHOUT_CAPSICUM
+	cap_rights_t pcifd_rights;
+	cap_rights_init(&pcifd_rights, CAP_IOCTL, CAP_READ, CAP_WRITE);
+	if (caph_rights_limit(pcifd, &pcifd_rights) == -1)
+		errx(EX_OSERR, "Unable to apply rights for sandbox");
+
+	const cap_ioctl_t pcifd_ioctls[] = { PCIOCREAD, PCIOCWRITE, PCIOCGETBAR,
+		PCIOCBARIO, PCIOCBARMMAP };
+	if (caph_ioctls_limit(pcifd, pcifd_ioctls, nitems(pcifd_ioctls)) == -1)
+		errx(EX_OSERR, "Unable to apply rights for sandbox");
+#endif
+
+	return (0);
+}
+
+uint32_t
 read_config(const struct pcisel *sel, long reg, int width)
 {
+	if (pcifd < 0 && pcifd_init()) {
+		return (0);
+	}
+
 	struct pci_io pi;
 
 	bzero(&pi, sizeof(pi));
@@ -131,9 +157,13 @@ read_config(const struct pcisel *sel, long reg, int width)
 		return (pi.pi_data);
 }
 
-static void
+void
 write_config(const struct pcisel *sel, long reg, int width, uint32_t data)
 {
+	if (pcifd < 0 && pcifd_init()) {
+		return;
+	}
+
 	struct pci_io pi;
 
 	bzero(&pi, sizeof(pi));
@@ -645,40 +675,20 @@ passthru_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl)
 	int bus, slot, func, error, memflags;
 	struct passthru_softc *sc;
 	const char *value;
-#ifndef WITHOUT_CAPSICUM
-	cap_rights_t rights;
-	cap_ioctl_t pci_ioctls[] =
-	    { PCIOCREAD, PCIOCWRITE, PCIOCGETBAR, PCIOCBARIO, PCIOCBARMMAP };
-#endif
 
 	sc = NULL;
 	error = 1;
 
-#ifndef WITHOUT_CAPSICUM
-	cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_WRITE);
-#endif
-
 	memflags = vm_get_memflags(ctx);
 	if (!(memflags & VM_MEM_F_WIRED)) {
 		warnx("passthru requires guest memory to be wired");
 		return (error);
 	}
 
-	if (pcifd < 0) {
-		pcifd = open(_PATH_DEVPCI, O_RDWR, 0);
-		if (pcifd < 0) {
-			warn("failed to open %s", _PATH_DEVPCI);
-			return (error);
-		}
+	if (pcifd < 0 && pcifd_init()) {
+		return (error);
 	}
 
-#ifndef WITHOUT_CAPSICUM
-	if (caph_rights_limit(pcifd, &rights) == -1)
-		errx(EX_OSERR, "Unable to apply rights for sandbox");
-	if (caph_ioctls_limit(pcifd, pci_ioctls, nitems(pci_ioctls)) == -1)
-		errx(EX_OSERR, "Unable to apply rights for sandbox");
-#endif
-
 #define GET_INT_CONFIG(var, name) do {					\
 	value = get_config_value_node(nvl, name);			\
 	if (value == NULL) {						\
diff --git a/usr.sbin/bhyve/pci_passthru.h b/usr.sbin/bhyve/pci_passthru.h
new file mode 100644
index 000000000000..bdc8dc3cd0e2
--- /dev/null
+++ b/usr.sbin/bhyve/pci_passthru.h
@@ -0,0 +1,15 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2020 Beckhoff Automation GmbH & Co. KG
+ * Author: Corvin Köhne <c.koehne@beckhoff.com>
+ */
+
+#pragma once
+
+#include <vmmapi.h>
+
+#include "pci_emul.h"
+
+uint32_t read_config(const struct pcisel *sel, long reg, int width);
+void write_config(const struct pcisel *sel, long reg, int width, uint32_t data);