forked from Minki/linux
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:
parent
088b530a07
commit
a2c763e074
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user