diff options
author | Jonas Gorski <jogo@openwrt.org> | 2013-06-21 13:48:48 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2013-06-25 11:48:06 -0400 |
commit | a3d9086bb121a6459c9ed0452e3c58891a504785 (patch) | |
tree | 99f9d81a1781e4a563dd4a20277ec4a99a49668f /arch | |
parent | 6a72015d3c3602dd969e79510486807c481a0e1b (diff) |
MIPS: Flush TLB handlers directly after writing them
When having enabled MIPS_PGD_C0_CONTEXT, trap_init() might call the
generated tlbmiss_handler_setup_pgd before it was committed to memory,
causing boot failures:
trap_init()
|- per_cpu_trap_init()
| |- TLBMISS_HANDLER_SETUP()
| |- tlbmiss_handler_setup_pgd()
|- flush_tlb_handlers()
To avoid this, move flush_tlb_handlers() into build_tlb_refill_handler()
right after they were generated. We can do this as the cache handling is
initialized just before creating the tlb handlers.
This issue was introduced in 3d8bfdd0307223de678962f1c1907a7cec549136
("MIPS: Use C0_KScratch (if present) to hold PGD pointer.").
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
Cc: Jayachandran C <jchandra@broadcom.com>
Cc: David Daney <david.daney@cavium.com>
Patchwork: https://patchwork.linux-mips.org/patch/5539/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/kernel/traps.c | 2 | ||||
-rw-r--r-- | arch/mips/mm/tlbex.c | 30 |
2 files changed, 16 insertions, 16 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index a75ae40184aa..8ef484c6b9d8 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -1627,7 +1627,6 @@ void *set_vi_handler(int n, vi_handler_t addr) | |||
1627 | } | 1627 | } |
1628 | 1628 | ||
1629 | extern void tlb_init(void); | 1629 | extern void tlb_init(void); |
1630 | extern void flush_tlb_handlers(void); | ||
1631 | 1630 | ||
1632 | /* | 1631 | /* |
1633 | * Timer interrupt | 1632 | * Timer interrupt |
@@ -1956,7 +1955,6 @@ void __init trap_init(void) | |||
1956 | set_handler(0x080, &except_vec3_generic, 0x80); | 1955 | set_handler(0x080, &except_vec3_generic, 0x80); |
1957 | 1956 | ||
1958 | local_flush_icache_range(ebase, ebase + 0x400); | 1957 | local_flush_icache_range(ebase, ebase + 0x400); |
1959 | flush_tlb_handlers(); | ||
1960 | 1958 | ||
1961 | sort_extable(__start___dbe_table, __stop___dbe_table); | 1959 | sort_extable(__start___dbe_table, __stop___dbe_table); |
1962 | 1960 | ||
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index f0f4dc44f394..7f6cd461dac5 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
@@ -2181,6 +2181,20 @@ static void __cpuinit build_r4000_tlb_modify_handler(void) | |||
2181 | dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm)); | 2181 | dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm)); |
2182 | } | 2182 | } |
2183 | 2183 | ||
2184 | static void __cpuinit flush_tlb_handlers(void) | ||
2185 | { | ||
2186 | local_flush_icache_range((unsigned long)handle_tlbl, | ||
2187 | (unsigned long)handle_tlbl + sizeof(handle_tlbl)); | ||
2188 | local_flush_icache_range((unsigned long)handle_tlbs, | ||
2189 | (unsigned long)handle_tlbs + sizeof(handle_tlbs)); | ||
2190 | local_flush_icache_range((unsigned long)handle_tlbm, | ||
2191 | (unsigned long)handle_tlbm + sizeof(handle_tlbm)); | ||
2192 | #ifdef CONFIG_MIPS_PGD_C0_CONTEXT | ||
2193 | local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd_array, | ||
2194 | (unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(handle_tlbm)); | ||
2195 | #endif | ||
2196 | } | ||
2197 | |||
2184 | void __cpuinit build_tlb_refill_handler(void) | 2198 | void __cpuinit build_tlb_refill_handler(void) |
2185 | { | 2199 | { |
2186 | /* | 2200 | /* |
@@ -2213,6 +2227,7 @@ void __cpuinit build_tlb_refill_handler(void) | |||
2213 | build_r3000_tlb_load_handler(); | 2227 | build_r3000_tlb_load_handler(); |
2214 | build_r3000_tlb_store_handler(); | 2228 | build_r3000_tlb_store_handler(); |
2215 | build_r3000_tlb_modify_handler(); | 2229 | build_r3000_tlb_modify_handler(); |
2230 | flush_tlb_handlers(); | ||
2216 | run_once++; | 2231 | run_once++; |
2217 | } | 2232 | } |
2218 | #else | 2233 | #else |
@@ -2240,23 +2255,10 @@ void __cpuinit build_tlb_refill_handler(void) | |||
2240 | build_r4000_tlb_modify_handler(); | 2255 | build_r4000_tlb_modify_handler(); |
2241 | if (!cpu_has_local_ebase) | 2256 | if (!cpu_has_local_ebase) |
2242 | build_r4000_tlb_refill_handler(); | 2257 | build_r4000_tlb_refill_handler(); |
2258 | flush_tlb_handlers(); | ||
2243 | run_once++; | 2259 | run_once++; |
2244 | } | 2260 | } |
2245 | if (cpu_has_local_ebase) | 2261 | if (cpu_has_local_ebase) |
2246 | build_r4000_tlb_refill_handler(); | 2262 | build_r4000_tlb_refill_handler(); |
2247 | } | 2263 | } |
2248 | } | 2264 | } |
2249 | |||
2250 | void __cpuinit flush_tlb_handlers(void) | ||
2251 | { | ||
2252 | local_flush_icache_range((unsigned long)handle_tlbl, | ||
2253 | (unsigned long)handle_tlbl + sizeof(handle_tlbl)); | ||
2254 | local_flush_icache_range((unsigned long)handle_tlbs, | ||
2255 | (unsigned long)handle_tlbs + sizeof(handle_tlbs)); | ||
2256 | local_flush_icache_range((unsigned long)handle_tlbm, | ||
2257 | (unsigned long)handle_tlbm + sizeof(handle_tlbm)); | ||
2258 | #ifdef CONFIG_MIPS_PGD_C0_CONTEXT | ||
2259 | local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd_array, | ||
2260 | (unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(handle_tlbm)); | ||
2261 | #endif | ||
2262 | } | ||