From af3971f81ac0fc344461cf86af682ecf1ebe18a8 Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Sun, 14 Feb 2016 18:52:57 +0100 Subject: MIPS: make inclusion of ROM exception vectors configurable This adds a compile time option to include code for static exception vectors. Static exception vectors are only needed, when the U-Boot entry point is equal to the CPU reset exception vector address. For instance this is the case when U-Boot is used as ROM in Qemu or booted from parallel NOR flash. When U-Boot is booted from RAM (e.g. loaded there by SPL), the exception vectors need to be setup dynamically, which is done in follow-up commits. Signed-off-by: Daniel Schwierzeck diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 097ad58..709ac5c 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 diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index 3f0fc12..108d2df 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -57,7 +57,6 @@ ENTRY(_start) b reset nop - .org 0x10 #if defined(CONFIG_SYS_XWAY_EBU_BOOTCFG) /* * Almost all Lantiq XWAY SoC devices have an external bus unit (EBU) to @@ -66,16 +65,20 @@ 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) .org 0x200 /* TLB refill, 32 bit task */ 1: b 1b @@ -106,7 +109,9 @@ ENTRY(_start) 1: b 1b nop - .align 4 + .org 0x500 +#endif + reset: #if __mips_isa_rev >= 6 mfc0 t0, CP0_CONFIG, 5 diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig index 7d483aa..d982b0f 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 2e38bb7..8fad4cf 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. -- cgit v0.10.2 From 345490fcd68d830adef7fcfa4ef5bf5681c29546 Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Sun, 7 Feb 2016 19:39:58 +0100 Subject: MIPS: fix ROM exception vectors When booting from ROM, early exceptions can't be handled properly. Instead of busy-looping give the developer the possibilty to examine the situation. Invoke an UHI exception operation which can be read as unhandled exception by a hardware debugger if one is attached. If the debugger doesn't support UHI, the exception is read as unexpected breakpoint. Signed-off-by: Daniel Schwierzeck diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index 108d2df..2397b6c 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -52,6 +52,14 @@ .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 + ENTRY(_start) /* U-Boot entry point */ b reset @@ -79,30 +87,30 @@ ENTRY(_start) #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 */ @@ -222,6 +230,7 @@ reset: move a0, zero # a0 <-- boot_flags = 0 PTR_LA t9, board_init_f + jr t9 move ra, zero -- cgit v0.10.2 From 65d297af7c6a08ec65bf005fa9bd5cdb955efe39 Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Mon, 8 Feb 2016 00:37:59 +0100 Subject: MIPS: fix iand optimize setup of CP0 registers Clear cp0 status while preserving implementation specific bits. Set bits BEV and ERL as the arch specification requires after a reset or soft-reset exception. Extend and fix initialization of watch registers. Check if additional watch register sets are implemented and initialize them too. Initialize cp0 count as early as possible to get the most accurate boot timing. Signed-off-by: Daniel Schwierzeck diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index 2397b6c..1ad1884 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -34,24 +34,16 @@ # 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 - .endm - .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 + .macro uhi_mips_exception move k0, t9 # preserve t9 in k0 move k1, a0 # preserve a0 in k1 @@ -63,7 +55,7 @@ ENTRY(_start) /* U-Boot entry point */ b reset - nop + mtc0 zero, CP0_COUNT # clear cp0 count for most accurate boot timing #if defined(CONFIG_SYS_XWAY_EBU_BOOTCFG) /* @@ -141,17 +133,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 diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 9ab5063..7a9d222 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 -- cgit v0.10.2 From c3e72ab80135a19ac6eb2585b69de0acf19b87c1 Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Sun, 25 Sep 2016 18:36:38 +0200 Subject: MIPS: factor out code for initial stack and global data Move the code for setting up the initial stack and global data to a macro to be able to use it more than once. Signed-off-by: Daniel Schwierzeck diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index 1ad1884..f1040c2 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -52,6 +52,34 @@ 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 @@ -227,32 +255,8 @@ wr_done: # 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 -#endif + /* Set up initial stack and global data */ + setup_stack_gd move a0, zero # a0 <-- boot_flags = 0 PTR_LA t9, board_init_f -- cgit v0.10.2 From 924ad86638705fe37db98812f355260669f0f043 Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Sat, 4 Jun 2016 16:13:21 +0200 Subject: MIPS: add possibility to setup initial stack and global data in SRAM This adds a new Kconfig option CONFIG_MIPS_INIT_STACK_IN_SRAM which a SoC can select if it supports some kind of SRAM. Together with CONFIG_SYS_INIT_SP_ADDR the initial stack and global data can be set up in that SRAM. This can be used to provide a C environment also for lowlevel_init(). Signed-off-by: Daniel Schwierzeck diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 709ac5c..d97930e 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -302,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 f1040c2..6740fdf 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -234,6 +234,11 @@ wr_done: 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 */ @@ -255,8 +260,10 @@ wr_done: # endif #endif +#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 -- cgit v0.10.2 From 67588bdade302b9c26e00f6a2ceaccaf8fd98fba Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Sat, 9 Jan 2016 18:34:14 +0100 Subject: MIPS: add asm-offsets for struct pt_regs Import asm-offsets.c from kernel to generate offset for struct pt_regs needed by exception handlers. Signed-off-by: Daniel Schwierzeck diff --git a/arch/mips/include/asm/asm-offsets.h b/arch/mips/include/asm/asm-offsets.h new file mode 100644 index 0000000..5352b1c --- /dev/null +++ b/arch/mips/include/asm/asm-offsets.h @@ -0,0 +1,5 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include diff --git a/arch/mips/lib/asm-offsets.c b/arch/mips/lib/asm-offsets.c new file mode 100644 index 0000000..9ed295a --- /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 +#include +#include + +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(); +} -- cgit v0.10.2 From bd60252811c3c81dd0a32c0871b9116ba160190f Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Sat, 9 Jan 2016 18:34:14 +0100 Subject: MIPS: reserve space for exception vectors In order to set own exception handlers, a table with the exception vectors must be built in DRAM and the CPU EBase register must be set to the base address of this table. Reserve the space above the stack and use gd->irq_sp as storage for the exception base address. Signed-off-by: Daniel Schwierzeck diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index b7ce5df..02607f7 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -7,6 +7,7 @@ obj-y += cache.o obj-y += cache_init.o +obj-y += stack.o obj-$(CONFIG_CMD_BOOTM) += bootm.o diff --git a/arch/mips/lib/stack.c b/arch/mips/lib/stack.c new file mode 100644 index 0000000..c80f5fe --- /dev/null +++ b/arch/mips/lib/stack.c @@ -0,0 +1,19 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +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; +} -- cgit v0.10.2 From 6c59363004e6d3f860623daa330eef17fbccd8cd Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Sat, 9 Jan 2016 18:34:14 +0100 Subject: MIPS: add handling for generic and EJTAG exceptions 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 Reviewed-by: Paul Burton Tested-by: Paul Burton diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h index e6435cc..c9c5961 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 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..2d6d7b0 --- /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 +#include +#include +#include + +#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 0000000..18622c2 --- /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 +#include +#include +#include + +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(); +} -- cgit v0.10.2 From 4c2cb115163caa7ff60f5bcb072d2ae20385f508 Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Sat, 9 Jan 2016 18:34:15 +0100 Subject: common/board_f: enable initr_trap for MIPS Enable initr_trap hook also for MIPS to install and enable U-Boot's specific MIPS exception handlers. Signed-off-by: Daniel Schwierzeck Reviewed-by: Simon Glass diff --git a/common/board_r.c b/common/board_r.c index d959ad3..5496f45 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -191,7 +191,7 @@ static int initr_serial(void) return 0; } -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) static int initr_trap(void) { /* @@ -807,7 +807,7 @@ init_fnc_t init_sequence_r[] = { #ifdef CONFIG_NEEDS_MANUAL_RELOC initr_manual_reloc_cmdtable, #endif -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) +#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) initr_trap, #endif #ifdef CONFIG_ADDR_MAP -- cgit v0.10.2 From e7e0469c880f9b83ea577e52d7fea4ba928a212a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 25 Nov 2016 23:32:22 +0100 Subject: mips: Let cache.h be included from assembly source Add ifdef __ASSEMBLY__ around the function prototype to let cache.h be included from assembly code. Signed-off-by: Marek Vasut Cc: Daniel Schwierzeck Cc: Paul Burton diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h index 669c362..83165d5 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__ */ -- cgit v0.10.2 From 7a3e0f74a7c3ff83ba0607ebf8a14310ff08db60 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 26 Sep 2016 19:28:56 +0100 Subject: MIPS: Use ram_top, not bi_memsize, in arch_lmb_reserve When calculating the region to reserve for the stack in arch_lmb_reserve, make use of ram_top instead of adding bi_memsize to CONFIG_SYS_SDRAM_BASE. This avoids overflow if the system has enough memory to reach the end of the address space. Signed-off-by: Paul Burton diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c index 0c6a4ab..9fec4ad 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) -- cgit v0.10.2 From 6fd596a1aa57bd431263f45b0c57ee8ae6b2403c Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Mon, 26 Sep 2016 19:28:57 +0100 Subject: MIPS: Fix map_physmem for cached mappings map_physmem should return a pointer that can be used by the CPU to access the given memory - on MIPS simply returning the physical address as it does prior to this patch doesn't achieve that. Instead return a pointer to the memory within (c)kseg0, which matches up consistently with the (c)kseg1 pointer that uncached mappings return via ioremap. Signed-off-by: Paul Burton diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 5b86386..ee7a592 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); } /* -- cgit v0.10.2