aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2012-10-16 16:20:26 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-11-26 07:41:06 -0500
commita2c763e0747f28c7b2eb4c5058344790bfee0ed9 (patch)
treee73510c58f6c7907af34fe4456e8830c8675db2f
parent088b530a07ad64b25cc28ad84d879af0859f9bf5 (diff)
MIPS: tlbex: Better debug output.
Pgtable bits are assigned dynamically depending on processor feature and statically based on kernel configuration. To make sense out of the disassembled TLB exception handlers a list of the actual assignments used for a particular configuration and hardware setup can be very useful. Output the actual TLB exception handlers in a format that simplifies their post processsing from dmesg output. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/include/asm/pgtable-bits.h104
-rw-r--r--arch/mips/mm/tlbex.c68
2 files changed, 124 insertions, 48 deletions
diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h
index da4ba49adcf6..f8b8fb358412 100644
--- a/arch/mips/include/asm/pgtable-bits.h
+++ b/arch/mips/include/asm/pgtable-bits.h
@@ -34,38 +34,72 @@
34 */ 34 */
35#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) 35#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
36 36
37#define _PAGE_PRESENT (1<<6) /* implemented in software */ 37/*
38#define _PAGE_READ (1<<7) /* implemented in software */ 38 * The following bits are directly used by the TLB hardware
39#define _PAGE_WRITE (1<<8) /* implemented in software */ 39 */
40#define _PAGE_ACCESSED (1<<9) /* implemented in software */ 40#define _PAGE_R4KBUG (1 << 0) /* workaround for r4k bug */
41#define _PAGE_MODIFIED (1<<10) /* implemented in software */ 41#define _PAGE_GLOBAL (1 << 0)
42#define _PAGE_FILE (1<<10) /* set:pagecache unset:swap */ 42#define _PAGE_VALID_SHIFT 1
43 43#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT)
44#define _PAGE_R4KBUG (1<<0) /* workaround for r4k bug */ 44#define _PAGE_SILENT_READ (1 << 1) /* synonym */
45#define _PAGE_GLOBAL (1<<0) 45#define _PAGE_DIRTY_SHIFT 2
46#define _PAGE_VALID (1<<1) 46#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) /* The MIPS dirty bit */
47#define _PAGE_SILENT_READ (1<<1) /* synonym */ 47#define _PAGE_SILENT_WRITE (1 << 2)
48#define _PAGE_DIRTY (1<<2) /* The MIPS dirty bit */ 48#define _CACHE_SHIFT 3
49#define _PAGE_SILENT_WRITE (1<<2) 49#define _CACHE_MASK (7 << 3)
50#define _CACHE_SHIFT 3 50
51#define _CACHE_MASK (7<<3) 51/*
52 * The following bits are implemented in software
53 *
54 * _PAGE_FILE semantics: set:pagecache unset:swap
55 */
56#define _PAGE_PRESENT_SHIFT 6
57#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
58#define _PAGE_READ_SHIFT 7
59#define _PAGE_READ (1 << _PAGE_READ_SHIFT)
60#define _PAGE_WRITE_SHIFT 8
61#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT)
62#define _PAGE_ACCESSED_SHIFT 9
63#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT)
64#define _PAGE_MODIFIED_SHIFT 10
65#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
66
67#define _PAGE_FILE (1 << 10)
52 68
53#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) 69#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
54 70
55#define _PAGE_PRESENT (1<<0) /* implemented in software */ 71/*
56#define _PAGE_READ (1<<1) /* implemented in software */ 72 * The following are implemented by software
57#define _PAGE_WRITE (1<<2) /* implemented in software */ 73 *
58#define _PAGE_ACCESSED (1<<3) /* implemented in software */ 74 * _PAGE_FILE semantics: set:pagecache unset:swap
59#define _PAGE_MODIFIED (1<<4) /* implemented in software */ 75 */
60#define _PAGE_FILE (1<<4) /* set:pagecache unset:swap */ 76#define _PAGE_PRESENT_SHIFT 0
61 77#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
62#define _PAGE_GLOBAL (1<<8) 78#define _PAGE_READ_SHIFT 1
63#define _PAGE_VALID (1<<9) 79#define _PAGE_READ (1 << _PAGE_READ_SHIFT)
64#define _PAGE_SILENT_READ (1<<9) /* synonym */ 80#define _PAGE_WRITE_SHIFT 2
65#define _PAGE_DIRTY (1<<10) /* The MIPS dirty bit */ 81#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT)
66#define _PAGE_SILENT_WRITE (1<<10) 82#define _PAGE_ACCESSED_SHIFT 3
67#define _CACHE_UNCACHED (1<<11) 83#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT)
68#define _CACHE_MASK (1<<11) 84#define _PAGE_MODIFIED_SHIFT 4
85#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
86#define _PAGE_FILE_SHIFT 4
87#define _PAGE_FILE (1 << _PAGE_FILE_SHIFT)
88
89/*
90 * And these are the hardware TLB bits
91 */
92#define _PAGE_GLOBAL_SHIFT 8
93#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
94#define _PAGE_VALID_SHIFT 9
95#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT)
96#define _PAGE_SILENT_READ (1 << _PAGE_VALID_SHIFT) /* synonym */
97#define _PAGE_DIRTY_SHIFT 10
98#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT)
99#define _PAGE_SILENT_WRITE (1 << _PAGE_DIRTY_SHIFT)
100#define _CACHE_UNCACHED_SHIFT 11
101#define _CACHE_UNCACHED (1 << _CACHE_UNCACHED_SHIFT)
102#define _CACHE_MASK (1 << _CACHE_UNCACHED_SHIFT)
69 103
70#else /* 'Normal' r4K case */ 104#else /* 'Normal' r4K case */
71/* 105/*
@@ -76,22 +110,22 @@
76 * which is more than we need right now. 110 * which is more than we need right now.
77 */ 111 */
78 112
79/* implemented in software */ 113/*
114 * The following bits are implemented in software
115 *
116 * _PAGE_READ / _PAGE_READ_SHIFT should be unused if cpu_has_rixi.
117 * _PAGE_FILE semantics: set:pagecache unset:swap
118 */
80#define _PAGE_PRESENT_SHIFT (0) 119#define _PAGE_PRESENT_SHIFT (0)
81#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) 120#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
82/* implemented in software, should be unused if cpu_has_rixi. */
83#define _PAGE_READ_SHIFT (cpu_has_rixi ? _PAGE_PRESENT_SHIFT : _PAGE_PRESENT_SHIFT + 1) 121#define _PAGE_READ_SHIFT (cpu_has_rixi ? _PAGE_PRESENT_SHIFT : _PAGE_PRESENT_SHIFT + 1)
84#define _PAGE_READ ({BUG_ON(cpu_has_rixi); 1 << _PAGE_READ_SHIFT; }) 122#define _PAGE_READ ({BUG_ON(cpu_has_rixi); 1 << _PAGE_READ_SHIFT; })
85/* implemented in software */
86#define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) 123#define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1)
87#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) 124#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT)
88/* implemented in software */
89#define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) 125#define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1)
90#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) 126#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT)
91/* implemented in software */
92#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) 127#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1)
93#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) 128#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
94/* set:pagecache unset:swap */
95#define _PAGE_FILE (_PAGE_MODIFIED) 129#define _PAGE_FILE (_PAGE_MODIFIED)
96 130
97#ifdef CONFIG_HUGETLB_PAGE 131#ifdef CONFIG_HUGETLB_PAGE
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 9c068acaeaee..a36b4955d4ed 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -206,19 +206,58 @@ static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
206} 206}
207 207
208/* 208/*
209 * For debug purposes. 209 * pgtable bits are assigned dynamically depending on processor feature
210 * and statically based on kernel configuration. This spits out the actual
211 * values the kernel is using. Required to make sense from disassembled
212 * TLB exception handlers.
210 */ 213 */
211static inline void dump_handler(const u32 *handler, int count) 214static void output_pgtable_bits_defines(void)
215{
216#define pr_define(fmt, ...) \
217 pr_debug("#define " fmt, ##__VA_ARGS__)
218
219 pr_debug("#include <asm/asm.h>\n");
220 pr_debug("#include <asm/regdef.h>\n");
221 pr_debug("\n");
222
223 pr_define("_PAGE_PRESENT_SHIFT %d\n", _PAGE_PRESENT_SHIFT);
224 pr_define("_PAGE_READ_SHIFT %d\n", _PAGE_READ_SHIFT);
225 pr_define("_PAGE_WRITE_SHIFT %d\n", _PAGE_WRITE_SHIFT);
226 pr_define("_PAGE_ACCESSED_SHIFT %d\n", _PAGE_ACCESSED_SHIFT);
227 pr_define("_PAGE_MODIFIED_SHIFT %d\n", _PAGE_MODIFIED_SHIFT);
228#ifdef _PAGE_HUGE_SHIFT
229 pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT);
230#endif
231 if (cpu_has_rixi) {
232#ifdef _PAGE_NO_EXEC_SHIFT
233 pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT);
234#endif
235#ifdef _PAGE_NO_READ_SHIFT
236 pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT);
237#endif
238 }
239 pr_define("_PAGE_GLOBAL_SHIFT %d\n", _PAGE_GLOBAL_SHIFT);
240 pr_define("_PAGE_VALID_SHIFT %d\n", _PAGE_VALID_SHIFT);
241 pr_define("_PAGE_DIRTY_SHIFT %d\n", _PAGE_DIRTY_SHIFT);
242 pr_define("_PFN_SHIFT %d\n", _PFN_SHIFT);
243 pr_debug("\n");
244}
245
246static inline void dump_handler(const char *symbol, const u32 *handler, int count)
212{ 247{
213 int i; 248 int i;
214 249
250 pr_debug("LEAF(%s)\n", symbol);
251
215 pr_debug("\t.set push\n"); 252 pr_debug("\t.set push\n");
216 pr_debug("\t.set noreorder\n"); 253 pr_debug("\t.set noreorder\n");
217 254
218 for (i = 0; i < count; i++) 255 for (i = 0; i < count; i++)
219 pr_debug("\t%p\t.word 0x%08x\n", &handler[i], handler[i]); 256 pr_debug("\t.word\t0x%08x\t\t# %p\n", handler[i], &handler[i]);
220 257
221 pr_debug("\t.set pop\n"); 258 pr_debug("\t.set\tpop\n");
259
260 pr_debug("\tEND(%s)\n", symbol);
222} 261}
223 262
224/* The only general purpose registers allowed in TLB handlers. */ 263/* The only general purpose registers allowed in TLB handlers. */
@@ -401,7 +440,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void)
401 440
402 memcpy((void *)ebase, tlb_handler, 0x80); 441 memcpy((void *)ebase, tlb_handler, 0x80);
403 442
404 dump_handler((u32 *)ebase, 32); 443 dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
405} 444}
406#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ 445#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
407 446
@@ -1434,7 +1473,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
1434 1473
1435 memcpy((void *)ebase, final_handler, 0x100); 1474 memcpy((void *)ebase, final_handler, 0x100);
1436 1475
1437 dump_handler((u32 *)ebase, 64); 1476 dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
1438} 1477}
1439 1478
1440/* 1479/*
@@ -1491,7 +1530,8 @@ static void __cpuinit build_r4000_setup_pgd(void)
1491 pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n", 1530 pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
1492 (unsigned int)(p - tlbmiss_handler_setup_pgd)); 1531 (unsigned int)(p - tlbmiss_handler_setup_pgd));
1493 1532
1494 dump_handler(tlbmiss_handler_setup_pgd, 1533 dump_handler("tlbmiss_handler",
1534 tlbmiss_handler_setup_pgd,
1495 ARRAY_SIZE(tlbmiss_handler_setup_pgd)); 1535 ARRAY_SIZE(tlbmiss_handler_setup_pgd));
1496} 1536}
1497#endif 1537#endif
@@ -1761,7 +1801,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void)
1761 pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", 1801 pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
1762 (unsigned int)(p - handle_tlbl)); 1802 (unsigned int)(p - handle_tlbl));
1763 1803
1764 dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); 1804 dump_handler("r3000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl));
1765} 1805}
1766 1806
1767static void __cpuinit build_r3000_tlb_store_handler(void) 1807static void __cpuinit build_r3000_tlb_store_handler(void)
@@ -1791,7 +1831,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void)
1791 pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", 1831 pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
1792 (unsigned int)(p - handle_tlbs)); 1832 (unsigned int)(p - handle_tlbs));
1793 1833
1794 dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); 1834 dump_handler("r3000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs));
1795} 1835}
1796 1836
1797static void __cpuinit build_r3000_tlb_modify_handler(void) 1837static void __cpuinit build_r3000_tlb_modify_handler(void)
@@ -1821,7 +1861,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
1821 pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", 1861 pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
1822 (unsigned int)(p - handle_tlbm)); 1862 (unsigned int)(p - handle_tlbm));
1823 1863
1824 dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); 1864 dump_handler("r3000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm));
1825} 1865}
1826#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ 1866#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
1827 1867
@@ -2028,7 +2068,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
2028 pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", 2068 pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
2029 (unsigned int)(p - handle_tlbl)); 2069 (unsigned int)(p - handle_tlbl));
2030 2070
2031 dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); 2071 dump_handler("r4000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl));
2032} 2072}
2033 2073
2034static void __cpuinit build_r4000_tlb_store_handler(void) 2074static void __cpuinit build_r4000_tlb_store_handler(void)
@@ -2075,7 +2115,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
2075 pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", 2115 pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
2076 (unsigned int)(p - handle_tlbs)); 2116 (unsigned int)(p - handle_tlbs));
2077 2117
2078 dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); 2118 dump_handler("r4000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs));
2079} 2119}
2080 2120
2081static void __cpuinit build_r4000_tlb_modify_handler(void) 2121static void __cpuinit build_r4000_tlb_modify_handler(void)
@@ -2123,7 +2163,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
2123 pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", 2163 pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
2124 (unsigned int)(p - handle_tlbm)); 2164 (unsigned int)(p - handle_tlbm));
2125 2165
2126 dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); 2166 dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm));
2127} 2167}
2128 2168
2129void __cpuinit build_tlb_refill_handler(void) 2169void __cpuinit build_tlb_refill_handler(void)
@@ -2135,6 +2175,8 @@ void __cpuinit build_tlb_refill_handler(void)
2135 */ 2175 */
2136 static int run_once = 0; 2176 static int run_once = 0;
2137 2177
2178 output_pgtable_bits_defines();
2179
2138#ifdef CONFIG_64BIT 2180#ifdef CONFIG_64BIT
2139 check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3); 2181 check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
2140#endif 2182#endif