mips: add support to restore exception vector base before booting linux

In U-Boot the exception vector base will be moved to top of memory, to be
used to display register dump when exception occurs.

But some old linux kernel does not honor the base set in CP0_EBASE. A
modified exception vector base will cause kernel crash.

This patch adds an option to enable reset exception vector base to its
previous value, or a user configured value before booting linux kernel.

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
This commit is contained in:
Weijie Gao 2020-04-21 09:28:25 +02:00 committed by Daniel Schwierzeck
parent 56ed625ba2
commit 71059736b8
4 changed files with 54 additions and 0 deletions

View File

@ -287,6 +287,36 @@ config MIPS_RELOCATION_TABLE_SIZE
If unsure, leave at the default value.
config RESTORE_EXCEPTION_VECTOR_BASE
bool "Restore exception vector base before booting linux kernel"
default n
help
In U-Boot the exception vector base will be moved to top of memory,
to be used to display register dump when exception occurs.
But some old linux kernel does not honor the base set in CP0_EBASE.
A modified exception vector base will cause kernel crash.
This option will restore the exception vector base to its previous
value.
If unsure, say N.
config OVERRIDE_EXCEPTION_VECTOR_BASE
bool "Override the exception vector base to be restored"
depends on RESTORE_EXCEPTION_VECTOR_BASE
default n
help
Enable this option if you want to use a different exception vector
base rather than the previously saved one.
config NEW_EXCEPTION_VECTOR_BASE
hex "New exception vector base"
depends on OVERRIDE_EXCEPTION_VECTOR_BASE
range 0x80000000 0xbffff000
default 0x80000000
help
The exception vector base to be restored before booting linux kernel
endmenu
menu "OS boot interface"

View File

@ -9,4 +9,6 @@ void except_vec_ejtag_debug(void);
int arch_misc_init(void);
void trap_restore(void);
#endif /* _U_BOOT_MIPS_H_ */

View File

@ -294,6 +294,9 @@ static void boot_jump_linux(bootm_headers_t *images)
bootstage_report();
#endif
if (CONFIG_IS_ENABLED(RESTORE_EXCEPTION_VECTOR_BASE))
trap_restore();
if (images->ft_len)
kernel(-2, (ulong)images->ft_addr, 0, 0);
else

View File

@ -20,6 +20,8 @@
DECLARE_GLOBAL_DATA_PTR;
static unsigned long saved_ebase;
static void show_regs(const struct pt_regs *regs)
{
const int field = 2 * sizeof(unsigned long);
@ -102,7 +104,24 @@ void trap_init(ulong reloc_addr)
set_handler(0x180, &except_vec3_generic, 0x80);
set_handler(0x280, &except_vec_ejtag_debug, 0x80);
saved_ebase = read_c0_ebase() & 0xfffff000;
write_c0_ebase(ebase);
clear_c0_status(ST0_BEV);
execution_hazard_barrier();
}
void trap_restore(void)
{
set_c0_status(ST0_BEV);
execution_hazard_barrier();
#ifdef CONFIG_OVERRIDE_EXCEPTION_VECTOR_BASE
write_c0_ebase(CONFIG_NEW_EXCEPTION_VECTOR_BASE & 0xfffff000);
#else
write_c0_ebase(saved_ebase);
#endif
clear_c0_status(ST0_BEV);
execution_hazard_barrier();
}