Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2c763e0 authored by Ralf Baechle's avatar Ralf Baechle
Browse files

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
Loading
Loading
Loading
Loading
+69 −35
Original line number Diff line number Diff line
@@ -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                 (1<<1)
#define _PAGE_VALID_SHIFT	1
#define _PAGE_VALID		(1 << _PAGE_VALID_SHIFT)
#define _PAGE_SILENT_READ	(1 << 1)  /* synonym                 */
#define _PAGE_DIRTY                 (1<<2)  /* The MIPS dirty bit      */
#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 */
/*
@@ -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
+55 −13
Original line number Diff line number Diff line
@@ -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