drm/i915/gt: Always try to reserve GGTT address 0x0
authorChris Wilson <chris@chris-wilson.co.uk>
Mon, 25 Jan 2021 12:50:33 +0000 (12:50 +0000)
committerJani Nikula <jani.nikula@intel.com>
Tue, 26 Jan 2021 13:45:54 +0000 (15:45 +0200)
Since writing to address 0 is a very common mistake, let's try to avoid
putting anything sensitive there.

References: https://gitlab.freedesktop.org/drm/intel/-/issues/2989
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210125125033.23656-1-chris@chris-wilson.co.uk
Cc: stable@vger.kernel.org
(cherry picked from commit 56b429cc584c6ed8b895d8d8540959655db1ff73)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
drivers/gpu/drm/i915/gt/intel_ggtt.c

index cf94525..db8c66d 100644 (file)
@@ -526,16 +526,39 @@ static int init_ggtt(struct i915_ggtt *ggtt)
 
        mutex_init(&ggtt->error_mutex);
        if (ggtt->mappable_end) {
-               /* Reserve a mappable slot for our lockless error capture */
-               ret = drm_mm_insert_node_in_range(&ggtt->vm.mm,
-                                                 &ggtt->error_capture,
-                                                 PAGE_SIZE, 0,
-                                                 I915_COLOR_UNEVICTABLE,
-                                                 0, ggtt->mappable_end,
-                                                 DRM_MM_INSERT_LOW);
-               if (ret)
-                       return ret;
+               /*
+                * Reserve a mappable slot for our lockless error capture.
+                *
+                * We strongly prefer taking address 0x0 in order to protect
+                * other critical buffers against accidental overwrites,
+                * as writing to address 0 is a very common mistake.
+                *
+                * Since 0 may already be in use by the system (e.g. the BIOS
+                * framebuffer), we let the reservation fail quietly and hope
+                * 0 remains reserved always.
+                *
+                * If we fail to reserve 0, and then fail to find any space
+                * for an error-capture, remain silent. We can afford not
+                * to reserve an error_capture node as we have fallback
+                * paths, and we trust that 0 will remain reserved. However,
+                * the only likely reason for failure to insert is a driver
+                * bug, which we expect to cause other failures...
+                */
+               ggtt->error_capture.size = I915_GTT_PAGE_SIZE;
+               ggtt->error_capture.color = I915_COLOR_UNEVICTABLE;
+               if (drm_mm_reserve_node(&ggtt->vm.mm, &ggtt->error_capture))
+                       drm_mm_insert_node_in_range(&ggtt->vm.mm,
+                                                   &ggtt->error_capture,
+                                                   ggtt->error_capture.size, 0,
+                                                   ggtt->error_capture.color,
+                                                   0, ggtt->mappable_end,
+                                                   DRM_MM_INSERT_LOW);
        }
+       if (drm_mm_node_allocated(&ggtt->error_capture))
+               drm_dbg(&ggtt->vm.i915->drm,
+                       "Reserved GGTT:[%llx, %llx] for use by error capture\n",
+                       ggtt->error_capture.start,
+                       ggtt->error_capture.start + ggtt->error_capture.size);
 
        /*
         * The upper portion of the GuC address space has a sizeable hole
@@ -548,9 +571,9 @@ static int init_ggtt(struct i915_ggtt *ggtt)
 
        /* Clear any non-preallocated blocks */
        drm_mm_for_each_hole(entry, &ggtt->vm.mm, hole_start, hole_end) {
-               drm_dbg_kms(&ggtt->vm.i915->drm,
-                           "clearing unused GTT space: [%lx, %lx]\n",
-                           hole_start, hole_end);
+               drm_dbg(&ggtt->vm.i915->drm,
+                       "clearing unused GTT space: [%lx, %lx]\n",
+                       hole_start, hole_end);
                ggtt->vm.clear_range(&ggtt->vm, hole_start,
                                     hole_end - hole_start);
        }