summaryrefslogtreecommitdiff
path: root/arch/mips/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/lib')
-rw-r--r--arch/mips/lib/Makefile3
-rw-r--r--arch/mips/lib/asm-offsets.c61
-rw-r--r--arch/mips/lib/bootm.c4
-rw-r--r--arch/mips/lib/genex.S224
-rw-r--r--arch/mips/lib/stack.c19
-rw-r--r--arch/mips/lib/traps.c106
6 files changed, 414 insertions, 3 deletions
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index b7ce5df765..659c6ad187 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 0000000000..9ed295ace3
--- /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 0c6a4ab3b3..be877625a8 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)
@@ -253,7 +253,6 @@ static int boot_reloc_fdt(bootm_headers_t *images)
#endif
}
-#ifdef CONFIG_ARCH_FIXUP_FDT
int arch_fixup_fdt(void *blob)
{
#if CONFIG_IS_ENABLED(MIPS_BOOT_FDT) && CONFIG_IS_ENABLED(OF_LIBFDT)
@@ -265,7 +264,6 @@ int arch_fixup_fdt(void *blob)
return 0;
#endif
}
-#endif
static int boot_setup_fdt(bootm_headers_t *images)
{
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/stack.c b/arch/mips/lib/stack.c
new file mode 100644
index 0000000000..c80f5fe146
--- /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 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();
+}