diff options
-rw-r--r-- | payloads/libpayload/arch/armv7/exception.c | 31 | ||||
-rw-r--r-- | payloads/libpayload/arch/armv7/exception_asm.S | 3 | ||||
-rw-r--r-- | src/arch/armv7/bootblock.inc | 13 | ||||
-rw-r--r-- | src/arch/armv7/exception.c | 36 | ||||
-rw-r--r-- | src/arch/armv7/exception_asm.S | 3 | ||||
-rw-r--r-- | src/arch/armv7/include/arch/cpu.h | 6 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5420/smp.c | 4 |
7 files changed, 67 insertions, 29 deletions
diff --git a/payloads/libpayload/arch/armv7/exception.c b/payloads/libpayload/arch/armv7/exception.c index 9efc312833..8d8b50b175 100644 --- a/payloads/libpayload/arch/armv7/exception.c +++ b/payloads/libpayload/arch/armv7/exception.c @@ -43,20 +43,32 @@ void exception_not_used(uint32_t *); void exception_irq(uint32_t *); void exception_fiq(uint32_t *); +static void dump_stack(uintptr_t addr, size_t bytes) +{ + int i, j; + const int line = 8; + uint32_t *ptr = (uint32_t *)(addr & ~(line * sizeof(*ptr) - 1)); + + printf("Dumping stack:\n"); + for (i = bytes / sizeof(*ptr); i >= 0; i -= line) { + printf("%p: ", ptr + i); + for (j = i; j < i + line; j++) + printf("%08x ", *(ptr + j)); + printf("\n"); + } +} + static void print_regs(uint32_t *regs) { int i; - /* Don't print the link register and stack pointer since we don't have their - * actual value. They are hidden by the 'shadow' registers provided - * by the trap hardware. - */ + for (i = 0; i < 16; i++) { if (i == 15) printf("PC"); else if (i == 14) - continue; /* LR */ + printf("LR"); else if (i == 13) - continue; /* SP */ + printf("SP"); else if (i == 12) printf("IP"); else @@ -69,6 +81,7 @@ void exception_undefined_instruction(uint32_t *regs) { printf("exception _undefined_instruction\n"); print_regs(regs); + dump_stack(regs[13], 512); halt(); } @@ -76,6 +89,7 @@ void exception_software_interrupt(uint32_t *regs) { printf("exception _software_interrupt\n"); print_regs(regs); + dump_stack(regs[13], 512); halt(); } @@ -83,6 +97,7 @@ void exception_prefetch_abort(uint32_t *regs) { printf("exception _prefetch_abort\n"); print_regs(regs); + dump_stack(regs[13], 512); halt(); } @@ -94,6 +109,7 @@ void exception_data_abort(uint32_t *regs) } else { printf("exception _data_abort\n"); print_regs(regs); + dump_stack(regs[13], 512); } halt(); } @@ -102,6 +118,7 @@ void exception_not_used(uint32_t *regs) { printf("exception _not_used\n"); print_regs(regs); + dump_stack(regs[13], 512); halt(); } @@ -109,6 +126,7 @@ void exception_irq(uint32_t *regs) { printf("exception _irq\n"); print_regs(regs); + dump_stack(regs[13], 512); halt(); } @@ -116,6 +134,7 @@ void exception_fiq(uint32_t *regs) { printf("exception _fiq\n"); print_regs(regs); + dump_stack(regs[13], 512); halt(); } diff --git a/payloads/libpayload/arch/armv7/exception_asm.S b/payloads/libpayload/arch/armv7/exception_asm.S index e46f4bcf6b..163fdbd52a 100644 --- a/payloads/libpayload/arch/armv7/exception_asm.S +++ b/payloads/libpayload/arch/armv7/exception_asm.S @@ -79,6 +79,7 @@ exception_common: str sp, exception_handler ldr sp, exception_stack_end push { lr } + stmfd sp, { sp, lr }^ sub sp, sp, $8 push { r0 - r12 } mov r0, sp @@ -86,7 +87,7 @@ exception_common: ldr pc, exception_handler pop { r0 - r12 } add sp, sp, $8 - ldm sp!, { pc }^ + ldmfd sp!, { pc }^ _undefined_instruction: .word exception_undefined_instruction diff --git a/src/arch/armv7/bootblock.inc b/src/arch/armv7/bootblock.inc index c45259db6d..b28a787839 100644 --- a/src/arch/armv7/bootblock.inc +++ b/src/arch/armv7/bootblock.inc @@ -43,15 +43,12 @@ _cbfs_master_header: reset: /* - * Set the cpu to SVC32 mode and unmask aborts. Aborts might happen - * before logging is turned on and may crash the machine, but at least - * the problem will show up near the code that causes it. + * Set the cpu to System mode with IRQ and FIQ disabled. Prefetch/Data + * aborts may happen early and crash before the abort handlers are + * installed, but at least the problem will show up near the code that + * causes it. */ - mrs r0, cpsr - bic r0, r0, #0x1f - orr r0, r0, #0xd3 - bic r0, r0, #0x100 - msr cpsr_cxsf,r0 + msr cpsr_cxf, #0xdf /* * From Cortex-A Series Programmer's Guide: diff --git a/src/arch/armv7/exception.c b/src/arch/armv7/exception.c index 1055cb5663..3b32e8bbb1 100644 --- a/src/arch/armv7/exception.c +++ b/src/arch/armv7/exception.c @@ -27,9 +27,10 @@ * SUCH DAMAGE. */ -#include <console/console.h> -#include <arch/exception.h> #include <stdint.h> +#include <types.h> +#include <arch/exception.h> +#include <console/console.h> void exception_test(void); @@ -43,20 +44,32 @@ void exception_not_used(uint32_t *); void exception_irq(uint32_t *); void exception_fiq(uint32_t *); +static void dump_stack(uintptr_t addr, size_t bytes) +{ + int i, j; + const int line = 8; + uint32_t *ptr = (uint32_t *)(addr & ~(line * sizeof(*ptr) - 1)); + + printk(BIOS_ERR, "Dumping stack:\n"); + for (i = bytes / sizeof(*ptr); i >= 0; i -= line) { + printk(BIOS_ERR, "%p: ", ptr + i); + for (j = i; j < i + line; j++) + printk(BIOS_ERR, "%08x ", *(ptr + j)); + printk(BIOS_ERR, "\n"); + } +} + static void print_regs(uint32_t *regs) { int i; - /* Don't print the link register and stack pointer since we don't have their - * actual value. They are hidden by the 'shadow' registers provided - * by the trap hardware. - */ + for (i = 0; i < 16; i++) { if (i == 15) printk(BIOS_ERR, "PC"); else if (i == 14) - continue; /* LR */ + printk(BIOS_ERR, "LR"); else if (i == 13) - continue; /* SP */ + printk(BIOS_ERR, "SP"); else if (i == 12) printk(BIOS_ERR, "IP"); else @@ -69,6 +82,7 @@ void exception_undefined_instruction(uint32_t *regs) { printk(BIOS_ERR, "exception _undefined_instruction\n"); print_regs(regs); + dump_stack(regs[13], 512); die("exception"); } @@ -76,6 +90,7 @@ void exception_software_interrupt(uint32_t *regs) { printk(BIOS_ERR, "exception _software_interrupt\n"); print_regs(regs); + dump_stack(regs[13], 512); die("exception"); } @@ -83,6 +98,7 @@ void exception_prefetch_abort(uint32_t *regs) { printk(BIOS_ERR, "exception _prefetch_abort\n"); print_regs(regs); + dump_stack(regs[13], 512); die("exception"); } @@ -94,6 +110,7 @@ void exception_data_abort(uint32_t *regs) } else { printk(BIOS_ERR, "exception _data_abort\n"); print_regs(regs); + dump_stack(regs[13], 512); } die("exception"); } @@ -102,6 +119,7 @@ void exception_not_used(uint32_t *regs) { printk(BIOS_ERR, "exception _not_used\n"); print_regs(regs); + dump_stack(regs[13], 512); die("exception"); } @@ -109,6 +127,7 @@ void exception_irq(uint32_t *regs) { printk(BIOS_ERR, "exception _irq\n"); print_regs(regs); + dump_stack(regs[13], 512); die("exception"); } @@ -116,6 +135,7 @@ void exception_fiq(uint32_t *regs) { printk(BIOS_ERR, "exception _fiq\n"); print_regs(regs); + dump_stack(regs[13], 512); die("exception"); } diff --git a/src/arch/armv7/exception_asm.S b/src/arch/armv7/exception_asm.S index e46f4bcf6b..163fdbd52a 100644 --- a/src/arch/armv7/exception_asm.S +++ b/src/arch/armv7/exception_asm.S @@ -79,6 +79,7 @@ exception_common: str sp, exception_handler ldr sp, exception_stack_end push { lr } + stmfd sp, { sp, lr }^ sub sp, sp, $8 push { r0 - r12 } mov r0, sp @@ -86,7 +87,7 @@ exception_common: ldr pc, exception_handler pop { r0 - r12 } add sp, sp, $8 - ldm sp!, { pc }^ + ldmfd sp!, { pc }^ _undefined_instruction: .word exception_undefined_instruction diff --git a/src/arch/armv7/include/arch/cpu.h b/src/arch/armv7/include/arch/cpu.h index df44a9244c..52cc8a3f50 100644 --- a/src/arch/armv7/include/arch/cpu.h +++ b/src/arch/armv7/include/arch/cpu.h @@ -98,10 +98,10 @@ inline static void sev(void) asm volatile ("sev"); } -/* puts CPU into SVC32 mode and disable interrupts. */ -inline static void set_svc32_mode(void) +/* puts CPU into System mode and disable interrupts. */ +inline static void set_system_mode(void) { - asm volatile("msr cpsr_c, %0" :: "r"(0x13 | 0xc0)); + asm volatile("msr cpsr_c, %0" :: "r"(0x1f | 0xc0)); } struct cpu_info *cpu_info(void); diff --git a/src/cpu/samsung/exynos5420/smp.c b/src/cpu/samsung/exynos5420/smp.c index 2a0656bcaf..069110c069 100644 --- a/src/cpu/samsung/exynos5420/smp.c +++ b/src/cpu/samsung/exynos5420/smp.c @@ -169,7 +169,7 @@ static void core_start_execution(void) struct exynos5_power *power = samsung_get_base_power(); enable_smp(); - set_svc32_mode(); + set_system_mode(); cpu_id = read_mpidr() & 0x3; /* up to 4 processors for one cluster. */ cpu_state = exynos_cpu_states->cpu_states[cpu_id]; @@ -221,7 +221,7 @@ static void low_power_start(void) sev(); } - set_svc32_mode(); + set_system_mode(); /* Whenever a Cortex A-15 core powers on, iROM resets its L2 cache * so we need to configure again. */ |