diff mbox

[U-Boot,8/9] MIPS: add handling for generic and EJTAG exceptions

Message ID 20160925180532.19800-9-daniel.schwierzeck@gmail.com
State Superseded
Delegated to: Daniel Schwierzeck
Headers show

Commit Message

Daniel Schwierzeck Sept. 25, 2016, 6:05 p.m. UTC
Add exception handlers for generic and EJTAG exceptions. Most of
the assembly code is imported from Linux kernel and adapted to U-Boot.
The exception vector table will be reserved above the stack before
U-Boot is relocated. The exception handlers will be installed and
activated after relocation in the initr_traps hook function.

Generic exceptions are handled by showing a CPU register dump similar
to Linux kernel. For example:

malta # md 1
00000001:
Ooops:
$ 0   : 00000000 00000000 00000009 00000004
$ 4   : 8ff7e108 00000000 0000003a 00000000
$ 8   : 00000008 00000001 8ff7cd18 00000004
$12   : 00000002 00000000 00000005 0000003a
$16   : 00000004 00000040 00000001 00000001
$20   : 00000000 8fff53c0 00000008 00000004
$24   : ffffffff 8ffdea44
$28   : 90001650 8ff7cd00 00000004 8ffe6818
Hi    : 00000000
Lo    : 00000004
epc   : 8ffe6848 (text bfc28848)
ra    : 8ffe6818 (text bfc28818)
Status: 00000006
Cause : 00000410 (ExcCode 04)
BadVA : 8ff9e928
PrId  : 00019300
 ### ERROR ### Please RESET the board ###

EJTAG exceptions are checked for SDBBP and delegated to the SDBBP handler
if necessary. Otherwise the debug mode will simply be exited. The SDBBP
handler currently prints the contents of registers c0_depc and c0_debug.
This could be extended in the future to handle semi-hosting according to
the MIPS UHI specification.

Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
---

 arch/mips/include/asm/u-boot-mips.h |   4 +
 arch/mips/lib/Makefile              |   2 +
 arch/mips/lib/genex.S               | 214 ++++++++++++++++++++++++++++++++++++
 arch/mips/lib/traps.c               | 104 ++++++++++++++++++
 4 files changed, 324 insertions(+)
 create mode 100644 arch/mips/lib/genex.S
 create mode 100644 arch/mips/lib/traps.c

Comments

Paul Burton Sept. 26, 2016, 10:29 a.m. UTC | #1
On Sunday, 25 September 2016 20:05:31 BST Daniel Schwierzeck wrote:
> Add exception handlers for generic and EJTAG exceptions. Most of
> the assembly code is imported from Linux kernel and adapted to U-Boot.
> The exception vector table will be reserved above the stack before
> U-Boot is relocated. The exception handlers will be installed and
> activated after relocation in the initr_traps hook function.

Hi Daniel,

This series looks good :) Just a couple of comments below.

> 
> Generic exceptions are handled by showing a CPU register dump similar
> to Linux kernel. For example:
> 
> malta # md 1
> 00000001:
> Ooops:
> $ 0   : 00000000 00000000 00000009 00000004
> $ 4   : 8ff7e108 00000000 0000003a 00000000
> $ 8   : 00000008 00000001 8ff7cd18 00000004
> $12   : 00000002 00000000 00000005 0000003a
> $16   : 00000004 00000040 00000001 00000001
> $20   : 00000000 8fff53c0 00000008 00000004
> $24   : ffffffff 8ffdea44
> $28   : 90001650 8ff7cd00 00000004 8ffe6818
> Hi    : 00000000
> Lo    : 00000004
> epc   : 8ffe6848 (text bfc28848)
> ra    : 8ffe6818 (text bfc28818)
> Status: 00000006
> Cause : 00000410 (ExcCode 04)
> BadVA : 8ff9e928
> PrId  : 00019300
>  ### ERROR ### Please RESET the board ###

Something I've had in the U-Boot source we use on Boston, Malta & SEAD-3 boards 
internally for a while is the ability to longjmp back to the shell after an exception. It seems 
to work pretty well & generally means exceptions are non-fatal. I'll submit that once this 
goes in.

> 
> EJTAG exceptions are checked for SDBBP and delegated to the SDBBP handler
> if necessary. Otherwise the debug mode will simply be exited. The SDBBP
> handler currently prints the contents of registers c0_depc and c0_debug.
> This could be extended in the future to handle semi-hosting according to
> the MIPS UHI specification.
> 
> Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
> ---
> 
>  arch/mips/include/asm/u-boot-mips.h |   4 +
>  arch/mips/lib/Makefile              |   2 +
>  arch/mips/lib/genex.S               | 214
> ++++++++++++++++++++++++++++++++++++ arch/mips/lib/traps.c               |
> 104 ++++++++++++++++++
>  4 files changed, 324 insertions(+)
>  create mode 100644 arch/mips/lib/genex.S
>  create mode 100644 arch/mips/lib/traps.c
> 
> diff --git a/arch/mips/include/asm/u-boot-mips.h
> b/arch/mips/include/asm/u-boot-mips.h index 1f527bb..71ff41d 100644
> --- a/arch/mips/include/asm/u-boot-mips.h
> +++ b/arch/mips/include/asm/u-boot-mips.h
> @@ -5,4 +5,8 @@
>  #ifndef _U_BOOT_MIPS_H_
>  #define _U_BOOT_MIPS_H_
> 
> +void exc_handler(void);
> +void except_vec3_generic(void);
> +void except_vec_ejtag_debug(void);
> +
>  #endif /* _U_BOOT_MIPS_H_ */
> diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
> index 02607f7..659c6ad 100644
> --- a/arch/mips/lib/Makefile
> +++ b/arch/mips/lib/Makefile
> @@ -7,7 +7,9 @@
> 
>  obj-y	+= cache.o
>  obj-y	+= cache_init.o
> +obj-y	+= genex.o
>  obj-y	+= stack.o
> +obj-y	+= traps.o
> 
>  obj-$(CONFIG_CMD_BOOTM) += bootm.o
> 
> diff --git a/arch/mips/lib/genex.S b/arch/mips/lib/genex.S
> new file mode 100644
> index 0000000..f72545d
> --- /dev/null
> +++ b/arch/mips/lib/genex.S
> @@ -0,0 +1,214 @@
> +/*
> + * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle
> + * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
> + * Copyright (C) 2002, 2007  Maciej W. Rozycki
> + * Copyright (C) 2001, 2012 MIPS Technologies, Inc.  All rights reserved.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <asm/asm.h>
> +#include <asm/regdef.h>
> +#include <asm/mipsregs.h>
> +#include <asm/asm-offsets.h>
> +
> +	.set	noreorder
> +
> +	/*
> +	 * Macros copied and adapted from Linux MIPS
> +	 */
> +	.macro	SAVE_AT
> +	.set	push
> +	.set	noat
> +	LONG_S	$1, PT_R1(sp)
> +	.set	pop
> +	.endm
> +
> +	.macro	RESTORE_AT
> +	.set	push
> +	.set	noat
> +	LONG_L	$1,  PT_R1(sp)
> +	.set	pop
> +	.endm
> +
> +	.macro	SAVE_TEMP
> +	mfhi	v1
> +#ifdef CONFIG_32BIT
> +	LONG_S	$8, PT_R8(sp)
> +	LONG_S	$9, PT_R9(sp)
> +#endif
> +	LONG_S	$10, PT_R10(sp)
> +	LONG_S	$11, PT_R11(sp)
Daniel Schwierzeck Sept. 26, 2016, 5:41 p.m. UTC | #2
2016-09-26 12:29 GMT+02:00 Paul Burton <paul.burton@imgtec.com>:
>
>
> Something I've had in the U-Boot source we use on Boston, Malta & SEAD-3
> boards internally for a while is the ability to longjmp back to the shell
> after an exception. It seems to work pretty well & generally means
> exceptions are non-fatal. I'll submit that once this goes in.

But this only works for commands issues at the U-Boot prompt? If the
init code crashes,
then you have no valid code to jump to.

>
>> +
>
>> + .macro RESTORE_TEMP
>
>> + LONG_L $24, PT_LO(sp)
>
>> + mtlo $24
>
>> + LONG_L $24, PT_HI(sp)
>
>> + mthi $24
>
>
>
> The hi & lo bits here & in the save code above need to be wrapped in "#if
> __mips_isa_rev < 6", since the hi & lo registers were removed in MIPSr6.
>

ok, I'll do a resync with Linux's arch/mips/include/asm/stackframe.h.


>
>> +void trap_init(ulong reloc_addr)
>
>> +{
>
>> + unsigned long ebase = gd->irq_sp;
>
>> +
>
>> + set_handler(0x180, &except_vec3_generic, 0x80);
>
>> + set_handler(0x280, &except_vec_ejtag_debug, 0x80);
>
>> +
>
>> + write_c0_ebase(ebase);
>
>> + clear_c0_status(ST0_BEV);
>
>
>
> I think strictly speaking we should probably have an ehb instruction at the
> end of trap_init so that we know the new ebase takes effect straight away.

Sounds plausible. Shall I import arch/mips/include/asm/hazards.h from Linux?

>
>
>
> With the R6 change mentioned above this works fine on a 64r6el (I6400)
> Boston board, so feel free to add:
>
>
>
> Reviewed-by: Paul Burton <paul.burton@imgtec.com>
>
> Tested-by: Paul Burton <paul.burton@imgtec.com>
>

thanks for testing and reviewing
Paul Burton Sept. 26, 2016, 6:15 p.m. UTC | #3
On Monday, 26 September 2016 19:41:22 BST Daniel Schwierzeck wrote:
> 2016-09-26 12:29 GMT+02:00 Paul Burton <paul.burton@imgtec.com>:
> > Something I've had in the U-Boot source we use on Boston, Malta & SEAD-3
> > boards internally for a while is the ability to longjmp back to the shell
> > after an exception. It seems to work pretty well & generally means
> > exceptions are non-fatal. I'll submit that once this goes in.
> 
> But this only works for commands issues at the U-Boot prompt? If the
> init code crashes,
> then you have no valid code to jump to.

Hi Daniel,

Yes, that's true. To end users though that's the typical case - when an 
exception occurs it's generally because an address was typed incorrectly or 
because the wrong size of access was used. Allowing the user to recover from 
that by returning them to the prompt where they can simply push the up key & 
modify the command they typed makes use much nicer.

> 
> >> +
> >> 
> >> + .macro RESTORE_TEMP
> >> 
> >> + LONG_L $24, PT_LO(sp)
> >> 
> >> + mtlo $24
> >> 
> >> + LONG_L $24, PT_HI(sp)
> >> 
> >> + mthi $24
> > 
> > The hi & lo bits here & in the save code above need to be wrapped in "#if
> > __mips_isa_rev < 6", since the hi & lo registers were removed in MIPSr6.
> 
> ok, I'll do a resync with Linux's arch/mips/include/asm/stackframe.h.

Sounds good :)

> 
> >> +void trap_init(ulong reloc_addr)
> >> 
> >> +{
> >> 
> >> + unsigned long ebase = gd->irq_sp;
> >> 
> >> +
> >> 
> >> + set_handler(0x180, &except_vec3_generic, 0x80);
> >> 
> >> + set_handler(0x280, &except_vec_ejtag_debug, 0x80);
> >> 
> >> +
> >> 
> >> + write_c0_ebase(ebase);
> >> 
> >> + clear_c0_status(ST0_BEV);
> > 
> > I think strictly speaking we should probably have an ehb instruction at
> > the
> > end of trap_init so that we know the new ebase takes effect straight away.
> 
> Sounds plausible. Shall I import arch/mips/include/asm/hazards.h from Linux?

Could be good. I have a patch lying around which adds hazards.h to clear the 
instruction hazard at the end of flush_cache, but it doesn't reuse the 
instruction_hazard function from Linux because that caused problems when run 
during relocation. I expect since my change to relocate_code that ought not to 
be a problem anymore though & the Linux version will probably work fine, but I 
haven't yet tested it.

> > With the R6 change mentioned above this works fine on a 64r6el (I6400)
> > Boston board, so feel free to add:
> > 
> > 
> > 
> > Reviewed-by: Paul Burton <paul.burton@imgtec.com>
> > 
> > Tested-by: Paul Burton <paul.burton@imgtec.com>
> 
> thanks for testing and reviewing

No problem.

Thanks,
    Paul
diff mbox

Patch

diff --git a/arch/mips/include/asm/u-boot-mips.h b/arch/mips/include/asm/u-boot-mips.h
index 1f527bb..71ff41d 100644
--- a/arch/mips/include/asm/u-boot-mips.h
+++ b/arch/mips/include/asm/u-boot-mips.h
@@ -5,4 +5,8 @@ 
 #ifndef _U_BOOT_MIPS_H_
 #define _U_BOOT_MIPS_H_
 
+void exc_handler(void);
+void except_vec3_generic(void);
+void except_vec_ejtag_debug(void);
+
 #endif /* _U_BOOT_MIPS_H_ */
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 02607f7..659c6ad 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -7,7 +7,9 @@ 
 
 obj-y	+= cache.o
 obj-y	+= cache_init.o
+obj-y	+= genex.o
 obj-y	+= stack.o
+obj-y	+= traps.o
 
 obj-$(CONFIG_CMD_BOOTM) += bootm.o
 
diff --git a/arch/mips/lib/genex.S b/arch/mips/lib/genex.S
new file mode 100644
index 0000000..f72545d
--- /dev/null
+++ b/arch/mips/lib/genex.S
@@ -0,0 +1,214 @@ 
+/*
+ * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2002, 2007  Maciej W. Rozycki
+ * Copyright (C) 2001, 2012 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/asm-offsets.h>
+
+	.set	noreorder
+
+	/*
+	 * Macros copied and adapted from Linux MIPS
+	 */
+	.macro	SAVE_AT
+	.set	push
+	.set	noat
+	LONG_S	$1, PT_R1(sp)
+	.set	pop
+	.endm
+
+	.macro	RESTORE_AT
+	.set	push
+	.set	noat
+	LONG_L	$1,  PT_R1(sp)
+	.set	pop
+	.endm
+
+	.macro	SAVE_TEMP
+	mfhi	v1
+#ifdef CONFIG_32BIT
+	LONG_S	$8, PT_R8(sp)
+	LONG_S	$9, PT_R9(sp)
+#endif
+	LONG_S	$10, PT_R10(sp)
+	LONG_S	$11, PT_R11(sp)
+	LONG_S	$12, PT_R12(sp)
+	LONG_S	v1, PT_HI(sp)
+	mflo	v1
+	LONG_S	$13, PT_R13(sp)
+	LONG_S	$14, PT_R14(sp)
+	LONG_S	$15, PT_R15(sp)
+	LONG_S	$24, PT_R24(sp)
+
+	LONG_S	v1, PT_LO(sp)
+	.endm
+
+	.macro	RESTORE_TEMP
+	LONG_L	$24, PT_LO(sp)
+	mtlo	$24
+	LONG_L	$24, PT_HI(sp)
+	mthi	$24
+#ifdef CONFIG_32BIT
+	LONG_L	$8, PT_R8(sp)
+	LONG_L	$9, PT_R9(sp)
+#endif
+	LONG_L	$10, PT_R10(sp)
+	LONG_L	$11, PT_R11(sp)
+	LONG_L	$12, PT_R12(sp)
+	LONG_L	$13, PT_R13(sp)
+	LONG_L	$14, PT_R14(sp)
+	LONG_L	$15, PT_R15(sp)
+	LONG_L	$24, PT_R24(sp)
+	.endm
+
+	.macro	SAVE_STATIC
+	LONG_S	$16, PT_R16(sp)
+	LONG_S	$17, PT_R17(sp)
+	LONG_S	$18, PT_R18(sp)
+	LONG_S	$19, PT_R19(sp)
+	LONG_S	$20, PT_R20(sp)
+	LONG_S	$21, PT_R21(sp)
+	LONG_S	$22, PT_R22(sp)
+	LONG_S	$23, PT_R23(sp)
+	LONG_S	$30, PT_R30(sp)
+	.endm
+
+	.macro	RESTORE_STATIC
+	LONG_L	$16, PT_R16(sp)
+	LONG_L	$17, PT_R17(sp)
+	LONG_L	$18, PT_R18(sp)
+	LONG_L	$19, PT_R19(sp)
+	LONG_L	$20, PT_R20(sp)
+	LONG_L	$21, PT_R21(sp)
+	LONG_L	$22, PT_R22(sp)
+	LONG_L	$23, PT_R23(sp)
+	LONG_L	$30, PT_R30(sp)
+	.endm
+
+	.macro	SAVE_SOME
+	.set	push
+	.set	noat
+	PTR_SUBU k1, sp, PT_SIZE
+	LONG_S	sp, PT_R29(k1)
+	move	sp, k1
+
+	LONG_S	$3, PT_R3(sp)
+	LONG_S	$0, PT_R0(sp)
+	MFC0	v1, CP0_STATUS
+	LONG_S	$2, PT_R2(sp)
+	LONG_S	v1, PT_STATUS(sp)
+	LONG_S	$4, PT_R4(sp)
+	MFC0	v1, CP0_CAUSE
+	LONG_S	$5, PT_R5(sp)
+	LONG_S	v1, PT_CAUSE(sp)
+	LONG_S	$6, PT_R6(sp)
+	MFC0	v1, CP0_EPC
+	LONG_S	$7, PT_R7(sp)
+#ifdef CONFIG_64BIT
+	LONG_S	$8, PT_R8(sp)
+	LONG_S	$9, PT_R9(sp)
+#endif
+	LONG_S	v1, PT_EPC(sp)
+	LONG_S	$25, PT_R25(sp)
+	LONG_S	$28, PT_R28(sp)
+	LONG_S	$31, PT_R31(sp)
+	.set	pop
+	.endm
+
+	.macro	RESTORE_SOME
+	.set	push
+	.set	noat
+	MFC0	a0, CP0_STATUS
+	ori	a0, 0x1f
+	xori	a0, 0x1f
+	MTC0	a0, CP0_STATUS
+	li	v1, 0xff00
+	and	a0, v1
+	LONG_L	v0, PT_STATUS(sp)
+	nor	v1, $0, v1
+	and	v0, v1
+	or	v0, a0
+	MTC0	v0, CP0_STATUS
+	LONG_L	v1, PT_EPC(sp)
+	MTC0	v1, CP0_EPC
+	LONG_L	$31, PT_R31(sp)
+	LONG_L	$28, PT_R28(sp)
+	LONG_L	$25, PT_R25(sp)
+#ifdef CONFIG_64BIT
+	LONG_L	$8, PT_R8(sp)
+	LONG_L	$9, PT_R9(sp)
+#endif
+	LONG_L	$7,  PT_R7(sp)
+	LONG_L	$6,  PT_R6(sp)
+	LONG_L	$5,  PT_R5(sp)
+	LONG_L	$4,  PT_R4(sp)
+	LONG_L	$3,  PT_R3(sp)
+	LONG_L	$2,  PT_R2(sp)
+	.set	pop
+	.endm
+
+	.macro	RESTORE_SP
+	LONG_L	sp, PT_R29(sp)
+	.endm
+
+NESTED(except_vec3_generic, 0, sp)
+	PTR_LA	k1, handle_reserved
+	jr	k1
+	 nop
+	END(except_vec3_generic)
+
+NESTED(except_vec_ejtag_debug, 0, sp)
+	PTR_LA	k1, handle_ejtag_debug
+	jr	k1
+	 nop
+	END(except_vec_ejtag_debug)
+
+NESTED(handle_reserved, PT_SIZE, sp)
+	SAVE_SOME
+	SAVE_AT
+	SAVE_TEMP
+	SAVE_STATIC
+
+	PTR_LA	t9, do_reserved
+	jr	t9
+	 move	a0, sp
+	END(handle_reserved)
+
+NESTED(handle_ejtag_debug, PT_SIZE, sp)
+	.set	push
+	.set	noat
+	MTC0	k1, CP0_DESAVE
+
+	/* Check for SDBBP */
+	MFC0	k1, CP0_DEBUG
+	sll	k1, k1, 30
+	bgez	k1, ejtag_return
+	 nop
+
+	SAVE_SOME
+	SAVE_AT
+	SAVE_TEMP
+	SAVE_STATIC
+
+	PTR_LA	t9, do_ejtag_debug
+	jalr	t9
+	 move	a0, sp
+
+	RESTORE_TEMP
+	RESTORE_STATIC
+	RESTORE_AT
+	RESTORE_SOME
+	RESTORE_SP
+
+ejtag_return:
+	MFC0	k1, CP0_DESAVE
+	deret
+	.set pop
+	END(handle_ejtag_debug)
diff --git a/arch/mips/lib/traps.c b/arch/mips/lib/traps.c
new file mode 100644
index 0000000..518b3ef
--- /dev/null
+++ b/arch/mips/lib/traps.c
@@ -0,0 +1,104 @@ 
+/*
+ * Copyright (C) 1994 - 1999, 2000, 01, 06 Ralf Baechle
+ * Copyright (C) 1995, 1996 Paul M. Antoine
+ * Copyright (C) 1998 Ulf Carlsson
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2002, 2003, 2004, 2005, 2007  Maciej W. Rozycki
+ * Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 2014, Imagination Technologies Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void show_regs(const struct pt_regs *regs)
+{
+	const int field = 2 * sizeof(unsigned long);
+	unsigned int cause = regs->cp0_cause;
+	unsigned int exccode;
+	int i;
+
+	/*
+	 * Saved main processor registers
+	 */
+	for (i = 0; i < 32; ) {
+		if ((i % 4) == 0)
+			printf("$%2d   :", i);
+		if (i == 0)
+			printf(" %0*lx", field, 0UL);
+		else if (i == 26 || i == 27)
+			printf(" %*s", field, "");
+		else
+			printf(" %0*lx", field, regs->regs[i]);
+
+		i++;
+		if ((i % 4) == 0)
+			puts("\n");
+	}
+
+	printf("Hi    : %0*lx\n", field, regs->hi);
+	printf("Lo    : %0*lx\n", field, regs->lo);
+
+	/*
+	 * Saved cp0 registers
+	 */
+	printf("epc   : %0*lx (text %0*lx)\n", field, regs->cp0_epc,
+	       field, regs->cp0_epc - gd->reloc_off);
+	printf("ra    : %0*lx (text %0*lx)\n", field, regs->regs[31],
+	       field, regs->regs[31] - gd->reloc_off);
+
+	printf("Status: %08x\n", (uint32_t) regs->cp0_status);
+
+	exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE;
+	printf("Cause : %08x (ExcCode %02x)\n", cause, exccode);
+
+	if (1 <= exccode && exccode <= 5)
+		printf("BadVA : %0*lx\n", field, regs->cp0_badvaddr);
+
+	printf("PrId  : %08x\n", read_c0_prid());
+}
+
+void do_reserved(const struct pt_regs *regs)
+{
+	puts("\nOoops:\n");
+	show_regs(regs);
+	hang();
+}
+
+void do_ejtag_debug(const struct pt_regs *regs)
+{
+	const int field = 2 * sizeof(unsigned long);
+	unsigned long depc;
+	unsigned int debug;
+
+	depc = read_c0_depc();
+	debug = read_c0_debug();
+
+	printf("SDBBP EJTAG debug exception: c0_depc = %0*lx, DEBUG = %08x\n",
+	       field, depc, debug);
+}
+
+static void set_handler(unsigned long offset, void *addr, unsigned long size)
+{
+	unsigned long ebase = gd->irq_sp;
+
+	memcpy((void *)(ebase + offset), addr, size);
+	flush_cache(ebase + offset, size);
+}
+
+void trap_init(ulong reloc_addr)
+{
+	unsigned long ebase = gd->irq_sp;
+
+	set_handler(0x180, &except_vec3_generic, 0x80);
+	set_handler(0x280, &except_vec_ejtag_debug, 0x80);
+
+	write_c0_ebase(ebase);
+	clear_c0_status(ST0_BEV);
+}