30,10 → 30,6 |
#include "i915_drv.h" |
|
#if 0 |
static const char *yesno(int v) |
{ |
return v ? "yes" : "no"; |
} |
|
static const char *ring_str(int ring) |
{ |
192,15 → 188,21 |
struct drm_i915_error_buffer *err, |
int count) |
{ |
int i; |
|
err_printf(m, " %s [%d]:\n", name, count); |
|
while (count--) { |
err_printf(m, " %08x %8u %02x %02x %x %x", |
err->gtt_offset, |
err_printf(m, " %08x_%08x %8u %02x %02x [ ", |
upper_32_bits(err->gtt_offset), |
lower_32_bits(err->gtt_offset), |
err->size, |
err->read_domains, |
err->write_domain, |
err->rseqno, err->wseqno); |
err->write_domain); |
for (i = 0; i < I915_NUM_RINGS; i++) |
err_printf(m, "%02x ", err->rseqno[i]); |
|
err_printf(m, "] %02x", err->wseqno); |
err_puts(m, pin_flag(err->pinned)); |
err_puts(m, tiling_flag(err->tiling)); |
err_puts(m, dirty_flag(err->dirty)); |
242,11 → 244,16 |
|
static void i915_ring_error_state(struct drm_i915_error_state_buf *m, |
struct drm_device *dev, |
struct drm_i915_error_ring *ring) |
struct drm_i915_error_state *error, |
int ring_idx) |
{ |
struct drm_i915_error_ring *ring = &error->ring[ring_idx]; |
|
if (!ring->valid) |
return; |
|
err_printf(m, "%s command stream:\n", ring_str(ring_idx)); |
err_printf(m, " START: 0x%08x\n", ring->start); |
err_printf(m, " HEAD: 0x%08x\n", ring->head); |
err_printf(m, " TAIL: 0x%08x\n", ring->tail); |
err_printf(m, " CTL: 0x%08x\n", ring->ctl); |
329,6 → 336,7 |
struct drm_device *dev = error_priv->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct drm_i915_error_state *error = error_priv->error; |
struct drm_i915_error_object *obj; |
int i, j, offset, elt; |
int max_hangcheck_score; |
|
358,8 → 366,15 |
err_printf(m, "Reset count: %u\n", error->reset_count); |
err_printf(m, "Suspend count: %u\n", error->suspend_count); |
err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device); |
err_printf(m, "IOMMU enabled?: %d\n", error->iommu); |
err_printf(m, "EIR: 0x%08x\n", error->eir); |
err_printf(m, "IER: 0x%08x\n", error->ier); |
if (INTEL_INFO(dev)->gen >= 8) { |
for (i = 0; i < 4; i++) |
err_printf(m, "GTIER gt %d: 0x%08x\n", i, |
error->gtier[i]); |
} else if (HAS_PCH_SPLIT(dev) || IS_VALLEYVIEW(dev)) |
err_printf(m, "GTIER: 0x%08x\n", error->gtier[0]); |
err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); |
err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); |
err_printf(m, "DERRMR: 0x%08x\n", error->derrmr); |
375,6 → 390,11 |
|
if (INTEL_INFO(dev)->gen >= 6) { |
err_printf(m, "ERROR: 0x%08x\n", error->error); |
|
if (INTEL_INFO(dev)->gen >= 8) |
err_printf(m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n", |
error->fault_data1, error->fault_data0); |
|
err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg); |
} |
|
381,24 → 401,22 |
if (INTEL_INFO(dev)->gen == 7) |
err_printf(m, "ERR_INT: 0x%08x\n", error->err_int); |
|
for (i = 0; i < ARRAY_SIZE(error->ring); i++) { |
err_printf(m, "%s command stream:\n", ring_str(i)); |
i915_ring_error_state(m, dev, &error->ring[i]); |
} |
for (i = 0; i < ARRAY_SIZE(error->ring); i++) |
i915_ring_error_state(m, dev, error, i); |
|
if (error->active_bo) |
for (i = 0; i < error->vm_count; i++) { |
err_printf(m, "vm[%d]\n", i); |
|
print_error_buffers(m, "Active", |
error->active_bo[0], |
error->active_bo_count[0]); |
error->active_bo[i], |
error->active_bo_count[i]); |
|
if (error->pinned_bo) |
print_error_buffers(m, "Pinned", |
error->pinned_bo[0], |
error->pinned_bo_count[0]); |
error->pinned_bo[i], |
error->pinned_bo_count[i]); |
} |
|
for (i = 0; i < ARRAY_SIZE(error->ring); i++) { |
struct drm_i915_error_object *obj; |
|
obj = error->ring[i].batchbuffer; |
if (obj) { |
err_puts(m, dev_priv->ring[i].name); |
406,8 → 424,9 |
err_printf(m, " (submitted by %s [%d])", |
error->ring[i].comm, |
error->ring[i].pid); |
err_printf(m, " --- gtt_offset = 0x%08x\n", |
obj->gtt_offset); |
err_printf(m, " --- gtt_offset = 0x%08x %08x\n", |
upper_32_bits(obj->gtt_offset), |
lower_32_bits(obj->gtt_offset)); |
print_error_obj(m, obj); |
} |
|
414,7 → 433,8 |
obj = error->ring[i].wa_batchbuffer; |
if (obj) { |
err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n", |
dev_priv->ring[i].name, obj->gtt_offset); |
dev_priv->ring[i].name, |
lower_32_bits(obj->gtt_offset)); |
print_error_obj(m, obj); |
} |
|
433,22 → 453,28 |
if ((obj = error->ring[i].ringbuffer)) { |
err_printf(m, "%s --- ringbuffer = 0x%08x\n", |
dev_priv->ring[i].name, |
obj->gtt_offset); |
lower_32_bits(obj->gtt_offset)); |
print_error_obj(m, obj); |
} |
|
if ((obj = error->ring[i].hws_page)) { |
err_printf(m, "%s --- HW Status = 0x%08x\n", |
dev_priv->ring[i].name, |
obj->gtt_offset); |
u64 hws_offset = obj->gtt_offset; |
u32 *hws_page = &obj->pages[0][0]; |
|
if (i915.enable_execlists) { |
hws_offset += LRC_PPHWSP_PN * PAGE_SIZE; |
hws_page = &obj->pages[LRC_PPHWSP_PN][0]; |
} |
err_printf(m, "%s --- HW Status = 0x%08llx\n", |
dev_priv->ring[i].name, hws_offset); |
offset = 0; |
for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { |
err_printf(m, "[%04x] %08x %08x %08x %08x\n", |
offset, |
obj->pages[0][elt], |
obj->pages[0][elt+1], |
obj->pages[0][elt+2], |
obj->pages[0][elt+3]); |
hws_page[elt], |
hws_page[elt+1], |
hws_page[elt+2], |
hws_page[elt+3]); |
offset += 16; |
} |
} |
456,11 → 482,24 |
if ((obj = error->ring[i].ctx)) { |
err_printf(m, "%s --- HW Context = 0x%08x\n", |
dev_priv->ring[i].name, |
obj->gtt_offset); |
lower_32_bits(obj->gtt_offset)); |
print_error_obj(m, obj); |
} |
} |
|
if ((obj = error->semaphore_obj)) { |
err_printf(m, "Semaphore page = 0x%08x\n", |
lower_32_bits(obj->gtt_offset)); |
for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { |
err_printf(m, "[%04x] %08x %08x %08x %08x\n", |
elt * 4, |
obj->pages[0][elt], |
obj->pages[0][elt+1], |
obj->pages[0][elt+2], |
obj->pages[0][elt+3]); |
} |
} |
|
if (error->overlay) |
intel_overlay_print_error_state(m, error->overlay); |
|
475,9 → 514,11 |
} |
|
int i915_error_state_buf_init(struct drm_i915_error_state_buf *ebuf, |
struct drm_i915_private *i915, |
size_t count, loff_t pos) |
{ |
memset(ebuf, 0, sizeof(*ebuf)); |
ebuf->i915 = i915; |
|
/* We need to have enough room to store any i915_error_state printf |
* so that we can move it to start position. |
525,6 → 566,7 |
|
for (i = 0; i < ARRAY_SIZE(error->ring); i++) { |
i915_error_object_free(error->ring[i].batchbuffer); |
i915_error_object_free(error->ring[i].wa_batchbuffer); |
i915_error_object_free(error->ring[i].ringbuffer); |
i915_error_object_free(error->ring[i].hws_page); |
i915_error_object_free(error->ring[i].ctx); |
531,7 → 573,15 |
kfree(error->ring[i].requests); |
} |
|
i915_error_object_free(error->semaphore_obj); |
|
for (i = 0; i < error->vm_count; i++) |
kfree(error->active_bo[i]); |
|
kfree(error->active_bo); |
kfree(error->active_bo_count); |
kfree(error->pinned_bo); |
kfree(error->pinned_bo_count); |
kfree(error->overlay); |
kfree(error->display); |
kfree(error); |
538,24 → 588,56 |
} |
|
static struct drm_i915_error_object * |
i915_error_object_create_sized(struct drm_i915_private *dev_priv, |
i915_error_object_create(struct drm_i915_private *dev_priv, |
struct drm_i915_gem_object *src, |
struct i915_address_space *vm, |
const int num_pages) |
struct i915_address_space *vm) |
{ |
struct drm_i915_error_object *dst; |
int i; |
u32 reloc_offset; |
struct i915_vma *vma = NULL; |
int num_pages; |
bool use_ggtt; |
int i = 0; |
u64 reloc_offset; |
|
if (src == NULL || src->pages == NULL) |
return NULL; |
|
num_pages = src->base.size >> PAGE_SHIFT; |
|
dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC); |
if (dst == NULL) |
return NULL; |
|
reloc_offset = dst->gtt_offset = i915_gem_obj_offset(src, vm); |
for (i = 0; i < num_pages; i++) { |
if (i915_gem_obj_bound(src, vm)) |
dst->gtt_offset = i915_gem_obj_offset(src, vm); |
else |
dst->gtt_offset = -1; |
|
reloc_offset = dst->gtt_offset; |
if (i915_is_ggtt(vm)) |
vma = i915_gem_obj_to_ggtt(src); |
use_ggtt = (src->cache_level == I915_CACHE_NONE && |
vma && (vma->bound & GLOBAL_BIND) && |
reloc_offset + num_pages * PAGE_SIZE <= dev_priv->gtt.mappable_end); |
|
/* Cannot access stolen address directly, try to use the aperture */ |
if (src->stolen) { |
use_ggtt = true; |
|
if (!(vma && vma->bound & GLOBAL_BIND)) |
goto unwind; |
|
reloc_offset = i915_gem_obj_ggtt_offset(src); |
if (reloc_offset + num_pages * PAGE_SIZE > dev_priv->gtt.mappable_end) |
goto unwind; |
} |
|
/* Cannot access snooped pages through the aperture */ |
if (use_ggtt && src->cache_level != I915_CACHE_NONE && !HAS_LLC(dev_priv->dev)) |
goto unwind; |
|
dst->page_count = num_pages; |
while (num_pages--) { |
unsigned long flags; |
void *d; |
|
564,10 → 646,7 |
goto unwind; |
|
local_irq_save(flags); |
if (src->cache_level == I915_CACHE_NONE && |
reloc_offset < dev_priv->gtt.mappable_end && |
src->has_global_gtt_mapping && |
i915_is_ggtt(vm)) { |
if (use_ggtt) { |
void __iomem *s; |
|
/* Simply ignore tiling or any overlapping fence. |
579,14 → 658,6 |
reloc_offset); |
memcpy_fromio(d, s, PAGE_SIZE); |
io_mapping_unmap_atomic(s); |
} else if (src->stolen) { |
unsigned long offset; |
|
offset = dev_priv->mm.stolen_base; |
offset += src->stolen->start; |
offset += i << PAGE_SHIFT; |
|
memcpy_fromio(d, (void __iomem *) offset, PAGE_SIZE); |
} else { |
struct page *page; |
void *s; |
603,11 → 674,9 |
} |
local_irq_restore(flags); |
|
dst->pages[i] = d; |
|
dst->pages[i++] = d; |
reloc_offset += PAGE_SIZE; |
} |
dst->page_count = num_pages; |
|
return dst; |
|
617,22 → 686,21 |
kfree(dst); |
return NULL; |
} |
#define i915_error_object_create(dev_priv, src, vm) \ |
i915_error_object_create_sized((dev_priv), (src), (vm), \ |
(src)->base.size>>PAGE_SHIFT) |
|
#define i915_error_ggtt_object_create(dev_priv, src) \ |
i915_error_object_create_sized((dev_priv), (src), &(dev_priv)->gtt.base, \ |
(src)->base.size>>PAGE_SHIFT) |
i915_error_object_create((dev_priv), (src), &(dev_priv)->gtt.base) |
|
static void capture_bo(struct drm_i915_error_buffer *err, |
struct drm_i915_gem_object *obj) |
struct i915_vma *vma) |
{ |
struct drm_i915_gem_object *obj = vma->obj; |
int i; |
|
err->size = obj->base.size; |
err->name = obj->base.name; |
err->rseqno = obj->last_read_seqno; |
err->wseqno = obj->last_write_seqno; |
err->gtt_offset = i915_gem_obj_ggtt_offset(obj); |
for (i = 0; i < I915_NUM_RINGS; i++) |
err->rseqno[i] = i915_gem_request_get_seqno(obj->last_read_req[i]); |
err->wseqno = i915_gem_request_get_seqno(obj->last_write_req); |
err->gtt_offset = vma->node.start; |
err->read_domains = obj->base.read_domains; |
err->write_domain = obj->base.write_domain; |
err->fence_reg = obj->fence_reg; |
639,13 → 707,12 |
err->pinned = 0; |
if (i915_gem_obj_is_pinned(obj)) |
err->pinned = 1; |
if (obj->user_pin_count > 0) |
err->pinned = -1; |
err->tiling = obj->tiling_mode; |
err->dirty = obj->dirty; |
err->purgeable = obj->madv != I915_MADV_WILLNEED; |
err->userptr = obj->userptr.mm != NULL; |
err->ring = obj->ring ? obj->ring->id : -1; |
err->ring = obj->last_write_req ? |
i915_gem_request_get_ring(obj->last_write_req)->id : -1; |
err->cache_level = obj->cache_level; |
} |
|
656,7 → 723,7 |
int i = 0; |
|
list_for_each_entry(vma, head, mm_list) { |
capture_bo(err++, vma->obj); |
capture_bo(err++, vma); |
if (++i == count) |
break; |
} |
665,21 → 732,25 |
} |
|
static u32 capture_pinned_bo(struct drm_i915_error_buffer *err, |
int count, struct list_head *head) |
int count, struct list_head *head, |
struct i915_address_space *vm) |
{ |
struct drm_i915_gem_object *obj; |
int i = 0; |
struct drm_i915_error_buffer * const first = err; |
struct drm_i915_error_buffer * const last = err + count; |
|
list_for_each_entry(obj, head, global_list) { |
if (!i915_gem_obj_is_pinned(obj)) |
continue; |
struct i915_vma *vma; |
|
capture_bo(err++, obj); |
if (++i == count) |
if (err == last) |
break; |
|
list_for_each_entry(vma, &obj->vma_list, vma_link) |
if (vma->vm == vm && vma->pin_count > 0) |
capture_bo(err++, vma); |
} |
|
return i; |
return err - first; |
} |
|
/* Generate a semi-unique error code. The code is not meant to have meaning, The |
721,34 → 792,71 |
struct drm_i915_private *dev_priv = dev->dev_private; |
int i; |
|
/* Fences */ |
switch (INTEL_INFO(dev)->gen) { |
case 8: |
case 7: |
case 6: |
if (IS_GEN3(dev) || IS_GEN2(dev)) { |
for (i = 0; i < dev_priv->num_fence_regs; i++) |
error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); |
break; |
case 5: |
case 4: |
for (i = 0; i < 16; i++) |
error->fence[i] = I915_READ64(FENCE_REG_965_0 + (i * 8)); |
break; |
case 3: |
if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) |
for (i = 0; i < 8; i++) |
error->fence[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4)); |
case 2: |
for (i = 0; i < 8; i++) |
error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4)); |
break; |
error->fence[i] = I915_READ(FENCE_REG(i)); |
} else if (IS_GEN5(dev) || IS_GEN4(dev)) { |
for (i = 0; i < dev_priv->num_fence_regs; i++) |
error->fence[i] = I915_READ64(FENCE_REG_965_LO(i)); |
} else if (INTEL_INFO(dev)->gen >= 6) { |
for (i = 0; i < dev_priv->num_fence_regs; i++) |
error->fence[i] = I915_READ64(FENCE_REG_GEN6_LO(i)); |
} |
} |
|
default: |
BUG(); |
|
static void gen8_record_semaphore_state(struct drm_i915_private *dev_priv, |
struct drm_i915_error_state *error, |
struct intel_engine_cs *ring, |
struct drm_i915_error_ring *ering) |
{ |
struct intel_engine_cs *to; |
int i; |
|
if (!i915_semaphore_is_enabled(dev_priv->dev)) |
return; |
|
if (!error->semaphore_obj) |
error->semaphore_obj = |
i915_error_ggtt_object_create(dev_priv, |
dev_priv->semaphore_obj); |
|
for_each_ring(to, dev_priv, i) { |
int idx; |
u16 signal_offset; |
u32 *tmp; |
|
if (ring == to) |
continue; |
|
signal_offset = (GEN8_SIGNAL_OFFSET(ring, i) & (PAGE_SIZE - 1)) |
/ 4; |
tmp = error->semaphore_obj->pages[0]; |
idx = intel_ring_sync_index(ring, to); |
|
ering->semaphore_mboxes[idx] = tmp[signal_offset]; |
ering->semaphore_seqno[idx] = ring->semaphore.sync_seqno[idx]; |
} |
} |
|
static void gen6_record_semaphore_state(struct drm_i915_private *dev_priv, |
struct intel_engine_cs *ring, |
struct drm_i915_error_ring *ering) |
{ |
ering->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(ring->mmio_base)); |
ering->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(ring->mmio_base)); |
ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0]; |
ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1]; |
|
if (HAS_VEBOX(dev_priv->dev)) { |
ering->semaphore_mboxes[2] = |
I915_READ(RING_SYNC_2(ring->mmio_base)); |
ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2]; |
} |
} |
|
static void i915_record_ring_state(struct drm_device *dev, |
struct drm_i915_error_state *error, |
struct intel_engine_cs *ring, |
struct drm_i915_error_ring *ering) |
{ |
757,20 → 865,12 |
if (INTEL_INFO(dev)->gen >= 6) { |
ering->rc_psmi = I915_READ(ring->mmio_base + 0x50); |
ering->fault_reg = I915_READ(RING_FAULT_REG(ring)); |
ering->semaphore_mboxes[0] |
= I915_READ(RING_SYNC_0(ring->mmio_base)); |
ering->semaphore_mboxes[1] |
= I915_READ(RING_SYNC_1(ring->mmio_base)); |
ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0]; |
ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1]; |
if (INTEL_INFO(dev)->gen >= 8) |
gen8_record_semaphore_state(dev_priv, error, ring, ering); |
else |
gen6_record_semaphore_state(dev_priv, ring, ering); |
} |
|
if (HAS_VEBOX(dev)) { |
ering->semaphore_mboxes[2] = |
I915_READ(RING_SYNC_2(ring->mmio_base)); |
ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2]; |
} |
|
if (INTEL_INFO(dev)->gen >= 4) { |
ering->faddr = I915_READ(RING_DMA_FADD(ring->mmio_base)); |
ering->ipeir = I915_READ(RING_IPEIR(ring->mmio_base)); |
787,7 → 887,7 |
ering->faddr = I915_READ(DMA_FADD_I8XX); |
ering->ipeir = I915_READ(IPEIR); |
ering->ipehr = I915_READ(IPEHR); |
ering->instdone = I915_READ(INSTDONE); |
ering->instdone = I915_READ(GEN2_INSTDONE); |
} |
|
ering->waiting = waitqueue_active(&ring->irq_queue); |
794,6 → 894,7 |
ering->instpm = I915_READ(RING_INSTPM(ring->mmio_base)); |
ering->seqno = ring->get_seqno(ring, false); |
ering->acthd = intel_ring_get_active_head(ring); |
ering->start = I915_READ_START(ring); |
ering->head = I915_READ_HEAD(ring); |
ering->tail = I915_READ_TAIL(ring); |
ering->ctl = I915_READ_CTL(ring); |
827,9 → 928,6 |
ering->hws = I915_READ(mmio); |
} |
|
ering->cpu_ring_head = ring->buffer->head; |
ering->cpu_ring_tail = ring->buffer->tail; |
|
ering->hangcheck_score = ring->hangcheck.score; |
ering->hangcheck_action = ring->hangcheck.action; |
|
838,8 → 936,13 |
|
ering->vm_info.gfx_mode = I915_READ(RING_MODE_GEN7(ring)); |
|
switch (INTEL_INFO(dev)->gen) { |
case 8: |
if (IS_GEN6(dev)) |
ering->vm_info.pp_dir_base = |
I915_READ(RING_PP_DIR_BASE_READ(ring)); |
else if (IS_GEN7(dev)) |
ering->vm_info.pp_dir_base = |
I915_READ(RING_PP_DIR_BASE(ring)); |
else if (INTEL_INFO(dev)->gen >= 8) |
for (i = 0; i < 4; i++) { |
ering->vm_info.pdp[i] = |
I915_READ(GEN8_RING_PDP_UDW(ring, i)); |
847,18 → 950,8 |
ering->vm_info.pdp[i] |= |
I915_READ(GEN8_RING_PDP_LDW(ring, i)); |
} |
break; |
case 7: |
ering->vm_info.pp_dir_base = |
I915_READ(RING_PP_DIR_BASE(ring)); |
break; |
case 6: |
ering->vm_info.pp_dir_base = |
I915_READ(RING_PP_DIR_BASE_READ(ring)); |
break; |
} |
} |
} |
|
|
static void i915_gem_record_active_context(struct intel_engine_cs *ring, |
873,6 → 966,9 |
return; |
|
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { |
if (!i915_gem_obj_ggtt_bound(obj)) |
continue; |
|
if ((error->ccid & PAGE_MASK) == i915_gem_obj_ggtt_offset(obj)) { |
ering->ctx = i915_error_ggtt_object_create(dev_priv, obj); |
break; |
889,6 → 985,7 |
|
for (i = 0; i < I915_NUM_RINGS; i++) { |
struct intel_engine_cs *ring = &dev_priv->ring[i]; |
struct intel_ringbuffer *rbuf; |
|
error->ring[i].pid = -1; |
|
897,10 → 994,16 |
|
error->ring[i].valid = true; |
|
i915_record_ring_state(dev, ring, &error->ring[i]); |
i915_record_ring_state(dev, error, ring, &error->ring[i]); |
|
request = i915_gem_find_active_request(ring); |
if (request) { |
struct i915_address_space *vm; |
|
vm = request->ctx && request->ctx->ppgtt ? |
&request->ctx->ppgtt->base : |
&dev_priv->gtt.base; |
|
/* We need to copy these to an anonymous buffer |
* as the simplest method to avoid being overwritten |
* by userspace. |
908,22 → 1011,18 |
error->ring[i].batchbuffer = |
i915_error_object_create(dev_priv, |
request->batch_obj, |
request->ctx ? |
request->ctx->vm : |
&dev_priv->gtt.base); |
vm); |
|
if (HAS_BROKEN_CS_TLB(dev_priv->dev) && |
ring->scratch.obj) |
if (HAS_BROKEN_CS_TLB(dev_priv->dev)) |
error->ring[i].wa_batchbuffer = |
i915_error_ggtt_object_create(dev_priv, |
ring->scratch.obj); |
|
if (request->file_priv) { |
if (request->pid) { |
struct task_struct *task; |
|
rcu_read_lock(); |
task = pid_task(request->file_priv->file->pid, |
PIDTYPE_PID); |
task = pid_task(request->pid, PIDTYPE_PID); |
if (task) { |
strcpy(error->ring[i].comm, task->comm); |
error->ring[i].pid = task->pid; |
932,10 → 1031,25 |
} |
} |
|
if (i915.enable_execlists) { |
/* TODO: This is only a small fix to keep basic error |
* capture working, but we need to add more information |
* for it to be useful (e.g. dump the context being |
* executed). |
*/ |
if (request) |
rbuf = request->ctx->engine[ring->id].ringbuf; |
else |
rbuf = ring->default_context->engine[ring->id].ringbuf; |
} else |
rbuf = ring->buffer; |
|
error->ring[i].cpu_ring_head = rbuf->head; |
error->ring[i].cpu_ring_tail = rbuf->tail; |
|
error->ring[i].ringbuffer = |
i915_error_ggtt_object_create(dev_priv, ring->buffer->obj); |
i915_error_ggtt_object_create(dev_priv, rbuf->obj); |
|
if (ring->status_page.obj) |
error->ring[i].hws_page = |
i915_error_ggtt_object_create(dev_priv, ring->status_page.obj); |
|
961,7 → 1075,7 |
erq = &error->ring[i].requests[count++]; |
erq->seqno = request->seqno; |
erq->jiffies = request->emitted_jiffies; |
erq->tail = request->tail; |
erq->tail = request->postfix; |
} |
} |
} |
983,9 → 1097,12 |
list_for_each_entry(vma, &vm->active_list, mm_list) |
i++; |
error->active_bo_count[ndx] = i; |
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) |
if (i915_gem_obj_is_pinned(obj)) |
|
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { |
list_for_each_entry(vma, &obj->vma_list, vma_link) |
if (vma->vm == vm && vma->pin_count > 0) |
i++; |
} |
error->pinned_bo_count[ndx] = i - error->active_bo_count[ndx]; |
|
if (i) { |
1004,7 → 1121,7 |
error->pinned_bo_count[ndx] = |
capture_pinned_bo(pinned_bo, |
error->pinned_bo_count[ndx], |
&dev_priv->mm.bound_list); |
&dev_priv->mm.bound_list, vm); |
error->active_bo[ndx] = active_bo; |
error->pinned_bo[ndx] = pinned_bo; |
} |
1025,9 → 1142,26 |
error->pinned_bo_count = kcalloc(cnt, sizeof(*error->pinned_bo_count), |
GFP_ATOMIC); |
|
if (error->active_bo == NULL || |
error->pinned_bo == NULL || |
error->active_bo_count == NULL || |
error->pinned_bo_count == NULL) { |
kfree(error->active_bo); |
kfree(error->active_bo_count); |
kfree(error->pinned_bo); |
kfree(error->pinned_bo_count); |
|
error->active_bo = NULL; |
error->active_bo_count = NULL; |
error->pinned_bo = NULL; |
error->pinned_bo_count = NULL; |
} else { |
list_for_each_entry(vm, &dev_priv->vm_list, global_link) |
i915_gem_capture_vm(dev_priv, error, vm, i++); |
|
error->vm_count = cnt; |
} |
} |
|
/* Capture all registers which don't fit into another category. */ |
static void i915_capture_reg_state(struct drm_i915_private *dev_priv, |
1034,6 → 1168,7 |
struct drm_i915_error_state *error) |
{ |
struct drm_device *dev = dev_priv->dev; |
int i; |
|
/* General organization |
* 1. Registers specific to a single generation |
1045,7 → 1180,8 |
|
/* 1: Registers specific to a single generation */ |
if (IS_VALLEYVIEW(dev)) { |
error->ier = I915_READ(GTIER) | I915_READ(VLV_IER); |
error->gtier[0] = I915_READ(GTIER); |
error->ier = I915_READ(VLV_IER); |
error->forcewake = I915_READ(FORCEWAKE_VLV); |
} |
|
1052,6 → 1188,11 |
if (IS_GEN7(dev)) |
error->err_int = I915_READ(GEN7_ERR_INT); |
|
if (INTEL_INFO(dev)->gen >= 8) { |
error->fault_data0 = I915_READ(GEN8_FAULT_TLB_DATA0); |
error->fault_data1 = I915_READ(GEN8_FAULT_TLB_DATA1); |
} |
|
if (IS_GEN6(dev)) { |
error->forcewake = I915_READ(FORCEWAKE); |
error->gab_ctl = I915_READ(GAB_CTL); |
1078,16 → 1219,18 |
if (HAS_HW_CONTEXTS(dev)) |
error->ccid = I915_READ(CCID); |
|
if (HAS_PCH_SPLIT(dev)) |
error->ier = I915_READ(DEIER) | I915_READ(GTIER); |
else { |
if (IS_GEN2(dev)) |
if (INTEL_INFO(dev)->gen >= 8) { |
error->ier = I915_READ(GEN8_DE_MISC_IER); |
for (i = 0; i < 4; i++) |
error->gtier[i] = I915_READ(GEN8_GT_IER(i)); |
} else if (HAS_PCH_SPLIT(dev)) { |
error->ier = I915_READ(DEIER); |
error->gtier[0] = I915_READ(GTIER); |
} else if (IS_GEN2(dev)) { |
error->ier = I915_READ16(IER); |
else |
} else if (!IS_VALLEYVIEW(dev)) { |
error->ier = I915_READ(IER); |
} |
|
/* 4: Everything else */ |
error->eir = I915_READ(EIR); |
error->pgtbl_er = I915_READ(PGTBL_ER); |
|
1106,7 → 1249,8 |
ecode = i915_error_generate_code(dev_priv, error, &ring_id); |
|
len = scnprintf(error->error_msg, sizeof(error->error_msg), |
"GPU HANG: ecode %d:0x%08x", ring_id, ecode); |
"GPU HANG: ecode %d:%d:0x%08x", |
INTEL_INFO(dev)->gen, ring_id, ecode); |
|
if (ring_id != -1 && error->ring[ring_id].pid != -1) |
len += scnprintf(error->error_msg + len, |
1124,6 → 1268,10 |
static void i915_capture_gen_state(struct drm_i915_private *dev_priv, |
struct drm_i915_error_state *error) |
{ |
error->iommu = -1; |
#ifdef CONFIG_INTEL_IOMMU |
error->iommu = intel_iommu_gfx_mapped; |
#endif |
error->reset_count = i915_reset_count(&dev_priv->gpu_error); |
error->suspend_count = dev_priv->suspend_count; |
} |
1194,13 → 1342,12 |
struct i915_error_state_file_priv *error_priv) |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
unsigned long flags; |
|
spin_lock_irqsave(&dev_priv->gpu_error.lock, flags); |
spin_lock_irq(&dev_priv->gpu_error.lock); |
error_priv->error = dev_priv->gpu_error.first_error; |
if (error_priv->error) |
kref_get(&error_priv->error->ref); |
spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags); |
spin_unlock_irq(&dev_priv->gpu_error.lock); |
|
} |
|
1214,28 → 1361,27 |
{ |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct drm_i915_error_state *error; |
unsigned long flags; |
|
spin_lock_irqsave(&dev_priv->gpu_error.lock, flags); |
spin_lock_irq(&dev_priv->gpu_error.lock); |
error = dev_priv->gpu_error.first_error; |
dev_priv->gpu_error.first_error = NULL; |
spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags); |
spin_unlock_irq(&dev_priv->gpu_error.lock); |
|
if (error) |
kref_put(&error->ref, i915_error_state_free); |
} |
#endif |
|
const char *i915_cache_level_str(int type) |
const char *i915_cache_level_str(struct drm_i915_private *i915, int type) |
{ |
switch (type) { |
case I915_CACHE_NONE: return " uncached"; |
case I915_CACHE_LLC: return " snooped or LLC"; |
case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped"; |
case I915_CACHE_L3_LLC: return " L3+LLC"; |
case I915_CACHE_WT: return " WT"; |
default: return ""; |
} |
} |
#endif |
|
/* NB: please notice the memset */ |
void i915_get_extra_instdone(struct drm_device *dev, uint32_t *instdone) |
1243,26 → 1389,15 |
struct drm_i915_private *dev_priv = dev->dev_private; |
memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG); |
|
switch (INTEL_INFO(dev)->gen) { |
case 2: |
case 3: |
instdone[0] = I915_READ(INSTDONE); |
break; |
case 4: |
case 5: |
case 6: |
instdone[0] = I915_READ(INSTDONE_I965); |
instdone[1] = I915_READ(INSTDONE1); |
break; |
default: |
WARN_ONCE(1, "Unsupported platform\n"); |
case 7: |
case 8: |
case 9: |
instdone[0] = I915_READ(GEN7_INSTDONE_1); |
if (IS_GEN2(dev) || IS_GEN3(dev)) |
instdone[0] = I915_READ(GEN2_INSTDONE); |
else if (IS_GEN4(dev) || IS_GEN5(dev) || IS_GEN6(dev)) { |
instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE)); |
instdone[1] = I915_READ(GEN4_INSTDONE1); |
} else if (INTEL_INFO(dev)->gen >= 7) { |
instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE)); |
instdone[1] = I915_READ(GEN7_SC_INSTDONE); |
instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE); |
instdone[3] = I915_READ(GEN7_ROW_INSTDONE); |
break; |
} |
} |