diff mbox

[BUG] Segv in radeon drm

Message ID ce6bcc70-20b8-8aa9-8094-7bbf164b6eed@alstadheim.priv.no (mailing list archive)
State New, archived
Headers show

Commit Message

Håkon Alstadheim July 3, 2017, 7:15 a.m. UTC
Not sure who this should go to, but running linux as domU under Xen
triggers this bug.

modprobe radeon on a linux domU wich has a "VGA compatible controller:
Advanced Micro Devices, Inc. [AMD/ATI] Curacao PRO [Radeon R7 370 / R9
270/370 OEM]" -card passed through to it, causes a NULL dereference in
the kernel. Also graphics-card is non-functional causing X to hang,
usually forcing me to "xl destroy <vm>". I have succeded in loading the
module in domU by giving radeon module various *pm=0 -options. Not
tested further for exactly which option is needed.

I have no idea what dev->pdev->bus->self is, or which invariants it
should be subject to, so the correct fix is likely somewhere else.

Below patch, which applies to all kernel-versions I have tried including
4.12, allows module to load:
-----------------
------------------------------------------------------------------
The module loads fine on bare metal _without_ the patch.
In domU, output to console during load is (with patch):
------------------------------------------------------------------
[drm] radeon: 2048M of VRAM memory ready
[drm] radeon: 2048M of GTT memory ready.
[drm] Loading pitcairn Microcode
[drm] Internal thermal controller with fan control
[drm] invalid dev->pdev->bus->self
[drm] radeon: dpm initialized
[drm] Found VCE firmware/feedback version 50.0.1 / 17!
-----------------------------------------------------------------

---
Håkon
diff mbox

Patch

--- drivers/gpu/drm/drm_pci.c.orig	2017-04-22 21:56:04.634330554 +0200
+++ drivers/gpu/drm/drm_pci.c	2017-06-18 21:28:18.473439278 +0200
@@ -337,11 +337,28 @@ 
 	u32 lnkcap, lnkcap2;

 	*mask = 0;
-	if (!dev->pdev)
-		return -EINVAL;
-
+	if (!dev->pdev) {
+	  DRM_INFO("invalid dev->pdev\n");
+	  return -EINVAL;
+	}
+	
+	if (!dev->pdev->bus) {
+	  DRM_INFO("invalid dev->pdev->bus\n");
+	  return -EINVAL;
+	}
+	
+	if (!dev->pdev->bus->self) {
+	  DRM_INFO("invalid dev->pdev->bus->self\n");
+	  return -EINVAL;
+	}
+	
 	root = dev->pdev->bus->self;

+	if (!root->vendor) {
+	  DRM_INFO("invalid root->vendor\n");
+	  return -EINVAL;
+	}
+
 	/* we've been informed via and serverworks don't make the cut */
 	if (root->vendor == PCI_VENDOR_ID_VIA ||
 	    root->vendor == PCI_VENDOR_ID_SERVERWORKS)