Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sh: tlb debugfs support.

Export the status of the utlb and itlb entries through debugfs.

Signed-off-by: Matt Fleming <matt@console-pimps.org>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>

authored by

Matt Fleming and committed by
Paul Mundt
6ae66502 4bea3418

+191 -3
+7
arch/sh/include/cpu-sh4/cpu/mmu_context.h
··· 19 19 20 20 #define MMUCR 0xFF000010 /* MMU Control Register */ 21 21 22 + #define MMU_TLB_ENTRY_SHIFT 8 23 + 22 24 #define MMU_ITLB_ADDRESS_ARRAY 0xF2000000 23 25 #define MMU_ITLB_ADDRESS_ARRAY2 0xF2800000 26 + #define MMU_ITLB_DATA_ARRAY 0xF3000000 27 + #define MMU_ITLB_DATA_ARRAY2 0xF3800000 28 + 24 29 #define MMU_UTLB_ADDRESS_ARRAY 0xF6000000 25 30 #define MMU_UTLB_ADDRESS_ARRAY2 0xF6800000 31 + #define MMU_UTLB_DATA_ARRAY 0xF7000000 32 + #define MMU_UTLB_DATA_ARRAY2 0xF7800000 26 33 #define MMU_PAGE_ASSOC_BIT 0x80 27 34 28 35 #define MMUCR_TI (1<<2)
+5 -3
arch/sh/mm/Makefile
··· 18 18 ioremap.o kmap.o pgtable.o tlbflush_$(BITS).o 19 19 20 20 obj-y += $(mmu-y) 21 - obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o 22 21 23 - ifdef CONFIG_DEBUG_FS 24 - obj-$(CONFIG_CPU_SH4) += cache-debugfs.o 22 + debugfs-y := asids-debugfs.o 23 + ifndef CONFIG_CACHE_OFF 24 + debugfs-$(CONFIG_CPU_SH4) += cache-debugfs.o 25 25 endif 26 26 27 27 ifdef CONFIG_MMU 28 + debugfs-$(CONFIG_CPU_SH4) += tlb-debugfs.o 28 29 tlb-$(CONFIG_CPU_SH3) := tlb-sh3.o 29 30 tlb-$(CONFIG_CPU_SH4) := tlb-sh4.o tlb-urb.o 30 31 tlb-$(CONFIG_CPU_SH5) := tlb-sh5.o ··· 33 32 obj-y += $(tlb-y) 34 33 endif 35 34 35 + obj-$(CONFIG_DEBUG_FS) += $(debugfs-y) 36 36 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 37 37 obj-$(CONFIG_PMB) += pmb.o 38 38 obj-$(CONFIG_NUMA) += numa.o
+179
arch/sh/mm/tlb-debugfs.c
··· 1 + /* 2 + * arch/sh/mm/tlb-debugfs.c 3 + * 4 + * debugfs ops for SH-4 ITLB/UTLBs. 5 + * 6 + * Copyright (C) 2010 Matt Fleming 7 + * 8 + * This file is subject to the terms and conditions of the GNU General Public 9 + * License. See the file "COPYING" in the main directory of this archive 10 + * for more details. 11 + */ 12 + #include <linux/init.h> 13 + #include <linux/module.h> 14 + #include <linux/debugfs.h> 15 + #include <linux/seq_file.h> 16 + #include <asm/processor.h> 17 + #include <asm/mmu_context.h> 18 + #include <asm/tlbflush.h> 19 + 20 + enum tlb_type { 21 + TLB_TYPE_ITLB, 22 + TLB_TYPE_UTLB, 23 + }; 24 + 25 + static struct { 26 + int bits; 27 + const char *size; 28 + } tlb_sizes[] = { 29 + { 0x0, " 1KB" }, 30 + { 0x1, " 4KB" }, 31 + { 0x2, " 8KB" }, 32 + { 0x4, " 64KB" }, 33 + { 0x5, "256KB" }, 34 + { 0x7, " 1MB" }, 35 + { 0x8, " 4MB" }, 36 + { 0xc, " 64MB" }, 37 + }; 38 + 39 + static int tlb_seq_show(struct seq_file *file, void *iter) 40 + { 41 + unsigned int tlb_type = (unsigned int)file->private; 42 + unsigned long addr1, addr2, data1, data2; 43 + unsigned long flags; 44 + unsigned long mmucr; 45 + unsigned int nentries, entry; 46 + unsigned int urb; 47 + 48 + mmucr = __raw_readl(MMUCR); 49 + if ((mmucr & 0x1) == 0) { 50 + seq_printf(file, "address translation disabled\n"); 51 + return 0; 52 + } 53 + 54 + if (tlb_type == TLB_TYPE_ITLB) { 55 + addr1 = MMU_ITLB_ADDRESS_ARRAY; 56 + addr2 = MMU_ITLB_ADDRESS_ARRAY2; 57 + data1 = MMU_ITLB_DATA_ARRAY; 58 + data2 = MMU_ITLB_DATA_ARRAY2; 59 + nentries = 4; 60 + } else { 61 + addr1 = MMU_UTLB_ADDRESS_ARRAY; 62 + addr2 = MMU_UTLB_ADDRESS_ARRAY2; 63 + data1 = MMU_UTLB_DATA_ARRAY; 64 + data2 = MMU_UTLB_DATA_ARRAY2; 65 + nentries = 64; 66 + } 67 + 68 + local_irq_save(flags); 69 + jump_to_uncached(); 70 + 71 + urb = (mmucr & MMUCR_URB) >> MMUCR_URB_SHIFT; 72 + 73 + /* Make the "entry >= urb" test fail. */ 74 + if (urb == 0) 75 + urb = MMUCR_URB_NENTRIES + 1; 76 + 77 + if (tlb_type == TLB_TYPE_ITLB) { 78 + addr1 = MMU_ITLB_ADDRESS_ARRAY; 79 + addr2 = MMU_ITLB_ADDRESS_ARRAY2; 80 + data1 = MMU_ITLB_DATA_ARRAY; 81 + data2 = MMU_ITLB_DATA_ARRAY2; 82 + nentries = 4; 83 + } else { 84 + addr1 = MMU_UTLB_ADDRESS_ARRAY; 85 + addr2 = MMU_UTLB_ADDRESS_ARRAY2; 86 + data1 = MMU_UTLB_DATA_ARRAY; 87 + data2 = MMU_UTLB_DATA_ARRAY2; 88 + nentries = 64; 89 + } 90 + 91 + seq_printf(file, "entry: vpn ppn asid size valid wired\n"); 92 + 93 + for (entry = 0; entry < nentries; entry++) { 94 + unsigned long vpn, ppn, asid, size; 95 + unsigned long valid; 96 + unsigned long val; 97 + const char *sz = " ?"; 98 + int i; 99 + 100 + val = __raw_readl(addr1 | (entry << MMU_TLB_ENTRY_SHIFT)); 101 + ctrl_barrier(); 102 + vpn = val & 0xfffffc00; 103 + valid = val & 0x100; 104 + 105 + val = __raw_readl(addr2 | (entry << MMU_TLB_ENTRY_SHIFT)); 106 + ctrl_barrier(); 107 + asid = val & MMU_CONTEXT_ASID_MASK; 108 + 109 + val = __raw_readl(data1 | (entry << MMU_TLB_ENTRY_SHIFT)); 110 + ctrl_barrier(); 111 + ppn = (val & 0x0ffffc00) << 4; 112 + 113 + val = __raw_readl(data2 | (entry << MMU_TLB_ENTRY_SHIFT)); 114 + ctrl_barrier(); 115 + size = (val & 0xf0) >> 4; 116 + 117 + for (i = 0; i < ARRAY_SIZE(tlb_sizes); i++) { 118 + if (tlb_sizes[i].bits == size) 119 + break; 120 + } 121 + 122 + if (i != ARRAY_SIZE(tlb_sizes)) 123 + sz = tlb_sizes[i].size; 124 + 125 + seq_printf(file, "%2d: 0x%08lx 0x%08lx %5lu %s %s %s\n", 126 + entry, vpn, ppn, asid, 127 + sz, valid ? "V" : "-", 128 + (urb <= entry) ? "W" : "-"); 129 + } 130 + 131 + back_to_cached(); 132 + local_irq_restore(flags); 133 + 134 + return 0; 135 + } 136 + 137 + static int tlb_debugfs_open(struct inode *inode, struct file *file) 138 + { 139 + return single_open(file, tlb_seq_show, inode->i_private); 140 + } 141 + 142 + static const struct file_operations tlb_debugfs_fops = { 143 + .owner = THIS_MODULE, 144 + .open = tlb_debugfs_open, 145 + .read = seq_read, 146 + .llseek = seq_lseek, 147 + .release = single_release, 148 + }; 149 + 150 + static int __init tlb_debugfs_init(void) 151 + { 152 + struct dentry *itlb, *utlb; 153 + 154 + itlb = debugfs_create_file("itlb", S_IRUSR, sh_debugfs_root, 155 + (unsigned int *)TLB_TYPE_ITLB, 156 + &tlb_debugfs_fops); 157 + if (unlikely(!itlb)) 158 + return -ENOMEM; 159 + if (IS_ERR(itlb)) 160 + return PTR_ERR(itlb); 161 + 162 + utlb = debugfs_create_file("utlb", S_IRUSR, sh_debugfs_root, 163 + (unsigned int *)TLB_TYPE_UTLB, 164 + &tlb_debugfs_fops); 165 + if (unlikely(!utlb)) { 166 + debugfs_remove(itlb); 167 + return -ENOMEM; 168 + } 169 + 170 + if (IS_ERR(utlb)) { 171 + debugfs_remove(itlb); 172 + return PTR_ERR(utlb); 173 + } 174 + 175 + return 0; 176 + } 177 + module_init(tlb_debugfs_init); 178 + 179 + MODULE_LICENSE("GPL v2");