git: 4a9bf50f408e - main - bhyve: read out graphics stolen memory address and size

From: Corvin Köhne <corvink_at_FreeBSD.org>
Date: Fri, 16 Jun 2023 06:14:14 UTC
The branch main has been updated by corvink:

URL: https://cgit.FreeBSD.org/src/commit/?id=4a9bf50f408eb9f1acc220dba2b260ec610fd15b

commit 4a9bf50f408eb9f1acc220dba2b260ec610fd15b
Author:     Corvin Köhne <corvink@FreeBSD.org>
AuthorDate: 2023-05-11 08:53:15 +0000
Commit:     Corvin Köhne <corvink@FreeBSD.org>
CommitDate: 2023-06-16 05:53:46 +0000

    bhyve: read out graphics stolen memory address and size
    
    This is the first step to emulate the graphics stolen memory register.
    
    Note that the graphics stolen memory is somehow confusing. On the one
    hand the Intel Open Source HD Graphics Programmers' Reference Manual
    states that it's only GPU accessible. As the CPU can't access the area,
    the guest shouldn't need it. On the other hand, the Intel GOP driver
    refuses to work properly, if it's not set to a proper address.
    
    Intel itself maps it into the guest by EPT [1]. At the moment, we're not
    aware of any situation where this EPT mapping is required, so we don't
    do it yet.
    
    Intel also states that the Windows driver for Tiger Lake reads the
    address of the graphics stolen memory [2]. As the GVT-d code doesn't
    support Tiger Lake in its first implementation, we can't check how it
    behaves. We should keep an eye on it.
    
    [1]
    https://github.com/projectacrn/acrn-hypervisor/blob/e28d6fbfdfd556ff1bc3ff330e41d4ddbaa0f897/devicemodel/hw/pci/passthrough.c#L655-L657
    [2]
    https://github.com/projectacrn/acrn-hypervisor/blob/e28d6fbfdfd556ff1bc3ff330e41d4ddbaa0f897/devicemodel/hw/pci/passthrough.c#L626-L629
    
    Reviewed by:            markj
    MFC after:              1 week
    Sponsored by:           Beckhoff Automation GmbH & Co. KG
    Differential Revision:  https://reviews.freebsd.org/D40039
---
 usr.sbin/bhyve/pci_gvt-d.c | 73 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 72 insertions(+), 1 deletion(-)

diff --git a/usr.sbin/bhyve/pci_gvt-d.c b/usr.sbin/bhyve/pci_gvt-d.c
index 767b8ee3127f..0be740921c92 100644
--- a/usr.sbin/bhyve/pci_gvt-d.c
+++ b/usr.sbin/bhyve/pci_gvt-d.c
@@ -6,6 +6,9 @@
  */
 
 #include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
 
 #include <dev/pci/pcireg.h>
 
@@ -16,6 +19,8 @@
 
 #define PCI_VENDOR_INTEL 0x8086
 
+#define GVT_D_MAP_GSM 0
+
 static int
 gvt_d_probe(struct pci_devinst *const pi)
 {
@@ -36,12 +41,78 @@ gvt_d_probe(struct pci_devinst *const pi)
 	return (0);
 }
 
+/*
+ * Note that the graphics stolen memory is somehow confusing. On the one hand
+ * the Intel Open Source HD Graphics Programmers' Reference Manual states that
+ * it's only GPU accessible. As the CPU can't access the area, the guest
+ * shouldn't need it. On the other hand, the Intel GOP driver refuses to work
+ * properly, if it's not set to a proper address.
+ *
+ * Intel itself maps it into the guest by EPT [1]. At the moment, we're not
+ * aware of any situation where this EPT mapping is required, so we don't do it
+ * yet.
+ *
+ * Intel also states that the Windows driver for Tiger Lake reads the address of
+ * the graphics stolen memory [2]. As the GVT-d code doesn't support Tiger Lake
+ * in its first implementation, we can't check how it behaves. We should keep an
+ * eye on it.
+ *
+ * [1]
+ * https://github.com/projectacrn/acrn-hypervisor/blob/e28d6fbfdfd556ff1bc3ff330e41d4ddbaa0f897/devicemodel/hw/pci/passthrough.c#L655-L657
+ * [2]
+ * https://github.com/projectacrn/acrn-hypervisor/blob/e28d6fbfdfd556ff1bc3ff330e41d4ddbaa0f897/devicemodel/hw/pci/passthrough.c#L626-L629
+ */
 static int
-gvt_d_init(struct pci_devinst *const pi __unused, nvlist_t *const nvl __unused)
+gvt_d_setup_gsm(struct pci_devinst *const pi)
 {
+	struct passthru_softc *sc;
+	struct passthru_mmio_mapping *gsm;
+	size_t sysctl_len;
+	int error;
+
+	sc = pi->pi_arg;
+
+	gsm = passthru_get_mmio(sc, GVT_D_MAP_GSM);
+	if (gsm == NULL) {
+		warnx("%s: Unable to access gsm", __func__);
+		return (-1);
+	}
+
+	sysctl_len = sizeof(gsm->hpa);
+	error = sysctlbyname("hw.intel_graphics_stolen_base", &gsm->hpa,
+	    &sysctl_len, NULL, 0);
+	if (error) {
+		warn("%s: Unable to get graphics stolen memory base",
+		    __func__);
+		return (-1);
+	}
+	sysctl_len = sizeof(gsm->len);
+	error = sysctlbyname("hw.intel_graphics_stolen_size", &gsm->len,
+	    &sysctl_len, NULL, 0);
+	if (error) {
+		warn("%s: Unable to get graphics stolen memory length",
+		    __func__);
+		return (-1);
+	}
+	gsm->hva = NULL; /* unused */
+
 	return (0);
 }
 
+static int
+gvt_d_init(struct pci_devinst *const pi, nvlist_t *const nvl __unused)
+{
+	int error;
+
+	if ((error = gvt_d_setup_gsm(pi)) != 0) {
+		warnx("%s: Unable to setup Graphics Stolen Memory", __func__);
+		goto done;
+	}
+
+done:
+	return (error);
+}
+
 static void
 gvt_d_deinit(struct pci_devinst *const pi __unused)
 {