diff options
author | Antony Pavlov <antonynpavlov@gmail.com> | 2015-11-10 10:27:16 +0300 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2015-11-11 08:38:24 +0100 |
commit | a919cac585e8849b539af2b273eda3d3d27408a6 (patch) | |
tree | ca5b97c757a8d294a6f27d60bdc7b53dfdbd6829 /arch | |
parent | f1db81f83899630b182972bf44c7ed1ca2a4f9e5 (diff) | |
download | barebox-a919cac585e8849b539af2b273eda3d3d27408a6.tar.gz barebox-a919cac585e8849b539af2b273eda3d3d27408a6.tar.xz |
MIPS: allow user to pass incorrect address to md command
This commit makes it possible to handle exception on
incorrect data access so 'md' command just show 'xxxxxxxx'
instead of crashing the system.
barebox:/ md -l 0xa0000003+4
a0000003: xxxxxxxx ....
Without this commit we will get this
barebox:/ md -l 0xa0000003+4
a0000003:
Ooops, address error on load or ifetch!
...
### ERROR ### Please RESET the board ###
Signed-off-by: Antony Pavlov <antonynpavlov@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/include/asm/barebox.h | 2 | ||||
-rw-r--r-- | arch/mips/lib/genex.S | 6 | ||||
-rw-r--r-- | arch/mips/lib/traps.c | 52 |
3 files changed, 53 insertions, 7 deletions
diff --git a/arch/mips/include/asm/barebox.h b/arch/mips/include/asm/barebox.h index 499b731924..e5b964ca1b 100644 --- a/arch/mips/include/asm/barebox.h +++ b/arch/mips/include/asm/barebox.h @@ -15,6 +15,6 @@ #ifndef _ASM_MIPS_BAREBOX_H_ #define _ASM_MIPS_BAREBOX_H_ -/* nothing special yet */ +#define ARCH_HAS_DATA_ABORT_MASK #endif /* _ASM_MIPS_BAREBOX_H_ */ diff --git a/arch/mips/lib/genex.S b/arch/mips/lib/genex.S index 8941714af9..5fb2223231 100644 --- a/arch/mips/lib/genex.S +++ b/arch/mips/lib/genex.S @@ -31,3 +31,9 @@ NESTED(except_vec3_generic, 0, sp) nop END(except_vec3_generic) .set at + +FEXPORT(ret_from_exception) + .set noat + RESTORE_ALL_AND_RET + nop + .set at diff --git a/arch/mips/lib/traps.c b/arch/mips/lib/traps.c index d69697d099..5fc32fe7e4 100644 --- a/arch/mips/lib/traps.c +++ b/arch/mips/lib/traps.c @@ -1,9 +1,25 @@ #include <common.h> - +#include <abort.h> #include <asm/mipsregs.h> #include <asm/ptrace.h> -void barebox_exc_handler(const struct pt_regs *regs); +static int mips_ignore_data_abort; +static int mips_data_abort_occurred; + +void data_abort_mask(void) +{ + mips_data_abort_occurred = 0; + mips_ignore_data_abort = 1; +} + +int data_abort_unmask(void) +{ + mips_ignore_data_abort = 0; + + return mips_data_abort_occurred != 0; +} + +void barebox_exc_handler(struct pt_regs *regs); /* * Trap codes from OpenBSD trap.h @@ -31,9 +47,14 @@ void barebox_exc_handler(const struct pt_regs *regs); #define CR_EXC_CODE 0x0000007c #define CR_EXC_CODE_SHIFT 2 +static inline u32 get_exc_code(u32 cause) +{ + return (cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT; +} + static char *get_exc_name(u32 cause) { - switch ((cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT) { + switch (get_exc_code(cause)) { case T_INT: return "interrupt pending"; @@ -133,12 +154,31 @@ static void show_regs(const struct pt_regs *regs) printf("Config: %08x\n\n", read_c0_config()); } -void barebox_exc_handler(const struct pt_regs *regs) +void barebox_exc_handler(struct pt_regs *regs) { unsigned int cause = regs->cp0_cause; - printf("\nOoops, %s!\n\n", get_exc_name(cause)); - show_regs(regs); + if (get_exc_code(cause) == T_ADDR_ERR_LD && mips_ignore_data_abort) { + + mips_data_abort_occurred = 1; + + regs->cp0_epc += 4; + + /* + * Don't let your children do this ... + */ + __asm__ __volatile__( + "move\t$29, %0\n\t" + "j\tret_from_exception" + :/* no outputs */ + :"r" (®s)); + + /* Unreached */ + + } else { + printf("\nOoops, %s!\n\n", get_exc_name(cause)); + show_regs(regs); + } hang(); } |