[PATCH] drm/i915: Detect invalid pages for SandyBridge

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



As SandyBridge returns garbage when decoding certain addresses through
the GTT (all memory below 1MiB and a very small number of individual
pages) we need to prevent the GPU from utilizing those pages. The
ultimate goal would be to prevent our allocator from handing us those
pages, but that is a longer term project. In the short term, we can
detect when we attempt to bind those pages to the GPU and return an
error to the application rather than hang the GPU and potentially the
system.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c |   40 ++++++++++++++++++++++++++++++++---
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index d9d3fc7..5c7ccfd 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -306,17 +306,51 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
 	intel_gtt_chipset_flush();
 }
 
+static bool
+gen6_valid_addresses(struct drm_i915_gem_object *obj)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(obj->pages->sgl, sg, obj->pages->nents, i) {
+		dma_addr_t addr = sg_dma_address(sg);
+		if (WARN(addr < 0x100000 ||
+			 addr == 0x20050000 ||
+			 addr == 0x20110000 ||
+			 addr == 0x20130000 ||
+			 addr == 0x20138000 ||
+			 addr == 0x40004000,
+			 "object references unaddressable physical pages: addr=%x",
+			 (u32)addr))
+			return false;
+	}
+
+	return true;
+}
+
 int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
 {
-	if (obj->has_dma_mapping)
-		return 0;
+	int ret;
 
-	if (!dma_map_sg(&obj->base.dev->pdev->dev,
+	if (!obj->has_dma_mapping &&
+	    !dma_map_sg(&obj->base.dev->pdev->dev,
 			obj->pages->sgl, obj->pages->nents,
 			PCI_DMA_BIDIRECTIONAL))
 		return -ENOSPC;
 
+	if (IS_GEN6(obj->base.dev) && !gen6_valid_addresses(obj)) {
+		ret = -EFAULT;
+		goto unmap;
+	}
+
 	return 0;
+
+unmap:
+	if (!obj->has_dma_mapping)
+		dma_unmap_sg(&obj->base.dev->pdev->dev,
+			     obj->pages->sgl, obj->pages->nents,
+			     PCI_DMA_BIDIRECTIONAL);
+	return ret;
 }
 
 void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,
-- 
1.7.10.4



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux