aboutsummaryrefslogtreecommitdiff
path: root/src/arch/arm64/armv8
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm64/armv8')
-rw-r--r--src/arch/arm64/armv8/Makefile.inc3
-rw-r--r--src/arch/arm64/armv8/bootblock.S36
-rw-r--r--src/arch/arm64/armv8/cpu.S62
-rw-r--r--src/arch/arm64/armv8/exception.c20
4 files changed, 59 insertions, 62 deletions
diff --git a/src/arch/arm64/armv8/Makefile.inc b/src/arch/arm64/armv8/Makefile.inc
index 359a368ab9..f25a567b29 100644
--- a/src/arch/arm64/armv8/Makefile.inc
+++ b/src/arch/arm64/armv8/Makefile.inc
@@ -26,6 +26,9 @@ armv8_asm_flags = $(armv8_flags)
################################################################################
ifeq ($(CONFIG_ARCH_BOOTBLOCK_ARMV8_64),y)
+ifneq ($(CONFIG_BOOTBLOCK_CUSTOM),y)
+bootblock-y += bootblock.S
+endif
bootblock-y += cache.c
bootblock-y += cache_helpers.S
bootblock-y += cpu.S
diff --git a/src/arch/arm64/armv8/bootblock.S b/src/arch/arm64/armv8/bootblock.S
index a23a5f2788..4a9fea9af6 100644
--- a/src/arch/arm64/armv8/bootblock.S
+++ b/src/arch/arm64/armv8/bootblock.S
@@ -1,7 +1,7 @@
/*
* Early initialization code for aarch64 (a.k.a. armv8)
*
- * Copyright 2013 Google Inc.
+ * Copyright 2015 Google Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -14,21 +14,23 @@
* GNU General Public License for more details.
*/
- .section ".id", "a", %progbits
+#include <arch/asm.h>
- .globl __id_start
-__id_start:
-ver:
- .asciz COREBOOT_VERSION
-vendor:
- .asciz CONFIG_MAINBOARD_VENDOR
-part:
- .asciz CONFIG_MAINBOARD_PART_NUMBER
-.long __id_end - ver /* Reverse offset to the vendor id */
-.long __id_end - vendor /* Reverse offset to the vendor id */
-.long __id_end - part /* Reverse offset to the part number */
-.long CONFIG_ROM_SIZE /* Size of this romimage */
- .globl __id_end
+ENTRY(_start)
+ /* Initialize PSTATE, SCTLR and caches to clean state. */
+ bl arm64_init_cpu
-__id_end:
-.previous
+ /* Initialize stack with sentinel value to later check overflow. */
+ ldr x0, =_stack
+ ldr x1, =_estack
+ ldr x2, =0xdeadbeefdeadbeef
+stack_init_loop:
+ stp x2, x2, [x0], #16
+ cmp x0, x1
+ bne stack_init_loop
+
+ /* Leave a line of beef dead for easier visibility in stack dumps. */
+ sub sp, x0, #16
+
+ bl main
+ENDPROC(_start)
diff --git a/src/arch/arm64/armv8/cpu.S b/src/arch/arm64/armv8/cpu.S
index c248cb3a81..4713ca59f9 100644
--- a/src/arch/arm64/armv8/cpu.S
+++ b/src/arch/arm64/armv8/cpu.S
@@ -19,27 +19,40 @@
/*
* Bring an ARMv8 processor we just gained control of (e.g. from IROM) into a
- * known state regarding caches/SCTLR. Completely cleans and invalidates
+ * known state regarding caches/SCTLR/PSTATE. Completely cleans and invalidates
* icache/dcache, disables MMU and dcache (if active), and enables unaligned
- * accesses, icache and branch prediction (if inactive). Clobbers x4 and x5.
+ * accesses, icache and branch prediction (if inactive). Clobbers R22 and R23.
*/
-ENTRY(arm_init_caches)
- /* w4: SCTLR, return address: x8 (stay valid for the whole function) */
- mov x8, x30
- /* XXX: Assume that we always start running at EL3 */
- mrs x4, sctlr_el3
+ENTRY(arm64_init_cpu)
+ /* Initialize PSTATE (unmask all exceptions, select SP_EL0). */
+ msr SPSel, #0
+ msr DAIFClr, #0xf
- /* FIXME: How to enable branch prediction on ARMv8? */
+ /* TODO: This is where we'd put non-boot CPUs into WFI if needed. */
+
+ /* x22: SCTLR, return address: x23 (callee-saved by subroutine) */
+ mov x23, x30
+ /* TODO: Assert that we always start running at EL3 */
+ mrs x22, sctlr_el3
+
+ /* Activate ICache (12) already for speed during cache flush below. */
+ orr x22, x22, #(1 << 12)
+ msr sctlr_el3, x22
+ isb
/* Flush and invalidate dcache */
mov x0, #DCCISW
bl flush_dcache_all
/* Deactivate MMU (0), Alignment Check (1) and DCache (2) */
- and x4, x4, # ~(1 << 0) & ~(1 << 1) & ~(1 << 2)
- /* Activate ICache (12) already for speed */
- orr x4, x4, #(1 << 12)
- msr sctlr_el3, x4
+ and x22, x22, # ~(1 << 0) & ~(1 << 1) & ~(1 << 2)
+ /* Activate Stack Alignment (3) because why not */
+ orr x22, x22, #(1 << 3)
+ /* Set to little-endian (25) */
+ and x22, x22, # ~(1 << 25)
+ /* Deactivate write-xor-execute enforcement (19) */
+ and x22, x22, # ~(1 << 19)
+ msr sctlr_el3, x22
/* Invalidate icache and TLB for good measure */
ic iallu
@@ -47,26 +60,5 @@ ENTRY(arm_init_caches)
dsb sy
isb
- ret x8
-ENDPROC(arm_init_caches)
-
-/* Based on u-boot transition.S */
-ENTRY(switch_el3_to_el2)
- mov x0, #0x5b1 /* Non-secure EL0/EL1 | HVC | 64bit EL2 */
- msr scr_el3, x0
- msr cptr_el3, xzr /* Disable coprocessor traps to EL3 */
- mov x0, #0x33ff
- msr cptr_el2, x0 /* Disable coprocessor traps to EL2 */
-
- /* Return to the EL2_SP2 mode from EL3 */
- mov x0, sp
- msr sp_el2, x0 /* Migrate SP */
- mrs x0, vbar_el3
- msr vbar_el2, x0 /* Migrate VBAR */
- mrs x0, sctlr_el3
- msr sctlr_el2, x0 /* Migrate SCTLR */
- mov x0, #0x3c9
- msr spsr_el3, x0 /* EL2_SP2 | D | A | I | F */
- msr elr_el3, x30
- eret
-ENDPROC(switch_el3_to_el2)
+ ret x23
+ENDPROC(arm64_init_cpu)
diff --git a/src/arch/arm64/armv8/exception.c b/src/arch/arm64/armv8/exception.c
index afbaf6da78..35e3f7fac6 100644
--- a/src/arch/arm64/armv8/exception.c
+++ b/src/arch/arm64/armv8/exception.c
@@ -36,6 +36,8 @@
#include <console/console.h>
#include <arch/lib_helpers.h>
+uint8_t exception_stack[0x200] __attribute__((aligned(16)));
+
static const char *exception_names[NUM_EXC_VIDS] = {
[EXC_VID_CUR_SP_EL0_SYNC] = "_sync_sp_el0",
[EXC_VID_CUR_SP_EL0_IRQ] = "_irq_sp_el0",
@@ -193,19 +195,17 @@ static uint64_t test_exception(void)
return 0;
}
-void exception_hwinit(void)
-{
- exc_set_vbar();
-}
-
void exception_init(void)
{
- /* Load the exception table. */
- exception_hwinit();
+ /* Load the exception table and initialize SP_EL3. */
+ exception_init_asm(exception_stack + ARRAY_SIZE(exception_stack));
printk(BIOS_DEBUG, "ARM64: Exception handlers installed.\n");
- printk(BIOS_DEBUG, "ARM64: Testing exception\n");
- test_exception();
- printk(BIOS_DEBUG, "ARM64: Done test exception\n");
+ /* Only spend time testing on debug builds that are trying to detect more errors. */
+ if (IS_ENABLED(CONFIG_FATAL_ASSERTS)) {
+ printk(BIOS_DEBUG, "ARM64: Testing exception\n");
+ test_exception();
+ printk(BIOS_DEBUG, "ARM64: Done test exception\n");
+ }
}