@@ -1499,6 +1499,7 @@ static void i915_get_extra_instdone(struct drm_device *dev,
static struct drm_i915_error_object *
i915_error_object_create_sized(struct drm_i915_private *dev_priv,
struct drm_i915_gem_object *src,
+ struct i915_address_space *vm,
const int num_pages)
{
struct drm_i915_error_object *dst;
@@ -1512,8 +1513,7 @@ i915_error_object_create_sized(struct drm_i915_private *dev_priv,
if (dst == NULL)
return NULL;
- /* FIXME: must handle per faulty VM */
- reloc_offset = i915_gem_ggtt_offset(src);
+ reloc_offset = i915_gem_obj_offset(src, vm);
for (i = 0; i < num_pages; i++) {
unsigned long flags;
void *d;
@@ -1565,7 +1565,7 @@ i915_error_object_create_sized(struct drm_i915_private *dev_priv,
reloc_offset += PAGE_SIZE;
}
dst->page_count = num_pages;
- dst->gtt_offset = i915_gem_ggtt_offset(src);
+ dst->gtt_offset = i915_gem_obj_offset(src, vm);
return dst;
@@ -1575,8 +1575,9 @@ unwind:
kfree(dst);
return NULL;
}
-#define i915_error_object_create(dev_priv, src) \
+#define i915_error_object_create(dev_priv, src, vm) \
i915_error_object_create_sized((dev_priv), (src), \
+ vm, \
(src)->base.size>>PAGE_SHIFT)
static void
@@ -1617,14 +1618,14 @@ i915_error_state_free(struct kref *error_ref)
kfree(error);
}
static void capture_bo(struct drm_i915_error_buffer *err,
- struct drm_i915_gem_object *obj)
+ struct drm_i915_gem_object *obj,
+ struct i915_address_space *vm)
{
err->size = obj->base.size;
err->name = obj->base.name;
err->rseqno = obj->last_read_seqno;
err->wseqno = obj->last_write_seqno;
- /* FIXME: plumb the actual context into here to pull the right VM */
- err->gtt_offset = i915_gem_ggtt_offset(obj);
+ err->gtt_offset = i915_gem_obj_offset(obj, vm);
err->read_domains = obj->base.read_domains;
err->write_domain = obj->base.write_domain;
err->fence_reg = obj->fence_reg;
@@ -1647,7 +1648,7 @@ static u32 capture_active_bo(struct drm_i915_error_buffer *err,
int i = 0;
list_for_each_entry(vma, head, mm_list) {
- capture_bo(err++, vma->obj);
+ capture_bo(err++, vma->obj, vma->vm);
if (++i == count)
break;
}
@@ -1662,10 +1663,14 @@ static u32 capture_pinned_bo(struct drm_i915_error_buffer *err,
int i = 0;
list_for_each_entry(obj, head, global_list) {
+ struct i915_vma *vma;
if (obj->pin_count == 0)
continue;
- capture_bo(err++, obj);
+ /* Object may be pinned in multiple VMs, just take first */
+ vma = list_first_entry(&obj->vma_list, struct i915_vma,
+ vma_link);
+ capture_bo(err++, obj, vma->vm);
if (++i == count)
break;
}
@@ -1713,6 +1718,7 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
struct i915_vma *vma;
struct drm_i915_gem_object *obj;
u32 seqno;
+ u32 pp_db;
if (!ring->get_seqno)
return NULL;
@@ -1729,11 +1735,19 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
obj = ring->private;
if (acthd >= i915_gem_ggtt_offset(obj) &&
acthd < i915_gem_ggtt_offset(obj) + obj->base.size)
- return i915_error_object_create(dev_priv, obj);
+ return i915_error_object_create(dev_priv, obj,
+ &dev_priv->gtt.base);
}
+ pp_db = I915_READ(RING_PP_DIR_BASE(ring));
seqno = ring->get_seqno(ring, false);
+
list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
+ struct i915_hw_ppgtt *ppgtt =
+ container_of(vm, struct i915_hw_ppgtt, base);
+ if (!is_i915_ggtt(vm) && pp_db >> 10 != ppgtt->pd_offset)
+ continue;
+
list_for_each_entry(vma, &vm->active_list, mm_list) {
obj = vma->obj;
if (obj->ring != ring)
@@ -1749,7 +1763,7 @@ i915_error_first_batchbuffer(struct drm_i915_private *dev_priv,
* simplest method to avoid being overwritten by
* userspace.
*/
- return i915_error_object_create(dev_priv, obj);
+ return i915_error_object_create(dev_priv, obj, vm);
}
}
@@ -1806,6 +1820,7 @@ static void i915_gem_record_active_context(struct intel_ring_buffer *ring,
struct drm_i915_error_ring *ering)
{
struct drm_i915_private *dev_priv = ring->dev->dev_private;
+ struct i915_address_space *ggtt = &dev_priv->gtt.base;
struct drm_i915_gem_object *obj;
/* Currently render ring is the only HW context user */
@@ -1813,9 +1828,14 @@ static void i915_gem_record_active_context(struct intel_ring_buffer *ring,
return;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+ if (!i915_gem_obj_bound(obj, ggtt))
+ continue;
+
if ((error->ccid & PAGE_MASK) == i915_gem_ggtt_offset(obj)) {
ering->ctx = i915_error_object_create_sized(dev_priv,
- obj, 1);
+ obj,
+ ggtt,
+ 1);
}
}
}
@@ -1835,8 +1855,8 @@ static void i915_gem_record_rings(struct drm_device *dev,
i915_error_first_batchbuffer(dev_priv, ring);
error->ring[i].ringbuffer =
- i915_error_object_create(dev_priv, ring->obj);
-
+ i915_error_object_create(dev_priv, ring->obj,
+ &dev_priv->gtt.base);
i915_gem_record_active_context(ring, error, &error->ring[i]);
@@ -1912,7 +1932,7 @@ static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
struct drm_i915_error_state *error)
{
struct i915_address_space *vm;
- int cnt = 0;
+ int cnt = 0, i = 0;
list_for_each_entry(vm, &dev_priv->vm_list, global_link)
cnt++;
@@ -1929,7 +1949,8 @@ static void i915_gem_capture_buffers(struct drm_i915_private *dev_priv,
error->pinned_bo_count = kcalloc(cnt, sizeof(*error->pinned_bo_count),
GFP_ATOMIC);
- i915_gem_capture_vm(dev_priv, error, vm, 0);
+ list_for_each_entry(vm, &dev_priv->vm_list, global_link)
+ i915_gem_capture_vm(dev_priv, error, vm, i++);
}
/**
Signed-off-by: Ben Widawsky <ben@bwidawsk.net> --- drivers/gpu/drm/i915/i915_irq.c | 53 ++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 16 deletions(-)