summaryrefslogtreecommitdiffstats
path: root/arch/mips/lib
diff options
context:
space:
mode:
authorAntony Pavlov <antonynpavlov@gmail.com>2015-11-10 10:27:16 +0300
committerSascha Hauer <s.hauer@pengutronix.de>2015-11-11 08:38:24 +0100
commita919cac585e8849b539af2b273eda3d3d27408a6 (patch)
treeca5b97c757a8d294a6f27d60bdc7b53dfdbd6829 /arch/mips/lib
parentf1db81f83899630b182972bf44c7ed1ca2a4f9e5 (diff)
downloadbarebox-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/mips/lib')
-rw-r--r--arch/mips/lib/genex.S6
-rw-r--r--arch/mips/lib/traps.c52
2 files changed, 52 insertions, 6 deletions
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" (&regs));
+
+ /* Unreached */
+
+ } else {
+ printf("\nOoops, %s!\n\n", get_exc_name(cause));
+ show_regs(regs);
+ }
hang();
}