[U-Boot] [PATCH 0/9] MIPS: improve start.S and add exception support

Fix and optinmize initialization of cp0 registers. Also add the possibilty to setup the initial stack and global data in SRAM to provide a C environment for lowlevel_init(). This could be used on the QCA ath79 platform to rewrite and optimize the low-level init code.
Add support for a dynamic exception vectors in RAM and add initial exception handlers. The general exception handler prints an oops message similar to Linux kernel and then hangs. The EJTAG exception handler checks for SDBBP and delegates to the SDBBP handler if necessary. Otherwise the debug mode will be simply exited. The SDBBP handler currently only prints the content of registers c0_depc and c0_debug. This could be extended in the future to handle semi-hosting according to the MIPS UHI specification.
This patch series is also available at: git://git.denx.de/u-boot-mips.git mips_rework_start_v1
Daniel Schwierzeck (9): MIPS: make inclusion of ROM exception vectors configurable MIPS: fix ROM exception vectors MIPS: fix iand optimize setup of CP0 registers MIPS: factor out code for initial stack and global data MIPS: add possibility to setup initial stack and global data in SRAM MIPS: add asm-offsets for struct pt_regs MIPS: reserve space for exception vectors MIPS: add handling for generic and EJTAG exceptions common/board_f: enable initr_trap for MIPS
arch/mips/Kconfig | 32 ++++++ arch/mips/cpu/start.S | 165 +++++++++++++++++---------- arch/mips/include/asm/asm-offsets.h | 5 + arch/mips/include/asm/mipsregs.h | 1 + arch/mips/include/asm/u-boot-mips.h | 4 + arch/mips/lib/Makefile | 3 + arch/mips/lib/asm-offsets.c | 61 ++++++++++ arch/mips/lib/genex.S | 214 ++++++++++++++++++++++++++++++++++++ arch/mips/lib/stack.c | 19 ++++ arch/mips/lib/traps.c | 104 ++++++++++++++++++ arch/mips/mach-ath79/Kconfig | 2 + arch/mips/mach-pic32/Kconfig | 1 + common/board_r.c | 4 +- 13 files changed, 552 insertions(+), 63 deletions(-) create mode 100644 arch/mips/include/asm/asm-offsets.h create mode 100644 arch/mips/lib/asm-offsets.c create mode 100644 arch/mips/lib/genex.S create mode 100644 arch/mips/lib/stack.c create mode 100644 arch/mips/lib/traps.c

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 daniel.schwierzeck@gmail.com ---
arch/mips/Kconfig | 21 +++++++++++++++++++++ arch/mips/cpu/start.S | 11 ++++++++--- arch/mips/mach-ath79/Kconfig | 2 ++ arch/mips/mach-pic32/Kconfig | 1 + 4 files changed, 32 insertions(+), 3 deletions(-)
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.

When booting from ROM, early exceptions can't be handled properly. Instead of busy-looping give the developer the possibilty to examine the situation. Thus issue a SDBBP instruction to transfer control to hardware debugger if one is attached.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com ---
arch/mips/cpu/start.S | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index 108d2df..6886036 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -79,30 +79,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 + sdbbp
.org 0x280 /* XTLB refill, 64 bit task */ -1: b 1b - nop + sdbbp
.org 0x300 /* Cache error exception */ -1: b 1b - nop + sdbbp
.org 0x380 /* General exception */ -1: b 1b - nop + sdbbp
.org 0x400 /* Catch interrupt exceptions */ -1: b 1b - nop + sdbbp
.org 0x480 /* EJTAG debug exception */ @@ -222,6 +222,7 @@ reset:
move a0, zero # a0 <-- boot_flags = 0 PTR_LA t9, board_init_f + jr t9 move ra, zero

Daniel Schwierzeck daniel.schwierzeck@gmail.com writes:
When booting from ROM, early exceptions can't be handled properly. Instead of busy-looping give the developer the possibilty to examine the situation. Thus issue a SDBBP instruction to transfer control to hardware debugger if one is attached.
You could make the SDBBP into a UHI operation that can be read by a debugger as an unhandled exception rather than an unexpected breakpoint (assuming said debugger knows about UHI). The fragment I use in lightweight boot code is:
move k0, t9 # Preserve t9 move k1, a0 # Preserve a0 li $25, 15 # UHI exception operation li $4, 0 # Use hard register context sdbbp 1 # Invoke UHI operation
You lose k0/k1 in this which may be undesirable but it might be a reasonable trade off. This shouldn't go in the debug vector of course!
Matthew

2016-09-26 9:58 GMT+02:00 Matthew Fortune Matthew.Fortune@imgtec.com:
Daniel Schwierzeck daniel.schwierzeck@gmail.com writes:
When booting from ROM, early exceptions can't be handled properly. Instead of busy-looping give the developer the possibilty to examine the situation. Thus issue a SDBBP instruction to transfer control to hardware debugger if one is attached.
You could make the SDBBP into a UHI operation that can be read by a debugger as an unhandled exception rather than an unexpected breakpoint (assuming said debugger knows about UHI). The fragment I use in lightweight boot code is:
move k0, t9 # Preserve t9 move k1, a0 # Preserve a0 li $25, 15 # UHI exception operation li $4, 0 # Use hard register context sdbbp 1 # Invoke UHI operation
You lose k0/k1 in this which may be undesirable but it might be a reasonable trade off. This shouldn't go in the debug vector of course!
sounds interesting. I'll have a look into that. Can I test this with OpenOCD and GDB?

Daniel Schwierzeck daniel.schwierzeck@gmail.com writes:
2016-09-26 9:58 GMT+02:00 Matthew Fortune Matthew.Fortune@imgtec.com:
Daniel Schwierzeck daniel.schwierzeck@gmail.com writes:
When booting from ROM, early exceptions can't be handled properly. Instead of busy-looping give the developer the possibilty to examine the situation. Thus issue a SDBBP instruction to transfer control to hardware debugger if one is attached.
You could make the SDBBP into a UHI operation that can be read by a debugger as an unhandled exception rather than an unexpected breakpoint (assuming said debugger knows about UHI). The fragment I use in lightweight boot code is:
move k0, t9 # Preserve t9 move k1, a0 # Preserve a0 li $25, 15 # UHI exception operation li $4, 0 # Use hard register context sdbbp 1 # Invoke UHI operation
You lose k0/k1 in this which may be undesirable but it might be a reasonable trade off. This shouldn't go in the debug vector of course!
sounds interesting. I'll have a look into that. Can I test this with OpenOCD and GDB?
I'm sorry to say progress with getting UHI into OpenOCD is rather slow. The main effort for OpenOCD has been part of the MIPSfpga project which I am not directly involved with. To my knowledge they have the basic 'write' call implemented but are not handling all the operations and the implementation is out of tree. I'll try and check on this and let you know.
I had an idea of using a special UHI operation to indicate a boot failure with a simple enumerated 'reason' code so you could get a quick hint at what blew up in low level boot code without the source. I.e. any errors that can be detected without ending up raising an exception. I put two quickly thought up errors into the UHI spec as an example but I only have some simplistic boot code to play with. If you think U-boot could have a range of errors to report like this (and want to use it) then we can add to the list.
Matthew

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 daniel.schwierzeck@gmail.com ---
arch/mips/cpu/start.S | 74 +++++++++++++++++++++++++++------------- arch/mips/include/asm/mipsregs.h | 1 + 2 files changed, 51 insertions(+), 24 deletions(-)
diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index 6886036..c909ffa 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -34,28 +34,20 @@ # 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 + 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) /* @@ -133,17 +125,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

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 daniel.schwierzeck@gmail.com ---
arch/mips/cpu/start.S | 56 +++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 26 deletions(-)
diff --git a/arch/mips/cpu/start.S b/arch/mips/cpu/start.S index c909ffa..ee9de99 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -44,6 +44,34 @@ nop .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 @@ -219,32 +247,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

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 daniel.schwierzeck@gmail.com ---
arch/mips/Kconfig | 11 +++++++++++ arch/mips/cpu/start.S | 7 +++++++ 2 files changed, 18 insertions(+)
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 ee9de99..3af571c 100644 --- a/arch/mips/cpu/start.S +++ b/arch/mips/cpu/start.S @@ -226,6 +226,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 */ @@ -247,8 +252,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

Import asm-offsets.c from kernel to generate offset for struct pt_regs needed by exception handlers.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com ---
arch/mips/include/asm/asm-offsets.h | 5 +++ arch/mips/lib/asm-offsets.c | 61 +++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 arch/mips/include/asm/asm-offsets.h create mode 100644 arch/mips/lib/asm-offsets.c
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 <generated/asm-offsets.h> 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 <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(); +}

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 daniel.schwierzeck@gmail.com ---
arch/mips/lib/Makefile | 1 + arch/mips/lib/stack.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 arch/mips/lib/stack.c
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 <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; +}

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
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); +}

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)

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

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

Enable initr_trap hook also for MIPS to install and enable U-Boot's specific MIPS exception handlers.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
---
common/board_r.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
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

On 25 September 2016 at 12:05, Daniel Schwierzeck daniel.schwierzeck@gmail.com wrote:
Enable initr_trap hook also for MIPS to install and enable U-Boot's specific MIPS exception handlers.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
common/board_r.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Daniel Schwierzeck daniel.schwierzeck@gmail.com writes:
will be simply exited. The SDBBP handler currently only prints the content of registers c0_depc and c0_debug. This could be extended in the future to handle semi-hosting according to the MIPS UHI specification.
Thanks for considering UHI in this. I worked on a prototype implementation of UHI with Paul that is yet to be submitted which hooks the syscall exception in U-Boot. There is a way to avoid going all the way down to debug mode to process a UHI operation on-target so we can support cores that don't have ejtag or simply to stay out of debug mode wherever possible. The basic principle is that either an application doesn't install its own exception vector and hence uses U-boot's or it does install its own but remembers where U-boot's EBASE was and unwinds a SYSCALL exception and forwards it to U-boot's general-exception handler. It seems to work pretty well but there is certainly no harm in hooking the debug vector too.
Matthew
participants (4)
-
Daniel Schwierzeck
-
Matthew Fortune
-
Paul Burton
-
Simon Glass