Skip to content

Commit

Permalink
MIPS: tlbex: Better debug output.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ralf Baechle committed Nov 26, 2012
1 parent 088b530 commit a2c763e
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 48 deletions.
104 changes: 69 additions & 35 deletions arch/mips/include/asm/pgtable-bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

#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 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)

/*
* 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 */

#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)
/*
* 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)

/*
* 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 */
/*
Expand All @@ -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
Expand Down
68 changes: 55 additions & 13 deletions arch/mips/mm/tlbex.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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 */

Expand Down Expand Up @@ -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);
}

/*
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 */

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down

0 comments on commit a2c763e

Please sign in to comment.