diff options
| -rw-r--r-- | arch/mips/include/asm/pgtable-bits.h | 104 | ||||
| -rw-r--r-- | arch/mips/mm/tlbex.c | 68 |
2 files changed, 124 insertions, 48 deletions
diff --git a/arch/mips/include/asm/pgtable-bits.h b/arch/mips/include/asm/pgtable-bits.h index da4ba49adcf6..f8b8fb358412 100644 --- a/arch/mips/include/asm/pgtable-bits.h +++ b/arch/mips/include/asm/pgtable-bits.h | |||
| @@ -34,38 +34,72 @@ | |||
| 34 | */ | 34 | */ |
| 35 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) | 35 | #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) |
| 36 | 36 | ||
| 37 | #define _PAGE_PRESENT (1<<6) /* implemented in software */ | 37 | /* |
| 38 | #define _PAGE_READ (1<<7) /* implemented in software */ | 38 | * The following bits are directly used by the TLB hardware |
| 39 | #define _PAGE_WRITE (1<<8) /* implemented in software */ | 39 | */ |
| 40 | #define _PAGE_ACCESSED (1<<9) /* implemented in software */ | 40 | #define _PAGE_R4KBUG (1 << 0) /* workaround for r4k bug */ |
| 41 | #define _PAGE_MODIFIED (1<<10) /* implemented in software */ | 41 | #define _PAGE_GLOBAL (1 << 0) |
| 42 | #define _PAGE_FILE (1<<10) /* set:pagecache unset:swap */ | 42 | #define _PAGE_VALID_SHIFT 1 |
| 43 | 43 | #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) | |
| 44 | #define _PAGE_R4KBUG (1<<0) /* workaround for r4k bug */ | 44 | #define _PAGE_SILENT_READ (1 << 1) /* synonym */ |
| 45 | #define _PAGE_GLOBAL (1<<0) | 45 | #define _PAGE_DIRTY_SHIFT 2 |
| 46 | #define _PAGE_VALID (1<<1) | 46 | #define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) /* The MIPS dirty bit */ |
| 47 | #define _PAGE_SILENT_READ (1<<1) /* synonym */ | 47 | #define _PAGE_SILENT_WRITE (1 << 2) |
| 48 | #define _PAGE_DIRTY (1<<2) /* The MIPS dirty bit */ | 48 | #define _CACHE_SHIFT 3 |
| 49 | #define _PAGE_SILENT_WRITE (1<<2) | 49 | #define _CACHE_MASK (7 << 3) |
| 50 | #define _CACHE_SHIFT 3 | 50 | |
| 51 | #define _CACHE_MASK (7<<3) | 51 | /* |
| 52 | * The following bits are implemented in software | ||
| 53 | * | ||
| 54 | * _PAGE_FILE semantics: set:pagecache unset:swap | ||
| 55 | */ | ||
| 56 | #define _PAGE_PRESENT_SHIFT 6 | ||
| 57 | #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) | ||
| 58 | #define _PAGE_READ_SHIFT 7 | ||
| 59 | #define _PAGE_READ (1 << _PAGE_READ_SHIFT) | ||
| 60 | #define _PAGE_WRITE_SHIFT 8 | ||
| 61 | #define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) | ||
| 62 | #define _PAGE_ACCESSED_SHIFT 9 | ||
| 63 | #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) | ||
| 64 | #define _PAGE_MODIFIED_SHIFT 10 | ||
| 65 | #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) | ||
| 66 | |||
| 67 | #define _PAGE_FILE (1 << 10) | ||
| 52 | 68 | ||
| 53 | #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) | 69 | #elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) |
| 54 | 70 | ||
| 55 | #define _PAGE_PRESENT (1<<0) /* implemented in software */ | 71 | /* |
| 56 | #define _PAGE_READ (1<<1) /* implemented in software */ | 72 | * The following are implemented by software |
| 57 | #define _PAGE_WRITE (1<<2) /* implemented in software */ | 73 | * |
| 58 | #define _PAGE_ACCESSED (1<<3) /* implemented in software */ | 74 | * _PAGE_FILE semantics: set:pagecache unset:swap |
| 59 | #define _PAGE_MODIFIED (1<<4) /* implemented in software */ | 75 | */ |
| 60 | #define _PAGE_FILE (1<<4) /* set:pagecache unset:swap */ | 76 | #define _PAGE_PRESENT_SHIFT 0 |
| 61 | 77 | #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) | |
| 62 | #define _PAGE_GLOBAL (1<<8) | 78 | #define _PAGE_READ_SHIFT 1 |
| 63 | #define _PAGE_VALID (1<<9) | 79 | #define _PAGE_READ (1 << _PAGE_READ_SHIFT) |
| 64 | #define _PAGE_SILENT_READ (1<<9) /* synonym */ | 80 | #define _PAGE_WRITE_SHIFT 2 |
| 65 | #define _PAGE_DIRTY (1<<10) /* The MIPS dirty bit */ | 81 | #define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) |
| 66 | #define _PAGE_SILENT_WRITE (1<<10) | 82 | #define _PAGE_ACCESSED_SHIFT 3 |
| 67 | #define _CACHE_UNCACHED (1<<11) | 83 | #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) |
| 68 | #define _CACHE_MASK (1<<11) | 84 | #define _PAGE_MODIFIED_SHIFT 4 |
| 85 | #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) | ||
| 86 | #define _PAGE_FILE_SHIFT 4 | ||
| 87 | #define _PAGE_FILE (1 << _PAGE_FILE_SHIFT) | ||
| 88 | |||
| 89 | /* | ||
| 90 | * And these are the hardware TLB bits | ||
| 91 | */ | ||
| 92 | #define _PAGE_GLOBAL_SHIFT 8 | ||
| 93 | #define _PAGE_GLOBAL (1 << _PAGE_GLOBAL_SHIFT) | ||
| 94 | #define _PAGE_VALID_SHIFT 9 | ||
| 95 | #define _PAGE_VALID (1 << _PAGE_VALID_SHIFT) | ||
| 96 | #define _PAGE_SILENT_READ (1 << _PAGE_VALID_SHIFT) /* synonym */ | ||
| 97 | #define _PAGE_DIRTY_SHIFT 10 | ||
| 98 | #define _PAGE_DIRTY (1 << _PAGE_DIRTY_SHIFT) | ||
| 99 | #define _PAGE_SILENT_WRITE (1 << _PAGE_DIRTY_SHIFT) | ||
| 100 | #define _CACHE_UNCACHED_SHIFT 11 | ||
| 101 | #define _CACHE_UNCACHED (1 << _CACHE_UNCACHED_SHIFT) | ||
| 102 | #define _CACHE_MASK (1 << _CACHE_UNCACHED_SHIFT) | ||
| 69 | 103 | ||
| 70 | #else /* 'Normal' r4K case */ | 104 | #else /* 'Normal' r4K case */ |
| 71 | /* | 105 | /* |
| @@ -76,22 +110,22 @@ | |||
| 76 | * which is more than we need right now. | 110 | * which is more than we need right now. |
| 77 | */ | 111 | */ |
| 78 | 112 | ||
| 79 | /* implemented in software */ | 113 | /* |
| 114 | * The following bits are implemented in software | ||
| 115 | * | ||
| 116 | * _PAGE_READ / _PAGE_READ_SHIFT should be unused if cpu_has_rixi. | ||
| 117 | * _PAGE_FILE semantics: set:pagecache unset:swap | ||
| 118 | */ | ||
| 80 | #define _PAGE_PRESENT_SHIFT (0) | 119 | #define _PAGE_PRESENT_SHIFT (0) |
| 81 | #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) | 120 | #define _PAGE_PRESENT (1 << _PAGE_PRESENT_SHIFT) |
| 82 | /* implemented in software, should be unused if cpu_has_rixi. */ | ||
| 83 | #define _PAGE_READ_SHIFT (cpu_has_rixi ? _PAGE_PRESENT_SHIFT : _PAGE_PRESENT_SHIFT + 1) | 121 | #define _PAGE_READ_SHIFT (cpu_has_rixi ? _PAGE_PRESENT_SHIFT : _PAGE_PRESENT_SHIFT + 1) |
| 84 | #define _PAGE_READ ({BUG_ON(cpu_has_rixi); 1 << _PAGE_READ_SHIFT; }) | 122 | #define _PAGE_READ ({BUG_ON(cpu_has_rixi); 1 << _PAGE_READ_SHIFT; }) |
| 85 | /* implemented in software */ | ||
| 86 | #define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) | 123 | #define _PAGE_WRITE_SHIFT (_PAGE_READ_SHIFT + 1) |
| 87 | #define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) | 124 | #define _PAGE_WRITE (1 << _PAGE_WRITE_SHIFT) |
| 88 | /* implemented in software */ | ||
| 89 | #define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) | 125 | #define _PAGE_ACCESSED_SHIFT (_PAGE_WRITE_SHIFT + 1) |
| 90 | #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) | 126 | #define _PAGE_ACCESSED (1 << _PAGE_ACCESSED_SHIFT) |
| 91 | /* implemented in software */ | ||
| 92 | #define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) | 127 | #define _PAGE_MODIFIED_SHIFT (_PAGE_ACCESSED_SHIFT + 1) |
| 93 | #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) | 128 | #define _PAGE_MODIFIED (1 << _PAGE_MODIFIED_SHIFT) |
| 94 | /* set:pagecache unset:swap */ | ||
| 95 | #define _PAGE_FILE (_PAGE_MODIFIED) | 129 | #define _PAGE_FILE (_PAGE_MODIFIED) |
| 96 | 130 | ||
| 97 | #ifdef CONFIG_HUGETLB_PAGE | 131 | #ifdef CONFIG_HUGETLB_PAGE |
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 9c068acaeaee..a36b4955d4ed 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
| @@ -206,19 +206,58 @@ static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance) | |||
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | /* | 208 | /* |
| 209 | * For debug purposes. | 209 | * pgtable bits are assigned dynamically depending on processor feature |
| 210 | * and statically based on kernel configuration. This spits out the actual | ||
| 211 | * values the kernel is using. Required to make sense from disassembled | ||
| 212 | * TLB exception handlers. | ||
| 210 | */ | 213 | */ |
| 211 | static inline void dump_handler(const u32 *handler, int count) | 214 | static void output_pgtable_bits_defines(void) |
| 215 | { | ||
| 216 | #define pr_define(fmt, ...) \ | ||
| 217 | pr_debug("#define " fmt, ##__VA_ARGS__) | ||
| 218 | |||
| 219 | pr_debug("#include <asm/asm.h>\n"); | ||
| 220 | pr_debug("#include <asm/regdef.h>\n"); | ||
| 221 | pr_debug("\n"); | ||
| 222 | |||
| 223 | pr_define("_PAGE_PRESENT_SHIFT %d\n", _PAGE_PRESENT_SHIFT); | ||
| 224 | pr_define("_PAGE_READ_SHIFT %d\n", _PAGE_READ_SHIFT); | ||
| 225 | pr_define("_PAGE_WRITE_SHIFT %d\n", _PAGE_WRITE_SHIFT); | ||
| 226 | pr_define("_PAGE_ACCESSED_SHIFT %d\n", _PAGE_ACCESSED_SHIFT); | ||
| 227 | pr_define("_PAGE_MODIFIED_SHIFT %d\n", _PAGE_MODIFIED_SHIFT); | ||
| 228 | #ifdef _PAGE_HUGE_SHIFT | ||
| 229 | pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT); | ||
| 230 | #endif | ||
| 231 | if (cpu_has_rixi) { | ||
| 232 | #ifdef _PAGE_NO_EXEC_SHIFT | ||
| 233 | pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT); | ||
| 234 | #endif | ||
| 235 | #ifdef _PAGE_NO_READ_SHIFT | ||
| 236 | pr_define("_PAGE_NO_READ_SHIFT %d\n", _PAGE_NO_READ_SHIFT); | ||
| 237 | #endif | ||
| 238 | } | ||
| 239 | pr_define("_PAGE_GLOBAL_SHIFT %d\n", _PAGE_GLOBAL_SHIFT); | ||
| 240 | pr_define("_PAGE_VALID_SHIFT %d\n", _PAGE_VALID_SHIFT); | ||
| 241 | pr_define("_PAGE_DIRTY_SHIFT %d\n", _PAGE_DIRTY_SHIFT); | ||
| 242 | pr_define("_PFN_SHIFT %d\n", _PFN_SHIFT); | ||
| 243 | pr_debug("\n"); | ||
| 244 | } | ||
| 245 | |||
| 246 | static inline void dump_handler(const char *symbol, const u32 *handler, int count) | ||
| 212 | { | 247 | { |
| 213 | int i; | 248 | int i; |
| 214 | 249 | ||
| 250 | pr_debug("LEAF(%s)\n", symbol); | ||
| 251 | |||
| 215 | pr_debug("\t.set push\n"); | 252 | pr_debug("\t.set push\n"); |
| 216 | pr_debug("\t.set noreorder\n"); | 253 | pr_debug("\t.set noreorder\n"); |
| 217 | 254 | ||
| 218 | for (i = 0; i < count; i++) | 255 | for (i = 0; i < count; i++) |
| 219 | pr_debug("\t%p\t.word 0x%08x\n", &handler[i], handler[i]); | 256 | pr_debug("\t.word\t0x%08x\t\t# %p\n", handler[i], &handler[i]); |
| 220 | 257 | ||
| 221 | pr_debug("\t.set pop\n"); | 258 | pr_debug("\t.set\tpop\n"); |
| 259 | |||
| 260 | pr_debug("\tEND(%s)\n", symbol); | ||
| 222 | } | 261 | } |
| 223 | 262 | ||
| 224 | /* The only general purpose registers allowed in TLB handlers. */ | 263 | /* The only general purpose registers allowed in TLB handlers. */ |
| @@ -401,7 +440,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void) | |||
| 401 | 440 | ||
| 402 | memcpy((void *)ebase, tlb_handler, 0x80); | 441 | memcpy((void *)ebase, tlb_handler, 0x80); |
| 403 | 442 | ||
| 404 | dump_handler((u32 *)ebase, 32); | 443 | dump_handler("r3000_tlb_refill", (u32 *)ebase, 32); |
| 405 | } | 444 | } |
| 406 | #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ | 445 | #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ |
| 407 | 446 | ||
| @@ -1434,7 +1473,7 @@ static void __cpuinit build_r4000_tlb_refill_handler(void) | |||
| 1434 | 1473 | ||
| 1435 | memcpy((void *)ebase, final_handler, 0x100); | 1474 | memcpy((void *)ebase, final_handler, 0x100); |
| 1436 | 1475 | ||
| 1437 | dump_handler((u32 *)ebase, 64); | 1476 | dump_handler("r4000_tlb_refill", (u32 *)ebase, 64); |
| 1438 | } | 1477 | } |
| 1439 | 1478 | ||
| 1440 | /* | 1479 | /* |
| @@ -1491,7 +1530,8 @@ static void __cpuinit build_r4000_setup_pgd(void) | |||
| 1491 | pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n", | 1530 | pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n", |
| 1492 | (unsigned int)(p - tlbmiss_handler_setup_pgd)); | 1531 | (unsigned int)(p - tlbmiss_handler_setup_pgd)); |
| 1493 | 1532 | ||
| 1494 | dump_handler(tlbmiss_handler_setup_pgd, | 1533 | dump_handler("tlbmiss_handler", |
| 1534 | tlbmiss_handler_setup_pgd, | ||
| 1495 | ARRAY_SIZE(tlbmiss_handler_setup_pgd)); | 1535 | ARRAY_SIZE(tlbmiss_handler_setup_pgd)); |
| 1496 | } | 1536 | } |
| 1497 | #endif | 1537 | #endif |
| @@ -1761,7 +1801,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void) | |||
| 1761 | pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", | 1801 | pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", |
| 1762 | (unsigned int)(p - handle_tlbl)); | 1802 | (unsigned int)(p - handle_tlbl)); |
| 1763 | 1803 | ||
| 1764 | dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); | 1804 | dump_handler("r3000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl)); |
| 1765 | } | 1805 | } |
| 1766 | 1806 | ||
| 1767 | static void __cpuinit build_r3000_tlb_store_handler(void) | 1807 | static void __cpuinit build_r3000_tlb_store_handler(void) |
| @@ -1791,7 +1831,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void) | |||
| 1791 | pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", | 1831 | pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", |
| 1792 | (unsigned int)(p - handle_tlbs)); | 1832 | (unsigned int)(p - handle_tlbs)); |
| 1793 | 1833 | ||
| 1794 | dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); | 1834 | dump_handler("r3000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs)); |
| 1795 | } | 1835 | } |
| 1796 | 1836 | ||
| 1797 | static void __cpuinit build_r3000_tlb_modify_handler(void) | 1837 | static void __cpuinit build_r3000_tlb_modify_handler(void) |
| @@ -1821,7 +1861,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void) | |||
| 1821 | pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", | 1861 | pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", |
| 1822 | (unsigned int)(p - handle_tlbm)); | 1862 | (unsigned int)(p - handle_tlbm)); |
| 1823 | 1863 | ||
| 1824 | dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); | 1864 | dump_handler("r3000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm)); |
| 1825 | } | 1865 | } |
| 1826 | #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ | 1866 | #endif /* CONFIG_MIPS_PGD_C0_CONTEXT */ |
| 1827 | 1867 | ||
| @@ -2028,7 +2068,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void) | |||
| 2028 | pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", | 2068 | pr_debug("Wrote TLB load handler fastpath (%u instructions).\n", |
| 2029 | (unsigned int)(p - handle_tlbl)); | 2069 | (unsigned int)(p - handle_tlbl)); |
| 2030 | 2070 | ||
| 2031 | dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); | 2071 | dump_handler("r4000_tlb_load", handle_tlbl, ARRAY_SIZE(handle_tlbl)); |
| 2032 | } | 2072 | } |
| 2033 | 2073 | ||
| 2034 | static void __cpuinit build_r4000_tlb_store_handler(void) | 2074 | static void __cpuinit build_r4000_tlb_store_handler(void) |
| @@ -2075,7 +2115,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void) | |||
| 2075 | pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", | 2115 | pr_debug("Wrote TLB store handler fastpath (%u instructions).\n", |
| 2076 | (unsigned int)(p - handle_tlbs)); | 2116 | (unsigned int)(p - handle_tlbs)); |
| 2077 | 2117 | ||
| 2078 | dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); | 2118 | dump_handler("r4000_tlb_store", handle_tlbs, ARRAY_SIZE(handle_tlbs)); |
| 2079 | } | 2119 | } |
| 2080 | 2120 | ||
| 2081 | static void __cpuinit build_r4000_tlb_modify_handler(void) | 2121 | static void __cpuinit build_r4000_tlb_modify_handler(void) |
| @@ -2123,7 +2163,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void) | |||
| 2123 | pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", | 2163 | pr_debug("Wrote TLB modify handler fastpath (%u instructions).\n", |
| 2124 | (unsigned int)(p - handle_tlbm)); | 2164 | (unsigned int)(p - handle_tlbm)); |
| 2125 | 2165 | ||
| 2126 | dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); | 2166 | dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm)); |
| 2127 | } | 2167 | } |
| 2128 | 2168 | ||
| 2129 | void __cpuinit build_tlb_refill_handler(void) | 2169 | void __cpuinit build_tlb_refill_handler(void) |
| @@ -2135,6 +2175,8 @@ void __cpuinit build_tlb_refill_handler(void) | |||
| 2135 | */ | 2175 | */ |
| 2136 | static int run_once = 0; | 2176 | static int run_once = 0; |
| 2137 | 2177 | ||
| 2178 | output_pgtable_bits_defines(); | ||
| 2179 | |||
| 2138 | #ifdef CONFIG_64BIT | 2180 | #ifdef CONFIG_64BIT |
| 2139 | check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3); | 2181 | check_for_high_segbits = current_cpu_data.vmbits > (PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3); |
| 2140 | #endif | 2182 | #endif |
