Commit a2c763e0 authored by Ralf Baechle's avatar Ralf Baechle

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: default avatarRalf Baechle <ralf@linux-mips.org>
parent 088b530a
...@@ -34,38 +34,72 @@ ...@@ -34,38 +34,72 @@
*/ */
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
#define _PAGE_PRESENT (1<<6) /* implemented in software */ /*
#define _PAGE_READ (1<<7) /* implemented in software */ * The following bits are directly used by the TLB hardware
#define _PAGE_WRITE (1<<8) /* implemented in software */ */
#define _PAGE_ACCESSED (1<<9) /* implemented in software */ #define _PAGE_R4KBUG (1 << 0) /* workaround for r4k bug */
#define _PAGE_MODIFIED (1<<10) /* implemented in software */ #define _PAGE_GLOBAL (1 << 0)
#define _PAGE_FILE (1<<10) /* set:pagecache unset:swap */ #define _PAGE_VALID_SHIFT 1
#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT)
#define _PAGE_R4KBUG (1<<0) /* workaround for r4k bug */ #define _PAGE_SILENT_READ (1 << 1) /* synonym */
#define _PAGE_GLOBAL (1<<0) #define _PAGE_DIRTY_SHIFT 2
#define _PAGE_VALID (1<<1) #define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) /* The MIPS dirty bit */
#define _PAGE_SILENT_READ (1<<1) /* synonym */ #define _PAGE_SILENT_WRITE (1 << 2)
#define _PAGE_DIRTY (1<<2) /* The MIPS dirty bit */ #define _CACHE_SHIFT 3
#define _PAGE_SILENT_WRITE (1<<2) #define _CACHE_MASK (7 << 3)
#define _CACHE_SHIFT 3
#define _CACHE_MASK (7<<3) /*
* The following bits are implemented in software
*
* _PAGE_FILE semantics: set:pagecache unset:swap
*/
#define _PAGE_PRESENT_SHIFT 6
#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
#define _PAGE_READ_SHIFT 7
#define _PAGE_READ (1 << _PAGE_READ_SHIFT)
#define _PAGE_WRITE_SHIFT 8
#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT)
#define _PAGE_ACCESSED_SHIFT 9
#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT)
#define _PAGE_MODIFIED_SHIFT 10
#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
#define _PAGE_FILE (1 << 10)
#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
#define _PAGE_PRESENT (1<<0) /* implemented in software */ /*
#define _PAGE_READ (1<<1) /* implemented in software */ * The following are implemented by software
#define _PAGE_WRITE (1<<2) /* implemented in software */ *
#define _PAGE_ACCESSED (1<<3) /* implemented in software */ * _PAGE_FILE semantics: set:pagecache unset:swap
#define _PAGE_MODIFIED (1<<4) /* implemented in software */ */
#define _PAGE_FILE (1<<4) /* set:pagecache unset:swap */ #define _PAGE_PRESENT_SHIFT 0
#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
#define _PAGE_GLOBAL (1<<8) #define _PAGE_READ_SHIFT 1
#define _PAGE_VALID (1<<9) #define _PAGE_READ (1 << _PAGE_READ_SHIFT)
#define _PAGE_SILENT_READ (1<<9) /* synonym */ #define _PAGE_WRITE_SHIFT 2
#define _PAGE_DIRTY (1<<10) /* The MIPS dirty bit */ #define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT)
#define _PAGE_SILENT_WRITE (1<<10) #define _PAGE_ACCESSED_SHIFT 3
#define _CACHE_UNCACHED (1<<11) #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT)
#define _CACHE_MASK (1<<11) #define _PAGE_MODIFIED_SHIFT 4
#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
#define _PAGE_FILE_SHIFT 4
#define _PAGE_FILE (1 << _PAGE_FILE_SHIFT)
/*
* And these are the hardware TLB bits
*/
#define _PAGE_GLOBAL_SHIFT 8
#define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT)
#define _PAGE_VALID_SHIFT 9
#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT)
#define _PAGE_SILENT_READ (1 << _PAGE_VALID_SHIFT) /* synonym */
#define _PAGE_DIRTY_SHIFT 10
#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT)
#define _PAGE_SILENT_WRITE (1 << _PAGE_DIRTY_SHIFT)
#define _CACHE_UNCACHED_SHIFT 11
#define _CACHE_UNCACHED (1 << _CACHE_UNCACHED_SHIFT)
#define _CACHE_MASK (1 << _CACHE_UNCACHED_SHIFT)
#else /* 'Normal' r4K case */ #else /* 'Normal' r4K case */
/* /*
...@@ -76,22 +110,22 @@ ...@@ -76,22 +110,22 @@
* which is more than we need right now. * which is more than we need right now.
*/ */
/* implemented in software */ /*
* The following bits are implemented in software
*
* _PAGE_READ / _PAGE_READ_SHIFT should be unused if cpu_has_rixi.
* _PAGE_FILE semantics: set:pagecache unset:swap
*/
#define _PAGE_PRESENT_SHIFT (0) #define _PAGE_PRESENT_SHIFT (0)
#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
/* implemented in software, should be unused if cpu_has_rixi. */
#define _PAGE_READ_SHIFT (cpu_has_rixi ? _PAGE_PRESENT_SHIFT : _PAGE_PRESENT_SHIFT + 1) #define _PAGE_READ_SHIFT (cpu_has_rixi ? _PAGE_PRESENT_SHIFT : _PAGE_PRESENT_SHIFT + 1)
#define _PAGE_READ ({BUG_ON(cpu_has_rixi); 1 << _PAGE_READ_SHIFT; }) #define _PAGE_READ ({BUG_ON(cpu_has_rixi); 1 << _PAGE_READ_SHIFT; })
/* implemented in software */
#define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) #define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1)
#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) #define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT)
/* implemented in software */
#define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) #define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1)
#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT)
/* implemented in software */
#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) #define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1)
#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
/* set:pagecache unset:swap */
#define _PAGE_FILE (_PAGE_MODIFIED) #define _PAGE_FILE (_PAGE_MODIFIED)
#ifdef CONFIG_HUGETLB_PAGE #ifdef CONFIG_HUGETLB_PAGE
......
...@@ -206,19 +206,58 @@ static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance) ...@@ -206,19 +206,58 @@ static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
} }
/* /*
* For debug purposes. * pgtable bits are assigned dynamically depending on processor feature
* and statically based on kernel configuration. This spits out the actual
* values the kernel is using. Required to make sense from disassembled
* TLB exception handlers.
*/ */
static inline void dump_handler(const u32 *handler, int count) static void output_pgtable_bits_defines(void)
{
#define pr_define(fmt, ...) \
pr_debug("#define " fmt, ##__VA_ARGS__)
pr_debug("#include <asm/asm.h>\n");
pr_debug("#include <asm/regdef.h>\n");
pr_debug("\n");
pr_define("_PAGE_PRESENT_SHIFT %d\n", _PAGE_PRESENT_SHIFT);
pr_define("_PAGE_READ_SHIFT %d\n", _PAGE_READ_SHIFT);
pr_define("_PAGE_WRITE_SHIFT %d\n", _PAGE_WRITE_SHIFT);
pr_define("_PAGE_ACCESSED_SHIFT %d\n", _PAGE_ACCESSED_SHIFT);
pr_define("_PAGE_MODIFIED_SHIFT %d\n", _PAGE_MODIFIED_SHIFT);
#ifdef _PAGE_HUGE_SHIFT
pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT);
#endif
if (cpu_has_rixi) {
#ifdef _PAGE_NO_EXEC_SHIFT
pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT);
#endif
#ifdef _PAGE_NO_READ_SHIFT
pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT);
#endif
}
pr_define("_PAGE_GLOBAL_SHIFT %d\n", _PAGE_GLOBAL_SHIFT);
pr_define("_PAGE_VALID_SHIFT %d\n", _PAGE_VALID_SHIFT);
pr_define("_PAGE_DIRTY_SHIFT %d\n", _PAGE_DIRTY_SHIFT);
pr_define("_PFN_SHIFT %d\n", _PFN_SHIFT);
pr_debug("\n");
}
static inline void dump_handler(const char *symbol, const u32 *handler, int count)
{ {
int i; int i;
pr_debug("LEAF(%s)\n", symbol);
pr_debug("\t.set push\n"); pr_debug("\t.set push\n");
pr_debug("\t.set noreorder\n"); pr_debug("\t.set noreorder\n");
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
pr_debug("\t%p\t.word 0x%08x\n", &handler[i], handler[i]); pr_debug("\t.word\t0x%08x\t\t# %p\n", handler[i], &handler[i]);
pr_debug("\t.set pop\n"); pr_debug("\t.set\tpop\n");
pr_debug("\tEND(%s)\n", symbol);
} }
/* The only general purpose registers allowed in TLB handlers. */ /* The only general purpose registers allowed in TLB handlers. */
...@@ -401,7 +440,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void) ...@@ -401,7 +440,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void)
memcpy((void *)ebase, tlb_handler, 0x80); memcpy((void *)ebase, tlb_handler, 0x80);
dump_handler((u32 *)ebase, 32); dump_handler("r3000_tlb_refill", (u32 *)ebase, 32);
} }
#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
...@@ -1434,7 +1473,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void) ...@@ -1434,7 +1473,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
memcpy((void *)ebase, final_handler, 0x100); memcpy((void *)ebase, final_handler, 0x100);
dump_handler((u32 *)ebase, 64); dump_handler("r4000_tlb_refill", (u32 *)ebase, 64);
} }
/* /*
...@@ -1491,7 +1530,8 @@ static void __cpuinit build_r4000_setup_pgd(void) ...@@ -1491,7 +1530,8 @@ static void __cpuinit build_r4000_setup_pgd(void)
pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n", pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
(unsigned int)(p - tlbmiss_handler_setup_pgd)); (unsigned int)(p - tlbmiss_handler_setup_pgd));
dump_handler(tlbmiss_handler_setup_pgd, dump_handler("tlbmiss_handler",
tlbmiss_handler_setup_pgd,
ARRAY_SIZE(tlbmiss_handler_setup_pgd)); ARRAY_SIZE(tlbmiss_handler_setup_pgd));
} }
#endif #endif
...@@ -1761,7 +1801,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void) ...@@ -1761,7 +1801,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void)
pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
(unsigned int)(p - handle_tlbl)); (unsigned int)(p - handle_tlbl));
dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); dump_handler("r3000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl));
} }
static void __cpuinit build_r3000_tlb_store_handler(void) static void __cpuinit build_r3000_tlb_store_handler(void)
...@@ -1791,7 +1831,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void) ...@@ -1791,7 +1831,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void)
pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
(unsigned int)(p - handle_tlbs)); (unsigned int)(p - handle_tlbs));
dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); dump_handler("r3000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs));
} }
static void __cpuinit build_r3000_tlb_modify_handler(void) static void __cpuinit build_r3000_tlb_modify_handler(void)
...@@ -1821,7 +1861,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void) ...@@ -1821,7 +1861,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
(unsigned int)(p - handle_tlbm)); (unsigned int)(p - handle_tlbm));
dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); dump_handler("r3000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm));
} }
#endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */
...@@ -2028,7 +2068,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void) ...@@ -2028,7 +2068,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
(unsigned int)(p - handle_tlbl)); (unsigned int)(p - handle_tlbl));
dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); dump_handler("r4000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl));
} }
static void __cpuinit build_r4000_tlb_store_handler(void) static void __cpuinit build_r4000_tlb_store_handler(void)
...@@ -2075,7 +2115,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void) ...@@ -2075,7 +2115,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
(unsigned int)(p - handle_tlbs)); (unsigned int)(p - handle_tlbs));
dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); dump_handler("r4000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs));
} }
static void __cpuinit build_r4000_tlb_modify_handler(void) static void __cpuinit build_r4000_tlb_modify_handler(void)
...@@ -2123,7 +2163,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void) ...@@ -2123,7 +2163,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
(unsigned int)(p - handle_tlbm)); (unsigned int)(p - handle_tlbm));
dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm));
} }
void __cpuinit build_tlb_refill_handler(void) void __cpuinit build_tlb_refill_handler(void)
...@@ -2135,6 +2175,8 @@ void __cpuinit build_tlb_refill_handler(void) ...@@ -2135,6 +2175,8 @@ void __cpuinit build_tlb_refill_handler(void)
*/ */
static int run_once = 0; static int run_once = 0;
output_pgtable_bits_defines();
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3); check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment