summaryrefslogtreecommitdiff
path: root/payloads/libpayload/arch/armv7
diff options
context:
space:
mode:
Diffstat (limited to 'payloads/libpayload/arch/armv7')
-rw-r--r--payloads/libpayload/arch/armv7/Makefile.inc1
-rw-r--r--payloads/libpayload/arch/armv7/exception.c155
-rw-r--r--payloads/libpayload/arch/armv7/exception_asm.S115
-rw-r--r--payloads/libpayload/arch/armv7/main.c3
4 files changed, 274 insertions, 0 deletions
diff --git a/payloads/libpayload/arch/armv7/Makefile.inc b/payloads/libpayload/arch/armv7/Makefile.inc
index 6d9e6c5c55..da0030e37c 100644
--- a/payloads/libpayload/arch/armv7/Makefile.inc
+++ b/payloads/libpayload/arch/armv7/Makefile.inc
@@ -32,4 +32,5 @@ libc-y += main.c sysinfo.c
libc-y += timer.c coreboot.c util.S
libc-y += virtual.c
libc-y += memcpy.S memset.S
+libc-y += exception_asm.S exception.c
diff --git a/payloads/libpayload/arch/armv7/exception.c b/payloads/libpayload/arch/armv7/exception.c
new file mode 100644
index 0000000000..8462b11fd0
--- /dev/null
+++ b/payloads/libpayload/arch/armv7/exception.c
@@ -0,0 +1,155 @@
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <arch/exception.h>
+#include <libpayload.h>
+#include <stdint.h>
+
+void exception_test(void);
+
+static int test_abort;
+
+void exception_undefined_instruction(uint32_t *);
+void exception_software_interrupt(uint32_t *);
+void exception_prefetch_abort(uint32_t *);
+void exception_data_abort(uint32_t *);
+void exception_not_used(uint32_t *);
+void exception_irq(uint32_t *);
+void exception_fiq(uint32_t *);
+
+static void print_regs(uint32_t *regs)
+{
+ /* 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 (int i = 0; i < 16; i++) {
+ if (i == 15)
+ printf("PC");
+ else if (i == 14)
+ continue; /* LR */
+ else if (i == 13)
+ continue; /* SP */
+ else if (i == 12)
+ printf("IP");
+ else
+ printf("R%d", i);
+ printf(" = 0x%08x\n", regs[i]);
+ }
+}
+
+void exception_undefined_instruction(uint32_t *regs)
+{
+ printf("exception _undefined_instruction\n");
+ print_regs(regs);
+ halt();
+}
+
+void exception_software_interrupt(uint32_t *regs)
+{
+ printf("exception _software_interrupt\n");
+ print_regs(regs);
+ halt();
+}
+
+void exception_prefetch_abort(uint32_t *regs)
+{
+ printf("exception _prefetch_abort\n");
+ print_regs(regs);
+ halt();
+}
+
+void exception_data_abort(uint32_t *regs)
+{
+ if (test_abort) {
+ regs[15] = regs[0];
+ return;
+ } else {
+ printf("exception _data_abort\n");
+ print_regs(regs);
+ }
+ halt();
+}
+
+void exception_not_used(uint32_t *regs)
+{
+ printf("exception _not_used\n");
+ print_regs(regs);
+ halt();
+}
+
+void exception_irq(uint32_t *regs)
+{
+ printf("exception _irq\n");
+ print_regs(regs);
+ halt();
+}
+
+void exception_fiq(uint32_t *regs)
+{
+ printf("exception _fiq\n");
+ print_regs(regs);
+ halt();
+}
+
+static inline uint32_t get_sctlr(void)
+{
+ uint32_t val;
+ asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (val));
+ return val;
+}
+
+static inline void set_sctlr(uint32_t val)
+{
+ asm volatile("mcr p15, 0, %0, c1, c0, 0" :: "r" (val));
+ asm volatile("" ::: "memory");
+}
+
+void exception_init(void)
+{
+ static const uint32_t sctlr_te = (0x1 << 30);
+ static const uint32_t sctlr_v = (0x1 << 13);
+ static const uint32_t sctlr_a = (0x1 << 1);
+
+ uint32_t sctlr = get_sctlr();
+ /* Handle exceptions in ARM mode. */
+ sctlr &= ~sctlr_te;
+ /* Set V=0 in SCTLR so VBAR points to the exception vector table. */
+ sctlr &= ~sctlr_v;
+ /* Enforce alignment. */
+ sctlr |= sctlr_a;
+ set_sctlr(sctlr);
+
+ extern uint32_t exception_table[];
+ set_vbar((uintptr_t)exception_table);
+
+ test_abort = 1;
+ exception_test();
+ test_abort = 0;
+}
diff --git a/payloads/libpayload/arch/armv7/exception_asm.S b/payloads/libpayload/arch/armv7/exception_asm.S
new file mode 100644
index 0000000000..e46f4bcf6b
--- /dev/null
+++ b/payloads/libpayload/arch/armv7/exception_asm.S
@@ -0,0 +1,115 @@
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright 2013 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+exception_stack:
+ .align 5
+ .skip 0x2000, 0xa5
+exception_stack_end:
+ .word exception_stack_end
+
+exception_handler:
+ .word 0
+
+
+ .align 6
+ .arm
+ .global exception_table
+exception_table:
+ b 1f
+ b 2f
+ b 3f
+ b 4f
+ b 5f
+ b 6f
+ b 7f
+ b 8f
+
+1:
+ ldr sp, _not_used
+ b exception_common
+2:
+ ldr sp, _undefined_instruction
+ b exception_common
+3:
+ ldr sp, _software_interrupt
+ b exception_common
+4:
+ ldr sp, _prefetch_abort
+ b exception_common
+5:
+ ldr sp, _data_abort
+ b exception_common
+6:
+ ldr sp, _not_used
+ b exception_common
+7:
+ ldr sp, _irq
+ b exception_common
+8:
+ ldr sp, _fiq
+ b exception_common
+
+exception_common:
+ str sp, exception_handler
+ ldr sp, exception_stack_end
+ push { lr }
+ sub sp, sp, $8
+ push { r0 - r12 }
+ mov r0, sp
+ mov lr, pc
+ ldr pc, exception_handler
+ pop { r0 - r12 }
+ add sp, sp, $8
+ ldm sp!, { pc }^
+
+
+_undefined_instruction: .word exception_undefined_instruction
+_software_interrupt: .word exception_software_interrupt
+_prefetch_abort: .word exception_prefetch_abort
+_data_abort: .word exception_data_abort
+_not_used: .word exception_not_used
+_irq: .word exception_irq
+_fiq: .word exception_fiq
+
+ .thumb
+ .global set_vbar
+ .thumb_func
+set_vbar:
+ mcr p15, 0, r0, c12, c0, 0
+ bx lr
+
+ .global exception_test
+ .thumb_func
+exception_test:
+ mov r1, $1
+ mov r0, pc
+ add r0, $3
+ ldr r1, [r1]
+ bx lr
+
diff --git a/payloads/libpayload/arch/armv7/main.c b/payloads/libpayload/arch/armv7/main.c
index 6b54b27fc6..93cfce5c63 100644
--- a/payloads/libpayload/arch/armv7/main.c
+++ b/payloads/libpayload/arch/armv7/main.c
@@ -27,6 +27,7 @@
* SUCH DAMAGE.
*/
+#include <arch/exception.h>
#include <libpayload.h>
unsigned int main_argc; /**< The argc value to pass to main() */
@@ -51,6 +52,8 @@ void start_main(void)
console_init();
#endif
+ exception_init();
+
/*
* Any other system init that has to happen before the
* user gets control goes here.