Page MenuHomeFreeBSD

D28280.id101983.diff
No OneTemporary

D28280.id101983.diff

diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h
--- a/sys/dev/pci/pcireg.h
+++ b/sys/dev/pci/pcireg.h
@@ -1098,3 +1098,8 @@
#define PCIM_OSC_CTL_PCIE_PME 0x04 /* PCIe Native Power Mgt Events */
#define PCIM_OSC_CTL_PCIE_AER 0x08 /* PCIe Advanced Error Reporting */
#define PCIM_OSC_CTL_PCIE_CAP_STRUCT 0x10 /* Various Capability Structures */
+
+/*
+ * PCI Vendors
+ */
+#define PCI_VENDOR_INTEL 0x8086
diff --git a/usr.sbin/bhyve/bhyve_config.5 b/usr.sbin/bhyve/bhyve_config.5
--- a/usr.sbin/bhyve/bhyve_config.5
+++ b/usr.sbin/bhyve/bhyve_config.5
@@ -139,6 +139,26 @@
This value only works when loaded with UEFI mode for VNC, and
used a VNC client that don't support QEMU Extended Key Event
Message (e.g. TightVNC).
+.It Va lpc.pcir.vendor Ta integer Ta 0x8086 Ta
+Vendor id of the LPC bridge as hex number.
+On Intel systems the LPC bridge uses the physical vendor id
+as default value.
+.It Va lpc.pcir.device Ta integer Ta 0x7000 Ta
+Device id of the LPC bridge as hex number.
+On Intel systems the LPC bridge uses the physical device id
+as default value.
+.It Va lpc.pcir.revid Ta integer Ta 0 Ta
+Revision id of the LPC bridge as hex number.
+On Intel systems the LPC bridge uses the physical revision id
+as default value.
+.It Va lpc.pcir.subvendor Ta integer Ta 0 Ta
+Subvendor id of the LPC bridge as hex number.
+On Intel systems the LPC bridge uses the physical subvendor id
+as default value.
+.It Va lpc.pcir.subdevice Ta integer Ta 0 Ta
+Subdevice id of the LPC bridge as hex number.
+On Intel systems the LPC bridge uses the physical subdevice id
+as default value.
.It Va rtc.use_localtime Ta bool Ta true Ta
The real time clock uses the local time of the host.
If this is set to false, the real time clock uses UTC.
diff --git a/usr.sbin/bhyve/pci_lpc.c b/usr.sbin/bhyve/pci_lpc.c
--- a/usr.sbin/bhyve/pci_lpc.c
+++ b/usr.sbin/bhyve/pci_lpc.c
@@ -33,6 +33,7 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
+#include <sys/pciio.h>
#include <machine/vmm.h>
#include <machine/vmm_snapshot.h>
@@ -50,6 +51,7 @@
#include "pci_emul.h"
#include "pci_irq.h"
#include "pci_lpc.h"
+#include "pci_passthru.h"
#include "pctestdev.h"
#include "uart_emul.h"
@@ -446,11 +448,61 @@
if (lpc_init(ctx) != 0)
return (-1);
+ char value[16];
+
+ /* on Intel systems lpc is always connected to 0:1f.0 */
+ const struct pcisel sel = { .pc_dev = 0x1f };
+ if ((read_config(&sel, PCIR_VENDOR, 2) == PCI_VENDOR_INTEL) &&
+ (read_config(&sel, PCIR_CLASS, 1) == PCIC_BRIDGE) &&
+ (read_config(&sel, PCIR_SUBCLASS, 1) == PCIS_BRIDGE_ISA)) {
+ /*
+ * The VID, DID, REVID, SUBVID and SUBDID of lpc need to be
+ * aligned with the physical ones. Without these physical
+ * values, GPU passthrough of Intel integrated graphics devices
+ * won't work properly. The Intel GOP driver checks these values
+ * to proof that it runs on the correct platform.
+ */
+ snprintf(value, sizeof(value), "0x%04x",
+ read_config(&sel, PCIR_VENDOR, 2));
+ set_config_value_if_unset("lpc.pcir.vendor", value);
+ snprintf(value, sizeof(value), "0x%04x",
+ read_config(&sel, PCIR_DEVICE, 2));
+ set_config_value_if_unset("lpc.pcir.device", value);
+ snprintf(value, sizeof(value), "0x%02x",
+ read_config(&sel, PCIR_REVID, 1));
+ set_config_value_if_unset("lpc.pcir.revid", value);
+ snprintf(value, sizeof(value), "0x%04x",
+ read_config(&sel, PCIR_SUBVEND_0, 2));
+ set_config_value_if_unset("lpc.pcir.subvendor", value);
+ snprintf(value, sizeof(value), "0x%04x",
+ read_config(&sel, PCIR_SUBDEV_0, 2));
+ set_config_value_if_unset("lpc.pcir.subdevice", value);
+ }
+
+ snprintf(value, sizeof(value), "0x%04x", LPC_VENDOR);
+ set_config_value_if_unset("lpc.pcir.vendor", value);
+ snprintf(value, sizeof(value), "0x%04x", LPC_DEV);
+ set_config_value_if_unset("lpc.pcir.device", value);
+ snprintf(value, sizeof(value), "0x%02x", 0);
+ set_config_value_if_unset("lpc.pcir.revid", 0);
+ snprintf(value, sizeof(value), "0x%04x", 0);
+ set_config_value_if_unset("lpc.pcir.subvendor", 0);
+ snprintf(value, sizeof(value), "0x%04x", 0);
+ set_config_value_if_unset("lpc.pcir.subdevice", 0);
+
/* initialize config space */
- pci_set_cfgdata16(pi, PCIR_DEVICE, LPC_DEV);
- pci_set_cfgdata16(pi, PCIR_VENDOR, LPC_VENDOR);
+ pci_set_cfgdata16(pi, PCIR_VENDOR,
+ strtol(get_config_value("lpc.pcir.vendor"), NULL, 16));
+ pci_set_cfgdata16(pi, PCIR_DEVICE,
+ strtol(get_config_value("lpc.pcir.device"), NULL, 16));
pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_BRIDGE);
pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_BRIDGE_ISA);
+ pci_set_cfgdata8(pi, PCIR_REVID,
+ strtol(get_config_value("lpc.pcir.revid"), NULL, 16));
+ pci_set_cfgdata16(pi, PCIR_SUBVEND_0,
+ strtol(get_config_value("lpc.pcir.subvendor"), NULL, 16));
+ pci_set_cfgdata16(pi, PCIR_SUBDEV_0,
+ strtol(get_config_value("lpc.pcir.subdevice"), NULL, 16));
lpc_bridge = pi;
diff --git a/usr.sbin/bhyve/pci_passthru.h b/usr.sbin/bhyve/pci_passthru.h
new file mode 100644
--- /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);
diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c
--- a/usr.sbin/bhyve/pci_passthru.c
+++ b/usr.sbin/bhyve/pci_passthru.c
@@ -61,12 +61,11 @@
#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 @@
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 @@
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));
@@ -638,40 +668,20 @@
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) { \

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 21, 8:31 PM (8 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31931895
Default Alt Text
D28280.id101983.diff (7 KB)

Event Timeline