diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/include/asm/system.h | 8 | ||||
-rw-r--r-- | arch/mips/include/asm/u-boot-mips.h | 4 | ||||
-rw-r--r-- | arch/mips/lib/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/lib/genex.S | 224 | ||||
-rw-r--r-- | arch/mips/lib/traps.c | 106 |
5 files changed, 344 insertions, 0 deletions
diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h index e6435cce29..c9c5961462 100644 --- a/arch/mips/include/asm/system.h +++ b/arch/mips/include/asm/system.h @@ -262,4 +262,12 @@ extern void __die_if_kernel(const char *, struct pt_regs *, const char *where, #define die_if_kernel(msg, regs) \ __die_if_kernel(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__) +static inline void execution_hazard_barrier(void) +{ + __asm__ __volatile__( + ".set noreorder\n" + "ehb\n" + ".set reorder"); +} + #endif /* _ASM_SYSTEM_H */ diff --git a/arch/mips/include/asm/u-boot-mips.h b/arch/mips/include/asm/u-boot-mips.h index 1f527bb8ec..71ff41dafe 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 02607f71cc..659c6ad187 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 0000000000..2d6d7b0c18 --- /dev/null +++ b/arch/mips/lib/genex.S @@ -0,0 +1,224 @@ +/* + * 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> + +#define STATMASK 0x1f + + .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 SAVE_TEMP +#if __mips_isa_rev < 6 + mfhi v1 +#endif +#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) +#if __mips_isa_rev < 6 + LONG_S v1, PT_HI(sp) + mflo v1 +#endif + LONG_S $13, PT_R13(sp) + LONG_S $14, PT_R14(sp) + LONG_S $15, PT_R15(sp) + LONG_S $24, PT_R24(sp) +#if __mips_isa_rev < 6 + LONG_S v1, PT_LO(sp) +#endif + .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 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_AT + .set push + .set noat + LONG_L $1, PT_R1(sp) + .set pop + .endm + + .macro RESTORE_TEMP +#if __mips_isa_rev < 6 + LONG_L $24, PT_LO(sp) + mtlo $24 + LONG_L $24, PT_HI(sp) + mthi $24 +#endif +#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 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 RESTORE_SOME + .set push + .set reorder + .set noat + mfc0 a0, CP0_STATUS + ori a0, STATMASK + xori a0, STATMASK + mtc0 a0, CP0_STATUS + li v1, ST0_CU1 | ST0_FR | ST0_IM + 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 0000000000..18622c223d --- /dev/null +++ b/arch/mips/lib/traps.c @@ -0,0 +1,106 @@ +/* + * 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> +#include <asm/system.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); + execution_hazard_barrier(); +} |