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>
This commit is contained in:
Ralf Baechle 2012-10-16 22:20:26 +02:00
parent 088b530a07
commit a2c763e074
2 changed files with 122 additions and 46 deletions

View File

@ -34,38 +34,72 @@
*/
#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 */
#define _PAGE_WRITE (1<<8) /* implemented in software */
#define _PAGE_ACCESSED (1<<9) /* implemented in software */
#define _PAGE_MODIFIED (1<<10) /* implemented in software */
#define _PAGE_FILE (1<<10) /* set:pagecache unset:swap */
/*
* The following bits are directly used by the TLB hardware
*/
#define _PAGE_R4KBUG (1 << 0) /* workaround for r4k bug */
#define _PAGE_GLOBAL (1 << 0)
#define _PAGE_VALID_SHIFT 1
#define _PAGE_VALID (1 << _PAGE_VALID_SHIFT)
#define _PAGE_SILENT_READ (1 << 1) /* synonym */
#define _PAGE_DIRTY_SHIFT 2
#define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) /* The MIPS dirty bit */
#define _PAGE_SILENT_WRITE (1 << 2)
#define _CACHE_SHIFT 3
#define _CACHE_MASK (7 << 3)
#define _PAGE_R4KBUG (1<<0) /* workaround for r4k bug */
#define _PAGE_GLOBAL (1<<0)
#define _PAGE_VALID (1<<1)
#define _PAGE_SILENT_READ (1<<1) /* synonym */
#define _PAGE_DIRTY (1<<2) /* The MIPS dirty bit */
#define _PAGE_SILENT_WRITE (1<<2)
#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)
#define _PAGE_PRESENT (1<<0) /* implemented in software */
#define _PAGE_READ (1<<1) /* implemented in software */
#define _PAGE_WRITE (1<<2) /* implemented in software */
#define _PAGE_ACCESSED (1<<3) /* implemented in software */
#define _PAGE_MODIFIED (1<<4) /* implemented in software */
#define _PAGE_FILE (1<<4) /* set:pagecache unset:swap */
/*
* The following are implemented by software
*
* _PAGE_FILE semantics: set:pagecache unset:swap
*/
#define _PAGE_PRESENT_SHIFT 0
#define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT)
#define _PAGE_READ_SHIFT 1
#define _PAGE_READ (1 << _PAGE_READ_SHIFT)
#define _PAGE_WRITE_SHIFT 2
#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT)
#define _PAGE_ACCESSED_SHIFT 3
#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT)
#define _PAGE_MODIFIED_SHIFT 4
#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
#define _PAGE_FILE_SHIFT 4
#define _PAGE_FILE (1 << _PAGE_FILE_SHIFT)
#define _PAGE_GLOBAL (1<<8)
#define _PAGE_VALID (1<<9)
#define _PAGE_SILENT_READ (1<<9) /* synonym */
#define _PAGE_DIRTY (1<<10) /* The MIPS dirty bit */
#define _PAGE_SILENT_WRITE (1<<10)
#define _CACHE_UNCACHED (1<<11)
#define _CACHE_MASK (1<<11)
/*
* 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 */
/*
@ -76,22 +110,22 @@
* 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 (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 ({BUG_ON(cpu_has_rixi); 1 << _PAGE_READ_SHIFT; })
/* implemented in software */
#define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1)
#define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT)
/* implemented in software */
#define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1)
#define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT)
/* implemented in software */
#define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1)
#define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT)
/* set:pagecache unset:swap */
#define _PAGE_FILE (_PAGE_MODIFIED)
#ifdef CONFIG_HUGETLB_PAGE

View File

@ -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;
pr_debug("LEAF(%s)\n", symbol);
pr_debug("\t.set push\n");
pr_debug("\t.set noreorder\n");
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. */
@ -401,7 +440,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void)
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 */
@ -1434,7 +1473,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
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)
pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
(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));
}
#endif
@ -1761,7 +1801,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void)
pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
(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)
@ -1791,7 +1831,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void)
pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
(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)
@ -1821,7 +1861,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void)
pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
(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 */
@ -2028,7 +2068,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
pr_debug("Wrote TLB load handler fastpath (%u instructions).\n",
(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)
@ -2075,7 +2115,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void)
pr_debug("Wrote TLB store handler fastpath (%u instructions).\n",
(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)
@ -2123,7 +2163,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n",
(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)
@ -2135,6 +2175,8 @@ void __cpuinit build_tlb_refill_handler(void)
*/
static int run_once = 0;
output_pgtable_bits_defines();
#ifdef CONFIG_64BIT
check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
#endif