aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/hyperv
diff options
context:
space:
mode:
authorWei Hu <whu@FreeBSD.org>2020-07-30 07:26:11 +0000
committerWei Hu <whu@FreeBSD.org>2020-07-30 07:26:11 +0000
commitc565776195f2f2b62427af07f6b1a9b7670cbc1f (patch)
treeb36e8ceac1a9e04a64a167f1cc16b6412fbbaa6e /sys/dev/hyperv
parentd3e63e8eb23a3dd4e9d36af2a725063c99687067 (diff)
downloadsrc-c565776195f2f2b62427af07f6b1a9b7670cbc1f.tar.gz
src-c565776195f2f2b62427af07f6b1a9b7670cbc1f.zip
Prevent framebuffer mmio space from being allocated to other devices on HyperV.
On Gen2 VMs, Hyper-V provides mmio space for framebuffer. This mmio address range is not useable for other PCI devices. Currently only efifb driver is using this range without reserving it from system. Therefore, vmbus driver reserves it before any other PCI device drivers start to request mmio addresses. PR: 222996 Submitted by: weh@microsoft.com Reported by: dmitry_kuleshov@ukr.net Reviewed by: decui@microsoft.com Sponsored by: Microsoft
Notes
Notes: svn path=/head/; revision=363689
Diffstat (limited to 'sys/dev/hyperv')
-rw-r--r--sys/dev/hyperv/vmbus/vmbus.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/sys/dev/hyperv/vmbus/vmbus.c b/sys/dev/hyperv/vmbus/vmbus.c
index 9d4f5e77fa97..38e9cd7b4c26 100644
--- a/sys/dev/hyperv/vmbus/vmbus.c
+++ b/sys/dev/hyperv/vmbus/vmbus.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
+#include <sys/linker.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
@@ -46,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/intr_machdep.h>
+#include <machine/metadata.h>
#include <machine/md_var.h>
#include <machine/resource.h>
#include <x86/include/apicvar.h>
@@ -1332,12 +1334,66 @@ vmbus_get_mmio_res(device_t dev)
vmbus_get_mmio_res_pass(dev, parse_32);
}
+/*
+ * On Gen2 VMs, Hyper-V provides mmio space for framebuffer.
+ * This mmio address range is not useable for other PCI devices.
+ * Currently only efifb driver is using this range without reserving
+ * it from system.
+ * Therefore, vmbus driver reserves it before any other PCI device
+ * drivers start to request mmio addresses.
+ */
+static struct resource *hv_fb_res;
+
+static void
+vmbus_fb_mmio_res(device_t dev)
+{
+ struct efi_fb *efifb;
+ caddr_t kmdp;
+
+ struct vmbus_softc *sc = device_get_softc(dev);
+ int rid = 0;
+
+ kmdp = preload_search_by_type("elf kernel");
+ if (kmdp == NULL)
+ kmdp = preload_search_by_type("elf64 kernel");
+ efifb = (struct efi_fb *)preload_search_info(kmdp,
+ MODINFO_METADATA | MODINFOMD_EFI_FB);
+ if (efifb == NULL) {
+ if (bootverbose)
+ device_printf(dev,
+ "fb has no preloaded kernel efi information\n");
+ /* We are on Gen1 VM, just return. */
+ return;
+ } else {
+ if (bootverbose)
+ device_printf(dev,
+ "efifb: fb_addr: %#jx, size: %#jx, "
+ "actual size needed: 0x%x\n",
+ efifb->fb_addr, efifb->fb_size,
+ (int) efifb->fb_height * efifb->fb_width);
+ }
+
+ hv_fb_res = pcib_host_res_alloc(&sc->vmbus_mmio_res, dev,
+ SYS_RES_MEMORY, &rid,
+ efifb->fb_addr, efifb->fb_addr + efifb->fb_size, efifb->fb_size,
+ RF_ACTIVE | rman_make_alignment_flags(PAGE_SIZE));
+
+ if (hv_fb_res && bootverbose)
+ device_printf(dev,
+ "successfully reserved memory for framebuffer "
+ "starting at %#jx, size %#jx\n",
+ efifb->fb_addr, efifb->fb_size);
+}
+
static void
vmbus_free_mmio_res(device_t dev)
{
struct vmbus_softc *sc = device_get_softc(dev);
pcib_host_res_free(dev, &sc->vmbus_mmio_res);
+
+ if (hv_fb_res)
+ hv_fb_res = NULL;
}
#endif /* NEW_PCIB */
@@ -1387,6 +1443,7 @@ vmbus_doattach(struct vmbus_softc *sc)
#ifdef NEW_PCIB
vmbus_get_mmio_res(sc->vmbus_dev);
+ vmbus_fb_mmio_res(sc->vmbus_dev);
#endif
sc->vmbus_flags |= VMBUS_FLAG_ATTACHED;