MIPS: tlbex: Better debug output.
authorRalf Baechle <ralf@linux-mips.org>
Tue, 16 Oct 2012 20:20:26 +0000 (22:20 +0200)
committerRalf Baechle <ralf@linux-mips.org>
Mon, 26 Nov 2012 12:41:06 +0000 (13:41 +0100)
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>
arch/mips/include/asm/pgtable-bits.h
arch/mips/mm/tlbex.c

index da4ba49adcf652fb9522c8c0b171f14aa4ab5247..f8b8fb35841247c58ede2dfe3bf4f6fca9e7a311 100644 (file)
  */
 #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 */
 /*
  * 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
index 9c068acaeaee3a6931e9fb86ff565d280a5fe935..a36b4955d4ed840258ba7d526b42bae180b3f8f2 100644 (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