summaryrefslogtreecommitdiffstats
path: root/arch/mips/lib
diff options
context:
space:
mode:
authorAntony Pavlov <antonynpavlov@gmail.com>2012-07-26 02:00:27 +0400
committerSascha Hauer <s.hauer@pengutronix.de>2012-07-27 09:54:13 +0200
commitbd6cc52de53fe260e63ae986bff84cf142690f78 (patch)
tree78c2fe9f959e6ab09e74c25b95b6529cafd92983 /arch/mips/lib
parentbdf8405e34df9eeb75cb71801363509a7ab91536 (diff)
downloadbarebox-bd6cc52de53fe260e63ae986bff84cf142690f78.tar.gz
barebox-bd6cc52de53fe260e63ae986bff84cf142690f78.tar.xz
MIPS: add initial exceptions handling
Checking exception handling: $ make qemu-malta_defconfig $ make ... $ qemu-system-mips -nodefaults -M malta -m 256 \ -nographic -serial stdio -bios ./barebox.bin ... barebox:/ md -l 0x03 Ooops, address error on load or ifetch! EPC = 0xa082783c CP0_STATUS = 0x00000006 CP0_CAUSE = 0x00000410 CP0_CONFIG = 0x80008482 ### 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/Makefile2
-rw-r--r--arch/mips/lib/genex.S31
-rw-r--r--arch/mips/lib/traps.c107
3 files changed, 140 insertions, 0 deletions
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index b99bb71837..a31046b80e 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -5,6 +5,8 @@ obj-y += ashldi3.o
obj-y += ashrdi3.o
obj-y += memory.o
obj-y += cpu-probe.o
+obj-y += traps.o
+obj-y += genex.o
obj-$(CONFIG_CPU_MIPS32) += c-r4k.o
obj-$(CONFIG_CPU_MIPS64) += c-r4k.o
diff --git a/arch/mips/lib/genex.S b/arch/mips/lib/genex.S
new file mode 100644
index 0000000000..d6f65a2ca4
--- /dev/null
+++ b/arch/mips/lib/genex.S
@@ -0,0 +1,31 @@
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+
+ .text
+ .set macro
+ .set noat
+ .set noreorder
+ .align 5
+
+/* Exception vector */
+NESTED(handle_reserved, 0, sp)
+ la k0, barebox_exc_handler
+ jal k0
+ move a0, sp
+ /* will never return here */
+ END(handle_reserved)
+
+/* General exception vector */
+NESTED(except_vec3_generic, 0, sp)
+ .set noat
+ mfc0 k1, CP0_CAUSE
+ la k0, exception_handlers
+ andi k1, k1, 0x7c
+ addu k0, k0, k1
+ lw k0, (k0)
+ nop
+ jr k0
+ nop
+ END(except_vec3_generic)
+ .set at
diff --git a/arch/mips/lib/traps.c b/arch/mips/lib/traps.c
new file mode 100644
index 0000000000..4e167cc9f4
--- /dev/null
+++ b/arch/mips/lib/traps.c
@@ -0,0 +1,107 @@
+#include <common.h>
+
+#include <asm/mipsregs.h>
+
+void barebox_exc_handler(void *regs);
+
+/*
+ * Trap codes from OpenBSD trap.h
+ */
+#define T_INT 0 /* Interrupt pending */
+#define T_TLB_MOD 1 /* TLB modified fault */
+#define T_TLB_LD_MISS 2 /* TLB miss on load or ifetch */
+#define T_TLB_ST_MISS 3 /* TLB miss on a store */
+#define T_ADDR_ERR_LD 4 /* Address error on a load or ifetch */
+#define T_ADDR_ERR_ST 5 /* Address error on a store */
+#define T_BUS_ERR_IFETCH 6 /* Bus error on an ifetch */
+#define T_BUS_ERR_LD_ST 7 /* Bus error on a load or store */
+#define T_SYSCALL 8 /* System call */
+#define T_BREAK 9 /* Breakpoint */
+#define T_RES_INST 10 /* Reserved instruction exception */
+#define T_COP_UNUSABLE 11 /* Coprocessor unusable */
+#define T_OVFLOW 12 /* Arithmetic overflow */
+#define T_TRAP 13 /* Trap instruction */
+#define T_VCEI 14 /* Virtual coherency instruction */
+#define T_FPE 15 /* Floating point exception */
+#define T_IWATCH 16 /* Inst. Watch address reference */
+#define T_DWATCH 23 /* Data Watch address reference */
+#define T_VCED 31 /* Virtual coherency data */
+
+#define CR_EXC_CODE 0x0000007c
+#define CR_EXC_CODE_SHIFT 2
+
+static char *get_exc_name(u32 cause)
+{
+ switch ((cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT) {
+
+ case T_INT:
+ return "interrupt pending";
+
+ case T_TLB_MOD:
+ return "TLB modified";
+
+ case T_TLB_LD_MISS:
+ return "TLB miss on load or ifetch";
+
+ case T_TLB_ST_MISS:
+ return "TLB miss on store";
+
+ case T_ADDR_ERR_LD:
+ return "address error on load or ifetch";
+
+ case T_ADDR_ERR_ST:
+ return "address error on store";
+
+ case T_BUS_ERR_IFETCH:
+ return "bus error on ifetch";
+
+ case T_BUS_ERR_LD_ST:
+ return "bus error on load or store";
+
+ case T_SYSCALL:
+ return "system call";
+
+ case T_BREAK:
+ return "breakpoint";
+
+ case T_RES_INST:
+ return "reserved instruction";
+
+ case T_COP_UNUSABLE:
+ return "coprocessor unusable";
+
+ case T_OVFLOW:
+ return "arithmetic overflow";
+
+ case T_TRAP:
+ return "trap instruction";
+
+ case T_VCEI:
+ return "virtual coherency instruction";
+
+ case T_FPE:
+ return "floating point";
+
+ case T_IWATCH:
+ return "iwatch";
+
+ case T_DWATCH:
+ return "dwatch";
+
+ case T_VCED:
+ return "virtual coherency data";
+ }
+
+ return "unknown exception";
+}
+
+void barebox_exc_handler(void *regs)
+{
+ printf("\nOoops, %s!\n", get_exc_name(read_c0_cause()));
+ printf("EPC = 0x%08x\n", read_c0_epc());
+ printf("CP0_STATUS = 0x%08x\n", read_c0_status());
+ printf("CP0_CAUSE = 0x%08x\n", read_c0_cause());
+ printf("CP0_CONFIG = 0x%08x\n\n", read_c0_config());
+
+ hang();
+}