diff options
author | Sushmita Susheelendra <ssusheel@codeaurora.org> | 2016-02-29 15:47:32 -0700 |
---|---|---|
committer | Sushmita Susheelendra <ssusheel@codeaurora.org> | 2016-08-25 15:35:22 -0600 |
commit | 25737e561a7b4fe8ce1770edc6ef4584dbb641c6 (patch) | |
tree | 67641f2032037d62cc034280734855cadd9385a9 /drivers/gpu/msm/kgsl_iommu.c | |
parent | e97b6a0e0217f7c072fdad6c50673cd7a64348e1 (diff) |
msm: kgsl: Improve logs for pagefaults on global buffers
Log the nearby allocations for pagefaults on global buffers.
Print the names of the allocations that fall around the
faulting address on a global buffer. Also add a new debugfs
file to list all the global pagetable entries. Useful for
debugging pagefaults and other issues with "global" objects.
CRs-Fixed: 985631
Change-Id: Ifbbdc69044fc64d7ea02509bf8113ed94eeece1e
Signed-off-by: Sushmita Susheelendra <ssusheel@codeaurora.org>
Diffstat (limited to 'drivers/gpu/msm/kgsl_iommu.c')
-rw-r--r-- | drivers/gpu/msm/kgsl_iommu.c | 123 |
1 files changed, 101 insertions, 22 deletions
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 166bb68e64a1..71b6086423d6 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -38,6 +38,10 @@ #define _IOMMU_PRIV(_mmu) (&((_mmu)->priv.iommu)) +#define ADDR_IN_GLOBAL(_a) \ + (((_a) >= KGSL_IOMMU_GLOBAL_MEM_BASE) && \ + ((_a) < (KGSL_IOMMU_GLOBAL_MEM_BASE + KGSL_IOMMU_GLOBAL_MEM_SIZE))) + static struct kgsl_mmu_pt_ops iommu_pt_ops; static bool need_iommu_sync; @@ -92,19 +96,41 @@ static struct kmem_cache *addr_entry_cache; #define GLOBAL_PT_ENTRIES 32 -static struct kgsl_memdesc *global_pt_entries[GLOBAL_PT_ENTRIES]; +struct global_pt_entry { + struct kgsl_memdesc *memdesc; + char name[32]; +}; + +static struct global_pt_entry global_pt_entries[GLOBAL_PT_ENTRIES]; static struct kgsl_memdesc *kgsl_global_secure_pt_entry; static int global_pt_count; uint64_t global_pt_alloc; static struct kgsl_memdesc gpu_qdss_desc; +void kgsl_print_global_pt_entries(struct seq_file *s) +{ + int i; + + for (i = 0; i < global_pt_count; i++) { + struct kgsl_memdesc *memdesc = global_pt_entries[i].memdesc; + + if (memdesc == NULL) + continue; + + seq_printf(s, "0x%16.16llX-0x%16.16llX %16llu %s\n", + memdesc->gpuaddr, memdesc->gpuaddr + memdesc->size - 1, + memdesc->size, global_pt_entries[i].name); + } +} + static void kgsl_iommu_unmap_globals(struct kgsl_pagetable *pagetable) { unsigned int i; for (i = 0; i < global_pt_count; i++) { - if (global_pt_entries[i] != NULL) - kgsl_mmu_unmap(pagetable, global_pt_entries[i]); + if (global_pt_entries[i].memdesc != NULL) + kgsl_mmu_unmap(pagetable, + global_pt_entries[i].memdesc); } } @@ -113,8 +139,9 @@ static void kgsl_iommu_map_globals(struct kgsl_pagetable *pagetable) unsigned int i; for (i = 0; i < global_pt_count; i++) { - if (global_pt_entries[i] != NULL) { - int ret = kgsl_mmu_map(pagetable, global_pt_entries[i]); + if (global_pt_entries[i].memdesc != NULL) { + int ret = kgsl_mmu_map(pagetable, + global_pt_entries[i].memdesc); BUG_ON(ret); } @@ -152,17 +179,17 @@ static void kgsl_iommu_remove_global(struct kgsl_mmu *mmu, return; for (i = 0; i < global_pt_count; i++) { - if (global_pt_entries[i] == memdesc) { + if (global_pt_entries[i].memdesc == memdesc) { memdesc->gpuaddr = 0; memdesc->priv &= ~KGSL_MEMDESC_GLOBAL; - global_pt_entries[i] = NULL; + global_pt_entries[i].memdesc = NULL; return; } } } static void kgsl_iommu_add_global(struct kgsl_mmu *mmu, - struct kgsl_memdesc *memdesc) + struct kgsl_memdesc *memdesc, const char *name) { if (memdesc->gpuaddr != 0) return; @@ -174,7 +201,10 @@ static void kgsl_iommu_add_global(struct kgsl_mmu *mmu, memdesc->priv |= KGSL_MEMDESC_GLOBAL; global_pt_alloc += memdesc->size; - global_pt_entries[global_pt_count++] = memdesc; + global_pt_entries[global_pt_count].memdesc = memdesc; + strlcpy(global_pt_entries[global_pt_count].name, name, + sizeof(global_pt_entries[global_pt_count].name)); + global_pt_count++; } void kgsl_add_global_secure_entry(struct kgsl_device *device, @@ -220,7 +250,7 @@ static void kgsl_setup_qdss_desc(struct kgsl_device *device) return; } - kgsl_mmu_add_global(device, &gpu_qdss_desc); + kgsl_mmu_add_global(device, &gpu_qdss_desc, "gpu-qdss"); } static inline void kgsl_cleanup_qdss_desc(struct kgsl_mmu *mmu) @@ -493,8 +523,62 @@ struct _mem_entry { unsigned int priv; int pending_free; pid_t pid; + char name[32]; }; +static void _get_global_entries(uint64_t faultaddr, + struct _mem_entry *prev, + struct _mem_entry *next) +{ + int i; + uint64_t prevaddr = 0; + struct global_pt_entry *p = NULL; + + uint64_t nextaddr = (uint64_t) -1; + struct global_pt_entry *n = NULL; + + for (i = 0; i < global_pt_count; i++) { + uint64_t addr; + + if (global_pt_entries[i].memdesc == NULL) + continue; + + addr = global_pt_entries[i].memdesc->gpuaddr; + if ((addr < faultaddr) && (addr > prevaddr)) { + prevaddr = addr; + p = &global_pt_entries[i]; + } + + if ((addr > faultaddr) && (addr < nextaddr)) { + nextaddr = addr; + n = &global_pt_entries[i]; + } + } + + if (p != NULL) { + prev->gpuaddr = p->memdesc->gpuaddr; + prev->size = p->memdesc->size; + prev->flags = p->memdesc->flags; + prev->priv = p->memdesc->priv; + prev->pid = 0; + strlcpy(prev->name, p->name, sizeof(prev->name)); + } + + if (n != NULL) { + next->gpuaddr = n->memdesc->gpuaddr; + next->size = n->memdesc->size; + next->flags = n->memdesc->flags; + next->priv = n->memdesc->priv; + next->pid = 0; + strlcpy(next->name, n->name, sizeof(next->name)); + } +} + +void __kgsl_get_memory_usage(struct _mem_entry *entry) +{ + kgsl_get_memory_usage(entry->name, sizeof(entry->name), entry->flags); +} + static void _get_entries(struct kgsl_process_private *private, uint64_t faultaddr, struct _mem_entry *prev, struct _mem_entry *next) @@ -529,6 +613,7 @@ static void _get_entries(struct kgsl_process_private *private, prev->priv = p->memdesc.priv; prev->pending_free = p->pending_free; prev->pid = private->pid; + __kgsl_get_memory_usage(prev); } if (n != NULL) { @@ -538,6 +623,7 @@ static void _get_entries(struct kgsl_process_private *private, next->priv = n->memdesc.priv; next->pending_free = n->pending_free; next->pid = private->pid; + __kgsl_get_memory_usage(next); } } @@ -553,7 +639,9 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr, /* Set the maximum possible size as an initial value */ nextentry->gpuaddr = (uint64_t) -1; - if (context) { + if (ADDR_IN_GLOBAL(faultaddr)) { + _get_global_entries(faultaddr, preventry, nextentry); + } else if (context) { private = context->proc_priv; spin_lock(&private->mem_lock); _get_entries(private, faultaddr, preventry, nextentry); @@ -563,18 +651,13 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr, static void _print_entry(struct kgsl_device *device, struct _mem_entry *entry) { - char name[32]; - memset(name, 0, sizeof(name)); - - kgsl_get_memory_usage(name, sizeof(name) - 1, entry->flags); - KGSL_LOG_DUMP(device, "[%016llX - %016llX] %s %s (pid = %d) (%s)\n", entry->gpuaddr, entry->gpuaddr + entry->size, entry->priv & KGSL_MEMDESC_GUARD_PAGE ? "(+guard)" : "", entry->pending_free ? "(pending free)" : "", - entry->pid, name); + entry->pid, entry->name); } static void _check_if_freed(struct kgsl_iommu_context *ctx, @@ -1395,7 +1478,7 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu) } } - kgsl_iommu_add_global(mmu, &iommu->setstate); + kgsl_iommu_add_global(mmu, &iommu->setstate, "setstate"); kgsl_setup_qdss_desc(device); done: @@ -2220,10 +2303,6 @@ static uint64_t kgsl_iommu_find_svm_region(struct kgsl_pagetable *pagetable, return addr; } -#define ADDR_IN_GLOBAL(_a) \ - (((_a) >= KGSL_IOMMU_GLOBAL_MEM_BASE) && \ - ((_a) < (KGSL_IOMMU_GLOBAL_MEM_BASE + KGSL_IOMMU_GLOBAL_MEM_SIZE))) - static int kgsl_iommu_set_svm_region(struct kgsl_pagetable *pagetable, uint64_t gpuaddr, uint64_t size) { |