aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--payloads/libpayload/arch/armv7/exception.c31
-rw-r--r--payloads/libpayload/arch/armv7/exception_asm.S3
-rw-r--r--src/arch/armv7/bootblock.inc13
-rw-r--r--src/arch/armv7/exception.c36
-rw-r--r--src/arch/armv7/exception_asm.S3
-rw-r--r--src/arch/armv7/include/arch/cpu.h6
-rw-r--r--src/cpu/samsung/exynos5420/smp.c4
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. */