drm/i915: Add PPGTT dumper
authorBen Widawsky <ben@bwidawsk.net>
Fri, 6 Dec 2013 22:11:29 +0000 (14:11 -0800)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 18 Dec 2013 15:26:16 +0000 (16:26 +0100)
Dump the aliasing PPGTT with it. The aliasing PPGTT should actually
always be empty.

TODO: Broadwell. Since we don't yet use full PPGTT on Broadwell, not
having the dumper is okay.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_gtt.c

index 4c610eeb54599dc2e8adad7ecbd1901425e8cf58..6a98b647e99ea117100e629f673b45843ba4632c 100644 (file)
@@ -1704,6 +1704,7 @@ static void gen6_ppgtt_info(struct seq_file *m, struct drm_device *dev)
 
                seq_puts(m, "aliasing PPGTT:\n");
                seq_printf(m, "pd gtt offset: 0x%08x\n", ppgtt->pd_offset);
+               ppgtt->debug_dump(ppgtt, m);
        }
        seq_printf(m, "ECOCHK: 0x%08x\n", I915_READ(GAM_ECOCHK));
 }
index 8fd99ac96940b8b177587521fe11da906ab61ee9..aab400c04be07176b0a2d5530c5e645b9bcc19b3 100644 (file)
@@ -678,6 +678,7 @@ struct i915_hw_ppgtt {
        int (*switch_mm)(struct i915_hw_ppgtt *ppgtt,
                         struct intel_ring_buffer *ring,
                         bool synchronous);
+       void (*debug_dump)(struct i915_hw_ppgtt *ppgtt, struct seq_file *m);
 };
 
 struct i915_ctx_hang_stats {
index ece9d8e7568b0e986c67117d8c4c86dfb10d608a..998f9a0b322a627591666addbe8db2242af75be8 100644 (file)
@@ -460,6 +460,62 @@ err_out:
        return ret;
 }
 
+static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
+{
+       struct drm_i915_private *dev_priv = ppgtt->base.dev->dev_private;
+       struct i915_address_space *vm = &ppgtt->base;
+       gen6_gtt_pte_t __iomem *pd_addr;
+       gen6_gtt_pte_t scratch_pte;
+       uint32_t pd_entry;
+       int pte, pde;
+
+       scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true);
+
+       pd_addr = (gen6_gtt_pte_t __iomem *)dev_priv->gtt.gsm +
+               ppgtt->pd_offset / sizeof(gen6_gtt_pte_t);
+
+       seq_printf(m, "  VM %p (pd_offset %x-%x):\n", vm,
+                  ppgtt->pd_offset, ppgtt->pd_offset + ppgtt->num_pd_entries);
+       for (pde = 0; pde < ppgtt->num_pd_entries; pde++) {
+               u32 expected;
+               gen6_gtt_pte_t *pt_vaddr;
+               dma_addr_t pt_addr = ppgtt->pt_dma_addr[pde];
+               pd_entry = readl(pd_addr + pde);
+               expected = (GEN6_PDE_ADDR_ENCODE(pt_addr) | GEN6_PDE_VALID);
+
+               if (pd_entry != expected)
+                       seq_printf(m, "\tPDE #%d mismatch: Actual PDE: %x Expected PDE: %x\n",
+                                  pde,
+                                  pd_entry,
+                                  expected);
+               seq_printf(m, "\tPDE: %x\n", pd_entry);
+
+               pt_vaddr = kmap_atomic(ppgtt->pt_pages[pde]);
+               for (pte = 0; pte < I915_PPGTT_PT_ENTRIES; pte+=4) {
+                       unsigned long va =
+                               (pde * PAGE_SIZE * I915_PPGTT_PT_ENTRIES) +
+                               (pte * PAGE_SIZE);
+                       int i;
+                       bool found = false;
+                       for (i = 0; i < 4; i++)
+                               if (pt_vaddr[pte + i] != scratch_pte)
+                                       found = true;
+                       if (!found)
+                               continue;
+
+                       seq_printf(m, "\t\t0x%lx [%03d,%04d]: =", va, pde, pte);
+                       for (i = 0; i < 4; i++) {
+                               if (pt_vaddr[pte + i] != scratch_pte)
+                                       seq_printf(m, " %08x", pt_vaddr[pte + i]);
+                               else
+                                       seq_puts(m, "  SCRATCH ");
+                       }
+                       seq_puts(m, "\n");
+               }
+               kunmap_atomic(pt_vaddr);
+       }
+}
+
 static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt)
 {
        struct drm_i915_private *dev_priv = ppgtt->base.dev->dev_private;
@@ -873,6 +929,7 @@ alloc:
 
        ppgtt->base.clear_range(&ppgtt->base, 0,
                                ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES, true);
+       ppgtt->debug_dump = gen6_dump_ppgtt;
 
        DRM_DEBUG_DRIVER("Allocated pde space (%ldM) at GTT entry: %lx\n",
                         ppgtt->node.size >> 20,