aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJonas Gorski <jogo@openwrt.org>2013-06-21 13:48:48 -0400
committerRalf Baechle <ralf@linux-mips.org>2013-06-25 11:48:06 -0400
commita3d9086bb121a6459c9ed0452e3c58891a504785 (patch)
tree99f9d81a1781e4a563dd4a20277ec4a99a49668f /arch
parent6a72015d3c3602dd969e79510486807c481a0e1b (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.c2
-rw-r--r--arch/mips/mm/tlbex.c30
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
1629extern void tlb_init(void); 1629extern void tlb_init(void);
1630extern 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
2184static 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
2184void __cpuinit build_tlb_refill_handler(void) 2198void __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
2250void __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}