From: Grazvydas Ignotas Date: Sun, 1 Jun 2014 21:42:26 +0000 (+0300) Subject: task_mmu.c: show multiple entries if attrs differ X-Git-Tag: sz_173~103 X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=commitdiff_plain;h=c5fd6bc55245c79d586df8541498a3f2204ae7bc task_mmu.c: show multiple entries if attrs differ --- diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index e8b5ef54455f..bc02b6b966dc 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -210,134 +210,196 @@ static int do_maps_open(struct inode *inode, struct file *file, } #ifdef __arm__ -static int show_arm_cache_attrs(struct seq_file *m, void *pgd, - unsigned long start, unsigned long end, vm_flags_t flags) +static void show_arm_map_vma(struct seq_file *m, struct vm_area_struct *vma) { static const char *cache_attrs4[4] = { "noC", "WB-WA", "WT-noWA", "WB-noWA" }; - u32 *arm_pgd = pgd, *cpt; + struct mm_struct *mm = vma->vm_mm; + struct file *file = vma->vm_file; + vm_flags_t flags = vma->vm_flags; + unsigned long start, end, end_b; + const char *name = NULL; + u32 *arm_pgd; + u32 *cpt, *cpt_e; u32 desc1, desc2; u32 tex_cb = 0; u32 prrr, nmrr = 0; u32 control = 0; u32 xn = 1, ap = 0; + int desc_type; int type; char buf[64]; char rw[4]; int len; int s; - desc1 = arm_pgd[start >> 20]; + if (mm == NULL) + return; - switch (desc1 & 3) { - case 0: - sprintf(buf, "l1_fault"); - goto out; - case 1: - break; - case 2: - tex_cb = ((desc1 >> 2) & 0x03) | ((desc1 >> 10) & 0x1c); - s = (desc1 >> 16) & 1; - xn = (desc1 >> 4) & 1; - ap = ((desc1 >> 10) & 3) | ((desc1 >> 13) & 4); - goto do_tex_cb; - case 3: - sprintf(buf, "reserved"); - goto out; + if (!file) { + name = arch_vma_name(vma); + if (!name) { + if (vma->vm_start <= mm->brk && + vma->vm_end >= mm->start_brk) { + name = "[heap]"; + } else if (vma->vm_start <= mm->start_stack && + vma->vm_end >= mm->start_stack) { + name = "[stack]"; + } + } } - cpt = __va(desc1 & 0xfffffc00); - desc2 = cpt[(start >> 12) & 0xff]; + arm_pgd = (u32 *)mm->pgd; - switch (desc2 & 3) { - case 0: - sprintf(buf, "l2_fault"); - goto out; - case 1: - tex_cb = ((desc2 >> 2) & 0x03) | ((desc2 >> 10) & 0x1c); - s = (desc2 >> 10) & 1; - xn = (desc2 >> 15) & 1; - ap = ((desc2 >> 4) & 3) | ((desc1 >> 7) & 4); - break; - case 2: - case 3: - tex_cb = ((desc2 >> 2) & 0x03) | ((desc2 >> 4) & 0x1c); - s = (desc2 >> 10) & 1; - xn = desc2 & 1; - ap = ((desc2 >> 4) & 3) | ((desc1 >> 7) & 4); - break; - } - -do_tex_cb: asm ("mrc p15, 0, %0, c1, c0, 0" : "=r"(control)); asm ("mrc p15, 0, %0, c10, c2, 0" : "=r"(prrr)); // primary region RR asm ("mrc p15, 0, %0, c10, c2, 1" : "=r"(nmrr)); // normal memory RR - if (control & (1 << 28)) { // TEX remap - // S (shareable) bit remapping - char s_normal[2] = { (prrr >> 18) & 1, (prrr >> 19) & 1 }; - char s_device[2] = { (prrr >> 16) & 1, (prrr >> 17) & 1 }; + start = vma->vm_start; + end = vma->vm_end; + + while (start < end) { + desc_type = '-'; + + desc1 = arm_pgd[start >> 20]; + + end_b = (start & ~0xfffff) + 0x100000; + for (; end_b < end; end_b += 0x100000) + if ((arm_pgd[end_b >> 20] ^ desc1) & 0xfffff) + break; - buf[0] = 0; - tex_cb &= 7; - type = (prrr >> tex_cb * 2) & 3; - switch (type) { + switch (desc1 & 3) { case 0: - sprintf(buf, "strongly-ordered"); - break; + sprintf(buf, "l1_fault"); + goto do_output; case 1: - sprintf(buf, "device"); - s = s_device[s]; break; + case 2: + tex_cb = ((desc1 >> 2) & 0x03) | ((desc1 >> 10) & 0x1c); + s = (desc1 >> 16) & 1; + xn = (desc1 >> 4) & 1; + ap = ((desc1 >> 10) & 3) | ((desc1 >> 13) & 4); + desc_type = (desc1 & (1 << 18)) ? 's' : 'h'; + goto do_tex_cb; case 3: - sprintf(buf, "reserved/normal"); + sprintf(buf, "reserved"); + goto do_output; + } + + cpt = __va(desc1 & 0xfffffc00); + desc2 = cpt[(start >> 12) & 0xff]; + + // find end + cpt_e = cpt; + for (end_b = start + 0x1000; end_b < end; end_b += 0x1000) { + if ((end_b & 0x000ff000) == 0) { + cpt_e = __va(arm_pgd[end_b >> 20] & 0xfffffc00); + if ((arm_pgd[end_b >> 20] ^ desc1) & 0x3ff) + break; + } + + // assume small pages + if ((cpt_e[(end_b >> 12) & 0xff] ^ desc2) & 0xfff) + break; + } + + switch (desc2 & 3) { + case 0: + sprintf(buf, "l2_fault"); + goto do_output; + case 1: + tex_cb = ((desc2 >> 2) & 0x03) | ((desc2 >> 10) & 0x1c); + s = (desc2 >> 10) & 1; + xn = (desc2 >> 15) & 1; + ap = ((desc2 >> 4) & 3) | ((desc2 >> 7) & 4); + break; case 2: - s = s_normal[s]; - sprintf(buf + strlen(buf), "inner-%s-outer-%s", - cache_attrs4[(nmrr >> tex_cb * 2) & 3], - cache_attrs4[(nmrr >> (tex_cb * 2 + 16)) & 3]); + case 3: + tex_cb = ((desc2 >> 2) & 0x03) | ((desc2 >> 4) & 0x1c); + s = (desc2 >> 10) & 1; + xn = desc2 & 1; + ap = ((desc2 >> 4) & 3) | ((desc2 >> 7) & 4); + break; } - } - else if (tex_cb & 0x10) { // TEX[2] set - sprintf(buf, "inner-%s-outer-%s", - cache_attrs4[tex_cb & 3], cache_attrs4[(tex_cb >> 2) & 3]); - } - else { - switch (tex_cb) { - case 0x00: sprintf(buf, "strongly-ordered"); s = 1; break; - case 0x01: sprintf(buf, "shareable-device"); s = 1; break; - case 0x02: sprintf(buf, "inner-outer-WT-noWA"); break; - case 0x03: sprintf(buf, "inner-outer-WB-noWA"); break; - case 0x04: sprintf(buf, "inner-outer-non-cacheable"); break; - case 0x06: sprintf(buf, "implementation-defined"); break; - case 0x07: sprintf(buf, "inner-outer-WB-WA"); break; - case 0x08: sprintf(buf, "non-shareable-device"); s = 0; break; - default: sprintf(buf, "reserved"); break; + +do_tex_cb: + if (control & (1 << 28)) { // TEX remap + // S (shareable) bit remapping + char s_normal[2] = { (prrr >> 18) & 1, (prrr >> 19) & 1 }; + char s_device[2] = { (prrr >> 16) & 1, (prrr >> 17) & 1 }; + + buf[0] = 0; + tex_cb &= 7; + type = (prrr >> tex_cb * 2) & 3; + switch (type) { + case 0: + sprintf(buf, "strongly-ordered"); + break; + case 1: + sprintf(buf, "device"); + s = s_device[s]; + break; + case 3: + sprintf(buf, "reserved/normal"); + case 2: + s = s_normal[s]; + sprintf(buf + strlen(buf), "inner-%s-outer-%s", + cache_attrs4[(nmrr >> tex_cb * 2) & 3], + cache_attrs4[(nmrr >> (tex_cb * 2 + 16)) & 3]); + } + } + else if (tex_cb & 0x10) { // TEX[2] set + sprintf(buf, "inner-%s-outer-%s", + cache_attrs4[tex_cb & 3], cache_attrs4[(tex_cb >> 2) & 3]); + } + else { + switch (tex_cb) { + case 0x00: sprintf(buf, "strongly-ordered"); s = 1; break; + case 0x01: sprintf(buf, "shareable-device"); s = 1; break; + case 0x02: sprintf(buf, "inner-outer-WT-noWA"); break; + case 0x03: sprintf(buf, "inner-outer-WB-noWA"); break; + case 0x04: sprintf(buf, "inner-outer-non-cacheable"); break; + case 0x06: sprintf(buf, "implementation-defined"); break; + case 0x07: sprintf(buf, "inner-outer-WB-WA"); break; + case 0x08: sprintf(buf, "non-shareable-device"); s = 0; break; + default: sprintf(buf, "reserved"); break; + } } - } - if (s) - sprintf(buf + strlen(buf), "-shareable"); + if (s) + sprintf(buf + strlen(buf), "-shareable"); -out: - // use user permissions here - if (control & (1 << 29)) // AFE - sprintf(rw, "%c%c", (ap & 2) ? 'r' : '-', - ((ap & 2) && !(ap & 4)) ? 'w' : '-'); - else - sprintf(rw, "%c%c", (ap & 2) ? 'r' : '-', - (ap == 3) ? 'w' : '-'); - - seq_printf(m, "%08lx-%08lx %s%c %-28s %n", - start, end, rw, - xn ? '-' : 'x', - buf, &len); - - return len; +do_output: + // use user permissions here + if (control & (1 << 29)) // AFE + sprintf(rw, "%c%c", (ap & 2) ? 'r' : '-', + ((ap & 2) && !(ap & 4)) ? 'w' : '-'); + else + sprintf(rw, "%c%c", (ap & 2) ? 'r' : '-', + (ap == 3) ? 'w' : '-'); + + seq_printf(m, "%08lx-%08lx %s%c%c%c %-28s %n", + start, end_b, + rw, + xn ? '-' : 'x', + flags & VM_MAYSHARE ? 's' : 'p', + desc_type, + buf, &len); + + if (file) { + pad_len_spaces(m, len); + seq_path(m, &file->f_path, "\n"); + } else if (name) { + pad_len_spaces(m, len); + seq_puts(m, name); + } + seq_putc(m, '\n'); + + start = end_b; + } } #endif -static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma, - int cache_attrs) +static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) { struct mm_struct *mm = vma->vm_mm; struct file *file = vma->vm_file; @@ -363,12 +425,7 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma, if (stack_guard_page_end(vma, end)) end -= PAGE_SIZE; -#ifdef __arm__ - if (cache_attrs) - len = show_arm_cache_attrs(m, mm->pgd, start, end, flags); - else -#endif - seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", + seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", start, end, flags & VM_READ ? 'r' : '-', @@ -414,7 +471,7 @@ static int show_map(struct seq_file *m, void *v) struct proc_maps_private *priv = m->private; struct task_struct *task = priv->task; - show_map_vma(m, vma, 0); + show_map_vma(m, vma); if (m->count < m->size) /* vma is copied successfully */ m->version = (vma != get_gate_vma(task->mm)) @@ -441,13 +498,14 @@ const struct file_operations proc_maps_operations = { .release = seq_release_private, }; +#ifdef __arm__ static int show_armv7_map(struct seq_file *m, void *v) { struct vm_area_struct *vma = v; struct proc_maps_private *priv = m->private; struct task_struct *task = priv->task; - show_map_vma(m, vma, 1); + show_arm_map_vma(m, vma); if (m->count < m->size) /* vma is copied successfully */ m->version = (vma != get_gate_vma(task->mm)) @@ -461,6 +519,7 @@ static const struct seq_operations proc_pid_armv7_maps_op = { .stop = m_stop, .show = show_armv7_map }; +#endif static int armv7_maps_open(struct inode *inode, struct file *file) { @@ -609,7 +668,7 @@ static int show_smap(struct seq_file *m, void *v) if (vma->vm_mm && !is_vm_hugetlb_page(vma)) walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); - show_map_vma(m, vma, 0); + show_map_vma(m, vma); seq_printf(m, "Size: %8lu kB\n"