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>
This commit is contained in:
committed by
Ralf Baechle
parent
6a72015d3c
commit
a3d9086bb1
@ -1627,7 +1627,6 @@ void *set_vi_handler(int n, vi_handler_t addr)
|
||||
}
|
||||
|
||||
extern void tlb_init(void);
|
||||
extern void flush_tlb_handlers(void);
|
||||
|
||||
/*
|
||||
* Timer interrupt
|
||||
@ -1956,7 +1955,6 @@ void __init trap_init(void)
|
||||
set_handler(0x080, &except_vec3_generic, 0x80);
|
||||
|
||||
local_flush_icache_range(ebase, ebase + 0x400);
|
||||
flush_tlb_handlers();
|
||||
|
||||
sort_extable(__start___dbe_table, __stop___dbe_table);
|
||||
|
||||
|
@ -2181,6 +2181,20 @@ static void __cpuinit build_r4000_tlb_modify_handler(void)
|
||||
dump_handler("r4000_tlb_modify", handle_tlbm, ARRAY_SIZE(handle_tlbm));
|
||||
}
|
||||
|
||||
static void __cpuinit flush_tlb_handlers(void)
|
||||
{
|
||||
local_flush_icache_range((unsigned long)handle_tlbl,
|
||||
(unsigned long)handle_tlbl + sizeof(handle_tlbl));
|
||||
local_flush_icache_range((unsigned long)handle_tlbs,
|
||||
(unsigned long)handle_tlbs + sizeof(handle_tlbs));
|
||||
local_flush_icache_range((unsigned long)handle_tlbm,
|
||||
(unsigned long)handle_tlbm + sizeof(handle_tlbm));
|
||||
#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
|
||||
local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd_array,
|
||||
(unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(handle_tlbm));
|
||||
#endif
|
||||
}
|
||||
|
||||
void __cpuinit build_tlb_refill_handler(void)
|
||||
{
|
||||
/*
|
||||
@ -2213,6 +2227,7 @@ void __cpuinit build_tlb_refill_handler(void)
|
||||
build_r3000_tlb_load_handler();
|
||||
build_r3000_tlb_store_handler();
|
||||
build_r3000_tlb_modify_handler();
|
||||
flush_tlb_handlers();
|
||||
run_once++;
|
||||
}
|
||||
#else
|
||||
@ -2240,23 +2255,10 @@ void __cpuinit build_tlb_refill_handler(void)
|
||||
build_r4000_tlb_modify_handler();
|
||||
if (!cpu_has_local_ebase)
|
||||
build_r4000_tlb_refill_handler();
|
||||
flush_tlb_handlers();
|
||||
run_once++;
|
||||
}
|
||||
if (cpu_has_local_ebase)
|
||||
build_r4000_tlb_refill_handler();
|
||||
}
|
||||
}
|
||||
|
||||
void __cpuinit flush_tlb_handlers(void)
|
||||
{
|
||||
local_flush_icache_range((unsigned long)handle_tlbl,
|
||||
(unsigned long)handle_tlbl + sizeof(handle_tlbl));
|
||||
local_flush_icache_range((unsigned long)handle_tlbs,
|
||||
(unsigned long)handle_tlbs + sizeof(handle_tlbs));
|
||||
local_flush_icache_range((unsigned long)handle_tlbm,
|
||||
(unsigned long)handle_tlbm + sizeof(handle_tlbm));
|
||||
#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
|
||||
local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd_array,
|
||||
(unsigned long)tlbmiss_handler_setup_pgd_array + sizeof(handle_tlbm));
|
||||
#endif
|
||||
}
|
||||
|
Reference in New Issue
Block a user