Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109171938
D45337.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D45337.diff
View Options
diff --git a/usr.sbin/bhyve/amd64/pci_gvt-d.c b/usr.sbin/bhyve/amd64/pci_gvt-d.c
--- a/usr.sbin/bhyve/amd64/pci_gvt-d.c
+++ b/usr.sbin/bhyve/amd64/pci_gvt-d.c
@@ -39,6 +39,7 @@
#define GVT_D_MAP_GSM 0
#define GVT_D_MAP_OPREGION 1
+#define GVT_D_MAP_VBT 2
static int
gvt_d_probe(struct pci_devinst *const pi)
@@ -177,13 +178,78 @@
passthru_cfgwrite_emulate));
}
+static int
+gvt_d_setup_vbt(struct pci_devinst *const pi, int memfd, uint64_t vbt_hpa,
+ uint64_t vbt_len, vm_paddr_t *vbt_gpa)
+{
+ struct passthru_softc *sc;
+ struct passthru_mmio_mapping *vbt;
+
+ sc = pi->pi_arg;
+
+ vbt = passthru_get_mmio(sc, GVT_D_MAP_VBT);
+ if (vbt == NULL) {
+ warnx("%s: Unable to access VBT", __func__);
+ return (-1);
+ }
+
+ vbt->hpa = vbt_hpa;
+ vbt->len = vbt_len;
+
+ vbt->hva = mmap(NULL, vbt->len, PROT_READ, MAP_SHARED, memfd, vbt->hpa);
+ if (vbt->hva == MAP_FAILED) {
+ warn("%s: Unable to map VBT", __func__);
+ return (-1);
+ }
+
+ vbt->gpa = gvt_d_alloc_mmio_memory(vbt->hpa, vbt->len,
+ E820_ALIGNMENT_NONE, E820_TYPE_NVS);
+ if (vbt->gpa == 0) {
+ warnx(
+ "%s: Unable to add VBT to E820 table (hpa 0x%lx len 0x%lx)",
+ __func__, vbt->hpa, vbt->len);
+ munmap(vbt->hva, vbt->len);
+ e820_dump_table();
+ return (-1);
+ }
+ vbt->gva = vm_map_gpa(pi->pi_vmctx, vbt->gpa, vbt->len);
+ if (vbt->gva == NULL) {
+ warnx("%s: Unable to map guest VBT", __func__);
+ munmap(vbt->hva, vbt->len);
+ return (-1);
+ }
+
+ if (vbt->gpa != vbt->hpa) {
+ /*
+ * A 1:1 host to guest mapping is not required but this could
+ * change in the future.
+ */
+ warnx(
+ "Warning: Unable to reuse host address of VBT. GPU passthrough might not work properly.");
+ }
+
+ memcpy(vbt->gva, vbt->hva, vbt->len);
+
+ /*
+ * Return the guest physical address. It's used to patch the OpRegion
+ * properly.
+ */
+ *vbt_gpa = vbt->gpa;
+
+ return (0);
+}
+
static int
gvt_d_setup_opregion(struct pci_devinst *const pi)
{
struct passthru_softc *sc;
struct passthru_mmio_mapping *opregion;
+ struct igd_opregion *opregion_ptr;
struct igd_opregion_header *header;
+ vm_paddr_t vbt_gpa = 0;
+ vm_paddr_t vbt_hpa;
uint64_t asls;
+ int error = 0;
int memfd;
sc = pi->pi_arg;
@@ -236,6 +302,39 @@
close(memfd);
return (-1);
}
+
+ opregion_ptr = (struct igd_opregion *)opregion->hva;
+ if (opregion_ptr->mbox3.rvda != 0) {
+ /*
+ * OpRegion v2.0 contains a physical address to the VBT. This
+ * address is useless in a guest environment. It's possible to
+ * patch that but we don't support that yet. So, the only thing
+ * we can do is give up.
+ */
+ if (opregion_ptr->header.over == 0x02000000) {
+ warnx(
+ "%s: VBT lays outside OpRegion. That's not yet supported for a version 2.0 OpRegion",
+ __func__);
+ close(memfd);
+ return (-1);
+ }
+ vbt_hpa = opregion->hpa + opregion_ptr->mbox3.rvda;
+ if (vbt_hpa < opregion->hpa) {
+ warnx(
+ "%s: overflow when calculating VBT address (OpRegion @ 0x%lx, RVDA = 0x%lx)",
+ __func__, opregion->hpa, opregion_ptr->mbox3.rvda);
+ close(memfd);
+ return (-1);
+ }
+
+ if ((error = gvt_d_setup_vbt(pi, memfd, vbt_hpa,
+ opregion_ptr->mbox3.rvds, &vbt_gpa)) != 0) {
+ munmap(opregion->hva, opregion->len);
+ close(memfd);
+ return (error);
+ }
+ }
+
close(memfd);
opregion->gpa = gvt_d_alloc_mmio_memory(opregion->hpa, opregion->len,
@@ -263,6 +362,20 @@
memcpy(opregion->gva, opregion->hva, opregion->len);
+ /*
+ * Patch the VBT address to match our guest physical address.
+ */
+ if (vbt_gpa != 0) {
+ if (vbt_gpa < opregion->gpa) {
+ warnx(
+ "%s: invalid guest VBT address 0x%16lx (OpRegion @ 0x%16lx)",
+ __func__, vbt_gpa, opregion->gpa);
+ return (-1);
+ }
+
+ ((struct igd_opregion *)opregion->gva)->mbox3.rvda = vbt_gpa - opregion->gpa;
+ }
+
pci_set_cfgdata32(pi, PCIR_ASLS_CTL, opregion->gpa);
return (set_pcir_handler(sc, PCIR_ASLS_CTL, 4, passthru_cfgread_emulate,
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
@@ -72,7 +72,7 @@
#define MSIX_TABLE_COUNT(ctrl) (((ctrl) & PCIM_MSIXCTRL_TABLE_SIZE) + 1)
#define MSIX_CAPLEN 12
-#define PASSTHRU_MMIO_MAX 2
+#define PASSTHRU_MMIO_MAX 3
static int pcifd = -1;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 2, 5:48 PM (21 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16407210
Default Alt Text
D45337.diff (4 KB)
Attached To
Mode
D45337: bhyve: support VBTs which lay outside of the OpRegion
Attached
Detach File
Event Timeline
Log In to Comment