From d9f1cee286c8d039e290f624baeeb133b8d47a21 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Tue, 17 Dec 2019 21:35:32 -0500 Subject: riscv: Fix breakage caused by linker relaxation Due to the two-instruction sequence needed to access arbitrary memory locations, the RISC-V linker aggressively optimises memory accesses and jumps at link-time. This is called "linker relaxation," and is discussed in this SiFive article . One of the optimizations in place is to assume that the __global_pointer symbol is placed in the gp register. To quote the article: "...The magic __global_pointer$ symbol is defined to point 0x800 bytes past the start of the .sdata section. The 0x800 magic number allows signed 12-bit offsets from __global_pointer$ to address symbols at the start of the .sdata section. The linker assumes that if this symbol is defined, then the gp register contains that value, which it can then use to relax accesses to global symbols within that 12-bit range. The compiler treats the gp register as a constant so it doesn't need to be saved or restored, which means it is generally only written by _start, the ELF entry point." However, U-Boot instead keeps the global data pointer in gp. This causes memory accesses and jumps optimized to use the gp pointer to fail. To fix this problem, we undefine the __global_pointer symbol. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng Reviewed-by: Rick Chen --- arch/riscv/cpu/u-boot.lds | 1 - 1 file changed, 1 deletion(-) (limited to 'arch') diff --git a/arch/riscv/cpu/u-boot.lds b/arch/riscv/cpu/u-boot.lds index 838a844399..c00d17c736 100644 --- a/arch/riscv/cpu/u-boot.lds +++ b/arch/riscv/cpu/u-boot.lds @@ -32,7 +32,6 @@ SECTIONS . = ALIGN(4); .data : { - __global_pointer$ = . + 0x800; *(.data*) } . = ALIGN(4); -- cgit From fd1f6e9a0bc7ba536c19478b2fd8619ecda6ec3b Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Wed, 25 Dec 2019 00:27:44 -0500 Subject: riscv: Add option to print registers on exception When debugging, it can be helpful to see more information about an unhandled exception. This patch adds an option to view the registers at the time of the trap, similar to the linux output on a kernel panic. Signed-off-by: Sean Anderson Reviewed-by: Rick Chen Reviewed-by: Bin Meng Tested-by: Bin Meng --- arch/riscv/Kconfig | 3 +++ arch/riscv/cpu/mtrap.S | 3 ++- arch/riscv/lib/interrupts.c | 50 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 44 insertions(+), 12 deletions(-) (limited to 'arch') diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 85e15ebffa..3338b788f8 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -222,6 +222,9 @@ config XIP from a NOR flash memory without copying the code to ram. Say yes here if U-Boot boots from flash directly. +config SHOW_REGS + bool "Show registers on unhandled exception" + config STACK_SIZE_SHIFT int default 14 diff --git a/arch/riscv/cpu/mtrap.S b/arch/riscv/cpu/mtrap.S index 407ecfa9c0..e40c7bd3f4 100644 --- a/arch/riscv/cpu/mtrap.S +++ b/arch/riscv/cpu/mtrap.S @@ -64,7 +64,8 @@ trap_entry: SREG x31, 31 * REGBYTES(sp) csrr a0, MODE_PREFIX(cause) csrr a1, MODE_PREFIX(epc) - mv a2, sp + csrr a2, MODE_PREFIX(tval) + mv a3, sp jal handle_trap csrw MODE_PREFIX(epc), a0 diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c index 512dce0619..074c70ee77 100644 --- a/arch/riscv/lib/interrupts.c +++ b/arch/riscv/lib/interrupts.c @@ -5,6 +5,8 @@ * * Copyright (C) 2017 Andes Technology Corporation * Rick Chen, Andes Technology Corporation + * + * Copyright (C) 2019 Sean Anderson */ #include @@ -14,7 +16,34 @@ #include #include -static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs) +static void show_regs(struct pt_regs *regs) +{ +#ifdef CONFIG_SHOW_REGS + printf("RA: " REG_FMT " SP: " REG_FMT " GP: " REG_FMT "\n", + regs->ra, regs->sp, regs->gp); + printf("TP: " REG_FMT " T0: " REG_FMT " T1: " REG_FMT "\n", + regs->tp, regs->t0, regs->t1); + printf("T2: " REG_FMT " S0: " REG_FMT " S1: " REG_FMT "\n", + regs->t2, regs->s0, regs->s1); + printf("A0: " REG_FMT " A1: " REG_FMT " A2: " REG_FMT "\n", + regs->a0, regs->a1, regs->a2); + printf("A3: " REG_FMT " A4: " REG_FMT " A5: " REG_FMT "\n", + regs->a3, regs->a4, regs->a5); + printf("A6: " REG_FMT " A7: " REG_FMT " S2: " REG_FMT "\n", + regs->a6, regs->a7, regs->s2); + printf("S3: " REG_FMT " S4: " REG_FMT " S5: " REG_FMT "\n", + regs->s3, regs->s4, regs->s5); + printf("S6: " REG_FMT " S7: " REG_FMT " S8: " REG_FMT "\n", + regs->s6, regs->s7, regs->s8); + printf("S9: " REG_FMT " S10: " REG_FMT " S11: " REG_FMT "\n", + regs->s9, regs->s10, regs->s11); + printf("T3: " REG_FMT " T4: " REG_FMT " T5: " REG_FMT "\n", + regs->t3, regs->t4, regs->t5); + printf("T6: " REG_FMT "\n", regs->t6); +#endif +} + +static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs) { static const char * const exception_code[] = { "Instruction address misaligned", @@ -35,14 +64,13 @@ static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs) "Store/AMO page fault", }; - if (code < ARRAY_SIZE(exception_code)) { - printf("exception code: %ld , %s , epc %lx , ra %lx\n", - code, exception_code[code], epc, regs->ra); - } else { - printf("reserved exception code: %ld , epc %lx , ra %lx\n", - code, epc, regs->ra); - } + if (code < ARRAY_SIZE(exception_code)) + printf("Unhandled exception: %s\n", exception_code[code]); + else + printf("Unhandled exception code: %ld\n", code); + printf("EPC: " REG_FMT " TVAL: " REG_FMT "\n", epc, tval); + show_regs(regs); hang(); } @@ -66,7 +94,7 @@ int disable_interrupts(void) return 0; } -ulong handle_trap(ulong cause, ulong epc, struct pt_regs *regs) +ulong handle_trap(ulong cause, ulong epc, ulong tval, struct pt_regs *regs) { ulong is_irq, irq; @@ -84,11 +112,11 @@ ulong handle_trap(ulong cause, ulong epc, struct pt_regs *regs) timer_interrupt(0); /* handle timer interrupt */ break; default: - _exit_trap(cause, epc, regs); + _exit_trap(cause, epc, tval, regs); break; }; } else { - _exit_trap(cause, epc, regs); + _exit_trap(cause, epc, tval, regs); } return epc; -- cgit From 404339759ef5e0bcd4fa7768d1148b1ace2d2bb6 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Mon, 27 Jan 2020 16:39:44 -0500 Subject: riscv: Remove unnecessary instruction The add instruction on risc-v can have any three sources and targets, so there is no need for an intermediate mov. Signed-off-by: Sean Anderson Reviewed-by: Rick Chen Reviewed-by: Bin Meng --- arch/riscv/cpu/start.S | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'arch') diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index f3dccdbe4c..6b3ff99c38 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -359,9 +359,8 @@ relocate_secondary_harts: call_board_init_r: jal invalidate_icache_all jal flush_dcache_all - la t0, board_init_r - mv t4, t0 /* offset of board_init_r() */ - add t4, t4, t6 /* real address of board_init_r() */ + la t0, board_init_r /* offset of board_init_r() */ + add t4, t0, t6 /* real address of board_init_r() */ /* * setup parameters for board_init_r */ -- cgit