Page MenuHomeFreeBSD

D28280.id99009.diff
No OneTemporary

D28280.id99009.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
@@ -133,6 +133,21 @@
.It Va gdb.wait Ta bool Ta false Ta
If the debug server is enabled, wait for a debugger to connect
before starting the guest.
+.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/config.h b/usr.sbin/bhyve/config.h
--- a/usr.sbin/bhyve/config.h
+++ b/usr.sbin/bhyve/config.h
@@ -99,12 +99,23 @@
void set_config_value_node(nvlist_t *parent, const char *name,
const char *value);
+/*
+ * Similar to set_config_value_node but only sets value if it's unset yet.
+ */
+void set_config_value_node_if_unset(nvlist_t *const parent,
+ const char *const name, const char *const value);
+
/*
* Similar to set_config_value_node but expects a full path to the
* leaf node.
*/
void set_config_value(const char *path, const char *value);
+/*
+ * Similar to set_config_value but only sets the value if it's unset yet.
+ */
+void set_config_value_if_unset(const char *const path, const char *const value);
+
/* Convenience wrappers for boolean variables. */
bool get_config_bool(const char *path);
bool get_config_bool_node(const nvlist_t *parent, const char *name);
diff --git a/usr.sbin/bhyve/config.c b/usr.sbin/bhyve/config.c
--- a/usr.sbin/bhyve/config.c
+++ b/usr.sbin/bhyve/config.c
@@ -135,6 +135,17 @@
nvlist_add_string(parent, name, value);
}
+void
+set_config_value_node_if_unset(nvlist_t *const parent, const char *const name,
+ const char *const value)
+{
+ if (get_config_value_node(parent, name) != NULL) {
+ return;
+ }
+
+ set_config_value_node(parent, name, value);
+}
+
void
set_config_value(const char *path, const char *value)
{
@@ -167,6 +178,16 @@
set_config_value_node(nvl, name, value);
}
+void
+set_config_value_if_unset(const char *const path, const char *const value)
+{
+ if (get_config_value(path) != NULL) {
+ return;
+ }
+
+ set_config_value(path, value);
+}
+
static const char *
get_raw_config_value(const char *path)
{
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,57 @@
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) {
+ /*
+ * The VID, DID, REVID, SUBVID and SUBDID of lpc need to be
+ * aligned with the physical ones. Without these physical
+ * values, GVT-d GOP driver couldn't work.
+ */
+ 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,31 @@
+/*-
+ * 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 <sys/pciio.h>
+
+#include <vmmapi.h>
+
+#include "pci_emul.h"
+
+struct passthru_softc {
+ struct pci_devinst *psc_pi;
+ struct pcibar psc_bar[PCI_BARMAX + 1];
+ struct {
+ int capoff;
+ int msgctrl;
+ int emulated;
+ } psc_msi;
+ struct {
+ int capoff;
+ } psc_msix;
+ struct pcisel psc_sel;
+};
+
+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"
@@ -79,20 +78,6 @@
static int pcifd = -1;
-struct passthru_softc {
- struct pci_devinst *psc_pi;
- struct pcibar psc_bar[PCI_BARMAX + 1];
- struct {
- int capoff;
- int msgctrl;
- int emulated;
- } psc_msi;
- struct {
- int capoff;
- } psc_msix;
- struct pcisel psc_sel;
-};
-
static int
msi_caplen(int msgctrl)
{
@@ -115,9 +100,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 +143,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));
@@ -630,40 +646,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
Fri, Jan 23, 3:47 AM (4 h, 23 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27874011
Default Alt Text
D28280.id99009.diff (9 KB)

Event Timeline