The Hyper-V DRM driver tries to free MMIO region on removing
the device regardless of VM type, while Gen1 VMs don't use MMIO
and hence causing the kernel to crash on a NULL pointer dereference.
Fix this by making deallocating MMIO only on Gen2 machines and implement
removal for Gen1
Fixes: 76c56a5affeb ("drm/hyperv: Add DRM driver for hyperv synthetic video device")
Signed-off-by: Mohammed Gamal <[email protected]>
---
drivers/gpu/drm/hyperv/hyperv_drm_drv.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
index cd818a629183..9f923beb7d8d 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
@@ -225,12 +225,29 @@ static int hyperv_vmbus_remove(struct hv_device *hdev)
{
struct drm_device *dev = hv_get_drvdata(hdev);
struct hyperv_drm_device *hv = to_hv(dev);
+ struct pci_dev *pdev;
drm_dev_unplug(dev);
drm_atomic_helper_shutdown(dev);
vmbus_close(hdev->channel);
hv_set_drvdata(hdev, NULL);
- vmbus_free_mmio(hv->mem->start, hv->fb_size);
+
+ /*
+ * Free allocated MMIO memory only on Gen2 VMs.
+ * On Gen1 VMs, release the PCI device
+ */
+ if (efi_enabled(EFI_BOOT)) {
+ vmbus_free_mmio(hv->mem->start, hv->fb_size);
+ } else {
+ pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
+ PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
+ if (!pdev) {
+ drm_err(dev, "Unable to find PCI Hyper-V video\n");
+ return -ENODEV;
+ }
+ pci_release_region(pdev, 0);
+ pci_dev_put(pdev);
+ }
return 0;
}
--
2.33.1
Thanks for the patch.
Reviewed-by: Deepak Rawat <[email protected]>
I will push this to drm-fixes, let me know otherwise.
Deepak
On Fri, 2021-11-19 at 12:29 +0100, Mohammed Gamal wrote:
> The Hyper-V DRM driver tries to free MMIO region on removing
> the device regardless of VM type, while Gen1 VMs don't use MMIO
> and hence causing the kernel to crash on a NULL pointer dereference.
>
> Fix this by making deallocating MMIO only on Gen2 machines and
> implement
> removal for Gen1
>
> Fixes: 76c56a5affeb ("drm/hyperv: Add DRM driver for hyperv synthetic
> video device")
>
> Signed-off-by: Mohammed Gamal <[email protected]>
> ---
> drivers/gpu/drm/hyperv/hyperv_drm_drv.c | 19 ++++++++++++++++++-
> 1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
> b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
> index cd818a629183..9f923beb7d8d 100644
> --- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
> +++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
> @@ -225,12 +225,29 @@ static int hyperv_vmbus_remove(struct hv_device
> *hdev)
> {
> struct drm_device *dev = hv_get_drvdata(hdev);
> struct hyperv_drm_device *hv = to_hv(dev);
> + struct pci_dev *pdev;
>
> drm_dev_unplug(dev);
> drm_atomic_helper_shutdown(dev);
> vmbus_close(hdev->channel);
> hv_set_drvdata(hdev, NULL);
> - vmbus_free_mmio(hv->mem->start, hv->fb_size);
> +
> + /*
> + * Free allocated MMIO memory only on Gen2 VMs.
> + * On Gen1 VMs, release the PCI device
> + */
> + if (efi_enabled(EFI_BOOT)) {
> + vmbus_free_mmio(hv->mem->start, hv->fb_size);
> + } else {
> + pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
> + PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
> + if (!pdev) {
> + drm_err(dev, "Unable to find PCI Hyper-V
> video\n");
> + return -ENODEV;
> + }
> + pci_release_region(pdev, 0);
> + pci_dev_put(pdev);
> + }
>
> return 0;
> }