summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/Kconfig32
-rw-r--r--arch/mips/cpu/start.S173
-rw-r--r--arch/mips/include/asm/asm-offsets.h5
-rw-r--r--arch/mips/include/asm/cache.h2
-rw-r--r--arch/mips/include/asm/io.h2
-rw-r--r--arch/mips/include/asm/mipsregs.h1
-rw-r--r--arch/mips/include/asm/system.h8
-rw-r--r--arch/mips/include/asm/u-boot-mips.h4
-rw-r--r--arch/mips/lib/Makefile3
-rw-r--r--arch/mips/lib/asm-offsets.c61
-rw-r--r--arch/mips/lib/bootm.c2
-rw-r--r--arch/mips/lib/genex.S224
-rw-r--r--arch/mips/lib/stack.c19
-rw-r--r--arch/mips/lib/traps.c106
-rw-r--r--arch/mips/mach-ath79/Kconfig2
-rw-r--r--arch/mips/mach-pic32/Kconfig1
16 files changed, 582 insertions, 63 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 097ad587c1c..d97930e577b 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -20,6 +20,7 @@ config TARGET_QEMU_MIPS
select SUPPORTS_CPU_MIPS32_R2
select SUPPORTS_CPU_MIPS64_R1
select SUPPORTS_CPU_MIPS64_R2
+ select ROM_EXCEPTION_VECTORS
config TARGET_MALTA
bool "Support malta"
@@ -40,6 +41,7 @@ config TARGET_MALTA
select SUPPORTS_CPU_MIPS64_R6
select SWAP_IO_SPACE
select MIPS_L1_CACHE_SHIFT_6
+ select ROM_EXCEPTION_VECTORS
config TARGET_VCT
bool "Support vct"
@@ -47,6 +49,7 @@ config TARGET_VCT
select SUPPORTS_CPU_MIPS32_R1
select SUPPORTS_CPU_MIPS32_R2
select SYS_MIPS_CACHE_INIT_RAM_LOAD
+ select ROM_EXCEPTION_VECTORS
config TARGET_DBAU1X00
bool "Support dbau1x00"
@@ -55,6 +58,7 @@ config TARGET_DBAU1X00
select SUPPORTS_CPU_MIPS32_R1
select SUPPORTS_CPU_MIPS32_R2
select SYS_MIPS_CACHE_INIT_RAM_LOAD
+ select ROM_EXCEPTION_VECTORS
select MIPS_TUNE_4KC
config TARGET_PB1X00
@@ -63,6 +67,7 @@ config TARGET_PB1X00
select SUPPORTS_CPU_MIPS32_R1
select SUPPORTS_CPU_MIPS32_R2
select SYS_MIPS_CACHE_INIT_RAM_LOAD
+ select ROM_EXCEPTION_VECTORS
select MIPS_TUNE_4KC
config ARCH_ATH79
@@ -91,6 +96,7 @@ config TARGET_BOSTON
select SUPPORTS_CPU_MIPS64_R1
select SUPPORTS_CPU_MIPS64_R2
select SUPPORTS_CPU_MIPS64_R6
+ select ROM_EXCEPTION_VECTORS
config TARGET_XILFPGA
bool "Support Imagination Xilfpga"
@@ -103,6 +109,7 @@ config TARGET_XILFPGA
select SUPPORTS_CPU_MIPS32_R1
select SUPPORTS_CPU_MIPS32_R2
select MIPS_L1_CACHE_SHIFT_4
+ select ROM_EXCEPTION_VECTORS
help
This supports IMGTEC MIPSfpga platform
@@ -192,6 +199,20 @@ config CPU_MIPS64_R6
endchoice
+menu "General setup"
+
+config ROM_EXCEPTION_VECTORS
+ bool "Build U-Boot image with exception vectors"
+ help
+ Enable this to include exception vectors in the U-Boot image. This is
+ required if the U-Boot entry point is equal to the address of the
+ CPU reset exception vector (e.g. U-Boot as ROM loader in Qemu,
+ U-Boot booted from parallel NOR flash).
+ Disable this, if the U-Boot image is booted from DRAM (e.g. by SPL).
+ In that case the image size will be reduced by 0x500 bytes.
+
+endmenu
+
menu "OS boot interface"
config MIPS_BOOT_CMDLINE_LEGACY
@@ -281,6 +302,17 @@ config SWAP_IO_SPACE
config SYS_MIPS_CACHE_INIT_RAM_LOAD
bool
+config MIPS_INIT_STACK_IN_SRAM
+ bool
+ default n
+ help
+ Select this if the initial stack frame could be setup in SRAM.
+ Normally the initial stack frame is set up in DRAM which is often
+ only available after lowlevel_init. With this option the initial
+ stack frame and the early C environment is set up before
+ lowlevel_init. Thus lowlevel_init does not need to be implemented
+ in assembler.
+
config SYS_DCACHE_SIZE
int
default 0
diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S
index 3f0fc125475..6740fdf9ed2 100644
--- a/arch/mips/cpu/start.S
+++ b/arch/mips/cpu/start.S
@@ -34,30 +34,57 @@
# define STATUS_SET ST0_KX
#endif
- /*
- * For the moment disable interrupts, mark the kernel mode and
- * set ST0_KX so that the CPU does not spit fire when using
- * 64-bit addresses.
- */
- .macro setup_c0_status set clr
- .set push
- mfc0 t0, CP0_STATUS
- or t0, ST0_CU0 | \set | 0x1f | \clr
- xor t0, 0x1f | \clr
- mtc0 t0, CP0_STATUS
- .set noreorder
- sll zero, 3 # ehb
- .set pop
+ .set noreorder
+
+ .macro init_wr sel
+ MTC0 zero, CP0_WATCHLO,\sel
+ mtc0 t1, CP0_WATCHHI,\sel
+ mfc0 t0, CP0_WATCHHI,\sel
+ bgez t0, wr_done
+ nop
.endm
- .set noreorder
+ .macro uhi_mips_exception
+ move k0, t9 # preserve t9 in k0
+ move k1, a0 # preserve a0 in k1
+ li t9, 15 # UHI exception operation
+ li a0, 0 # Use hard register context
+ sdbbp 1 # Invoke UHI operation
+ .endm
+
+ .macro setup_stack_gd
+ li t0, -16
+ PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR
+ and sp, t1, t0 # force 16 byte alignment
+ PTR_SUBU \
+ sp, sp, GD_SIZE # reserve space for gd
+ and sp, sp, t0 # force 16 byte alignment
+ move k0, sp # save gd pointer
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+ li t2, CONFIG_SYS_MALLOC_F_LEN
+ PTR_SUBU \
+ sp, sp, t2 # reserve space for early malloc
+ and sp, sp, t0 # force 16 byte alignment
+#endif
+ move fp, sp
+
+ /* Clear gd */
+ move t0, k0
+1:
+ PTR_S zero, 0(t0)
+ blt t0, t1, 1b
+ PTR_ADDIU t0, PTRSIZE
+
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+ PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset
+#endif
+ .endm
ENTRY(_start)
/* U-Boot entry point */
b reset
- nop
+ mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing
- .org 0x10
#if defined(CONFIG_SYS_XWAY_EBU_BOOTCFG)
/*
* Almost all Lantiq XWAY SoC devices have an external bus unit (EBU) to
@@ -66,47 +93,53 @@ ENTRY(_start)
* initial configuration for that EBU in order to access the flash
* device with correct parameters. This config option is board-specific.
*/
+ .org 0x10
.word CONFIG_SYS_XWAY_EBU_BOOTCFG
.word 0x0
-#elif defined(CONFIG_MALTA)
+#endif
+#if defined(CONFIG_MALTA)
/*
* Linux expects the Board ID here.
*/
+ .org 0x10
.word 0x00000420 # 0x420 (Malta Board with CoreLV)
.word 0x00000000
#endif
+#if defined(CONFIG_ROM_EXCEPTION_VECTORS)
+ /*
+ * Exception vector entry points. When running from ROM, an exception
+ * cannot be handled. Halt execution and transfer control to debugger,
+ * if one is attached.
+ */
.org 0x200
/* TLB refill, 32 bit task */
-1: b 1b
- nop
+ uhi_mips_exception
.org 0x280
/* XTLB refill, 64 bit task */
-1: b 1b
- nop
+ uhi_mips_exception
.org 0x300
/* Cache error exception */
-1: b 1b
- nop
+ uhi_mips_exception
.org 0x380
/* General exception */
-1: b 1b
- nop
+ uhi_mips_exception
.org 0x400
/* Catch interrupt exceptions */
-1: b 1b
- nop
+ uhi_mips_exception
.org 0x480
/* EJTAG debug exception */
1: b 1b
nop
- .align 4
+ .org 0x500
+#endif
+
reset:
#if __mips_isa_rev >= 6
mfc0 t0, CP0_CONFIG, 5
@@ -128,17 +161,51 @@ reset:
b 3b
nop
- /* Clear watch registers */
-4: MTC0 zero, CP0_WATCHLO
+ /* Init CP0 Status */
+4: mfc0 t0, CP0_STATUS
+ and t0, ST0_IMPL
+ or t0, ST0_BEV | ST0_ERL | STATUS_SET
+ mtc0 t0, CP0_STATUS
+
+ /*
+ * Check whether CP0 Config1 is implemented. If not continue
+ * with legacy Watch register initialization.
+ */
+ mfc0 t0, CP0_CONFIG
+ bgez t0, wr_legacy
+ nop
+
+ /*
+ * Check WR bit in CP0 Config1 to determine if Watch registers
+ * are implemented.
+ */
+ mfc0 t0, CP0_CONFIG, 1
+ andi t0, (1 << 3)
+ beqz t0, wr_done
+ nop
+
+ /* Clear Watch Status bits and disable watch exceptions */
+ li t1, 0x7 # Clear I, R and W conditions
+ init_wr 0
+ init_wr 1
+ init_wr 2
+ init_wr 3
+ init_wr 4
+ init_wr 5
+ init_wr 6
+ init_wr 7
+ b wr_done
+ nop
+
+wr_legacy:
+ MTC0 zero, CP0_WATCHLO
mtc0 zero, CP0_WATCHHI
- /* WP(Watch Pending), SW0/1 should be cleared */
+wr_done:
+ /* Clear WP, IV and SW interrupts */
mtc0 zero, CP0_CAUSE
- setup_c0_status STATUS_SET 0
-
- /* Init Timer */
- mtc0 zero, CP0_COUNT
+ /* Clear timer interrupt (CP0_COUNT cleared on branch to 'reset') */
mtc0 zero, CP0_COMPARE
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
@@ -167,6 +234,11 @@ reset:
nop
#endif
+#ifdef CONFIG_MIPS_INIT_STACK_IN_SRAM
+ /* Set up initial stack and global data */
+ setup_stack_gd
+#endif
+
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
# ifdef CONFIG_SYS_MIPS_CACHE_INIT_RAM_LOAD
/* Initialize any external memory */
@@ -188,35 +260,14 @@ reset:
# endif
#endif
- /* Set up temporary stack */
- li t0, -16
- PTR_LI t1, CONFIG_SYS_INIT_SP_ADDR
- and sp, t1, t0 # force 16 byte alignment
- PTR_SUBU \
- sp, sp, GD_SIZE # reserve space for gd
- and sp, sp, t0 # force 16 byte alignment
- move k0, sp # save gd pointer
-#ifdef CONFIG_SYS_MALLOC_F_LEN
- li t2, CONFIG_SYS_MALLOC_F_LEN
- PTR_SUBU \
- sp, sp, t2 # reserve space for early malloc
- and sp, sp, t0 # force 16 byte alignment
-#endif
- move fp, sp
-
- /* Clear gd */
- move t0, k0
-1:
- PTR_S zero, 0(t0)
- blt t0, t1, 1b
- PTR_ADDIU t0, PTRSIZE
-
-#ifdef CONFIG_SYS_MALLOC_F_LEN
- PTR_S sp, GD_MALLOC_BASE(k0) # gd->malloc_base offset
+#ifndef CONFIG_MIPS_INIT_STACK_IN_SRAM
+ /* Set up initial stack and global data */
+ setup_stack_gd
#endif
move a0, zero # a0 <-- boot_flags = 0
PTR_LA t9, board_init_f
+
jr t9
move ra, zero
diff --git a/arch/mips/include/asm/asm-offsets.h b/arch/mips/include/asm/asm-offsets.h
new file mode 100644
index 00000000000..5352b1cd383
--- /dev/null
+++ b/arch/mips/include/asm/asm-offsets.h
@@ -0,0 +1,5 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <generated/asm-offsets.h>
diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h
index 669c362a52a..83165d5c970 100644
--- a/arch/mips/include/asm/cache.h
+++ b/arch/mips/include/asm/cache.h
@@ -19,6 +19,7 @@
*/
#define CONFIG_SYS_CACHELINE_SIZE ARCH_DMA_MINALIGN
+#ifndef __ASSEMBLY__
/**
* mips_cache_probe() - Probe the properties of the caches
*
@@ -27,5 +28,6 @@
* functions such as flush_cache may be called.
*/
void mips_cache_probe(void);
+#endif
#endif /* __MIPS_CACHE_H__ */
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 5b86386bc1c..ee7a59290de 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -501,7 +501,7 @@ map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
if (flags == MAP_NOCACHE)
return ioremap(paddr, len);
- return (void *)paddr;
+ return (void *)CKSEG0ADDR(paddr);
}
/*
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 9ab506361e7..7a9d222aade 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -299,6 +299,7 @@
#define STATUSF_IP14 (_ULCAST_(1) << 6)
#define STATUSB_IP15 7
#define STATUSF_IP15 (_ULCAST_(1) << 7)
+#define ST0_IMPL (_ULCAST_(3) << 16)
#define ST0_CH 0x00040000
#define ST0_NMI 0x00080000
#define ST0_SR 0x00100000
diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h
index e6435cce294..c9c59614627 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 1f527bb8ec0..71ff41dafec 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 b7ce5df7652..659c6ad187c 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -7,6 +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/asm-offsets.c b/arch/mips/lib/asm-offsets.c
new file mode 100644
index 00000000000..9ed295ace35
--- /dev/null
+++ b/arch/mips/lib/asm-offsets.c
@@ -0,0 +1,61 @@
+/*
+ * offset.c: Calculate pt_regs and task_struct offsets.
+ *
+ * Copyright (C) 1996 David S. Miller
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ *
+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <asm/ptrace.h>
+#include <linux/stddef.h>
+#include <linux/kbuild.h>
+
+void output_ptreg_defines(void)
+{
+ COMMENT("MIPS pt_regs offsets.");
+ OFFSET(PT_R0, pt_regs, regs[0]);
+ OFFSET(PT_R1, pt_regs, regs[1]);
+ OFFSET(PT_R2, pt_regs, regs[2]);
+ OFFSET(PT_R3, pt_regs, regs[3]);
+ OFFSET(PT_R4, pt_regs, regs[4]);
+ OFFSET(PT_R5, pt_regs, regs[5]);
+ OFFSET(PT_R6, pt_regs, regs[6]);
+ OFFSET(PT_R7, pt_regs, regs[7]);
+ OFFSET(PT_R8, pt_regs, regs[8]);
+ OFFSET(PT_R9, pt_regs, regs[9]);
+ OFFSET(PT_R10, pt_regs, regs[10]);
+ OFFSET(PT_R11, pt_regs, regs[11]);
+ OFFSET(PT_R12, pt_regs, regs[12]);
+ OFFSET(PT_R13, pt_regs, regs[13]);
+ OFFSET(PT_R14, pt_regs, regs[14]);
+ OFFSET(PT_R15, pt_regs, regs[15]);
+ OFFSET(PT_R16, pt_regs, regs[16]);
+ OFFSET(PT_R17, pt_regs, regs[17]);
+ OFFSET(PT_R18, pt_regs, regs[18]);
+ OFFSET(PT_R19, pt_regs, regs[19]);
+ OFFSET(PT_R20, pt_regs, regs[20]);
+ OFFSET(PT_R21, pt_regs, regs[21]);
+ OFFSET(PT_R22, pt_regs, regs[22]);
+ OFFSET(PT_R23, pt_regs, regs[23]);
+ OFFSET(PT_R24, pt_regs, regs[24]);
+ OFFSET(PT_R25, pt_regs, regs[25]);
+ OFFSET(PT_R26, pt_regs, regs[26]);
+ OFFSET(PT_R27, pt_regs, regs[27]);
+ OFFSET(PT_R28, pt_regs, regs[28]);
+ OFFSET(PT_R29, pt_regs, regs[29]);
+ OFFSET(PT_R30, pt_regs, regs[30]);
+ OFFSET(PT_R31, pt_regs, regs[31]);
+ OFFSET(PT_LO, pt_regs, lo);
+ OFFSET(PT_HI, pt_regs, hi);
+ OFFSET(PT_EPC, pt_regs, cp0_epc);
+ OFFSET(PT_BVADDR, pt_regs, cp0_badvaddr);
+ OFFSET(PT_STATUS, pt_regs, cp0_status);
+ OFFSET(PT_CAUSE, pt_regs, cp0_cause);
+ DEFINE(PT_SIZE, sizeof(struct pt_regs));
+ BLANK();
+}
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 0c6a4ab3b32..9fec4ad4386 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -42,7 +42,7 @@ void arch_lmb_reserve(struct lmb *lmb)
/* adjust sp by 4K to be safe */
sp -= 4096;
- lmb_reserve(lmb, sp, CONFIG_SYS_SDRAM_BASE + gd->ram_size - sp);
+ lmb_reserve(lmb, sp, gd->ram_top - sp);
}
static void linux_cmdline_init(void)
diff --git a/arch/mips/lib/genex.S b/arch/mips/lib/genex.S
new file mode 100644
index 00000000000..2d6d7b0c18e
--- /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/stack.c b/arch/mips/lib/stack.c
new file mode 100644
index 00000000000..c80f5fe1465
--- /dev/null
+++ b/arch/mips/lib/stack.c
@@ -0,0 +1,19 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int arch_reserve_stacks(void)
+{
+ /* reserve space for exception vector table */
+ gd->start_addr_sp -= 0x500;
+ gd->start_addr_sp &= ~0xFFF;
+ gd->irq_sp = gd->start_addr_sp;
+ debug("Reserving %d Bytes for exception vector at: %08lx\n",
+ 0x500, gd->start_addr_sp);
+
+ return 0;
+}
diff --git a/arch/mips/lib/traps.c b/arch/mips/lib/traps.c
new file mode 100644
index 00000000000..18622c223d6
--- /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();
+}
diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig
index 7d483aa8dce..d982b0f8e69 100644
--- a/arch/mips/mach-ath79/Kconfig
+++ b/arch/mips/mach-ath79/Kconfig
@@ -9,6 +9,7 @@ config SOC_AR933X
select SUPPORTS_BIG_ENDIAN
select SUPPORTS_CPU_MIPS32_R1
select SUPPORTS_CPU_MIPS32_R2
+ select ROM_EXCEPTION_VECTORS
select MIPS_TUNE_24KC
help
This supports QCA/Atheros ar933x family SOCs.
@@ -27,6 +28,7 @@ config SOC_QCA953X
select SUPPORTS_BIG_ENDIAN
select SUPPORTS_CPU_MIPS32_R1
select SUPPORTS_CPU_MIPS32_R2
+ select ROM_EXCEPTION_VECTORS
select MIPS_TUNE_24KC
help
This supports QCA/Atheros qca953x family SOCs.
diff --git a/arch/mips/mach-pic32/Kconfig b/arch/mips/mach-pic32/Kconfig
index 2e38bb7ecaf..8fad4cff912 100644
--- a/arch/mips/mach-pic32/Kconfig
+++ b/arch/mips/mach-pic32/Kconfig
@@ -14,6 +14,7 @@ config SOC_PIC32MZDA
select SUPPORTS_CPU_MIPS32_R2
select MIPS_L1_CACHE_SHIFT_4
select SYS_MIPS_CACHE_INIT_RAM_LOAD
+ select ROM_EXCEPTION_VECTORS
help
This supports Microchip PIC32MZ[DA] family of microcontrollers.