summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel/start.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel/start.S')
-rw-r--r--arch/arm64/kernel/start.S94
1 files changed, 94 insertions, 0 deletions
diff --git a/arch/arm64/kernel/start.S b/arch/arm64/kernel/start.S
new file mode 100644
index 0000000..776744c
--- /dev/null
+++ b/arch/arm64/kernel/start.S
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * tashaboot arm64 entry. firmware drops us here, usually at EL2 on
+ * qemu virt. we park the secondaries, drop to EL1, set the stack and
+ * hand the dtb pointer to C.
+ *
+ * Copyright (C) 2026 Bradley Morgan <brads@mainlining.org>
+ */
+
+#include <asm/macro.h>
+
+.section .text.boot
+.globl _start
+_start:
+ b reset
+
+ .balign 8
+.globl _text_base
+_text_base:
+ .quad 0x40000000
+
+reset:
+ /* keep the dtb pointer before anything clobbers x0 */
+ mov x19, x0
+
+ /* park secondary cores, they have nothing to do yet */
+ mrs x0, mpidr_el1
+ and x0, x0, #0xff
+ cbnz x0, park
+
+ /* figure out which EL we got */
+ mrs x0, CurrentEL
+ lsr x0, x0, #2
+ cmp x0, #3
+ b.eq from_el3
+ cmp x0, #2
+ b.eq from_el2
+ cmp x0, #1
+ b.eq el1_entry
+ b park
+
+from_el3:
+ /* EL3 is a dead end for us, drop through the EL2 path if we can */
+ b park
+
+from_el2:
+ /* EL1 must be aarch64 */
+ mov x0, #(1 << 31)
+ msr hcr_el2, x0
+
+ /* scrub the EL2 state so EL1 starts clean */
+ msr cptr_el2, xzr
+ msr hstr_el2, xzr
+ mrs x0, cnthctl_el2
+ orr x0, x0, #(3 << 0)
+ msr cnthctl_el2, x0
+ msr vpidr_el2, xzr
+
+ mov x0, #0x3c5
+ msr scr_el3, x0
+
+ /* no MMU, no caches at EL1 yet */
+ msr sctlr_el1, xzr
+ isb
+
+ /* SPSR for EL1h with interrupts masked */
+ mov x0, #0x3c5
+ msr spsr_el2, x0
+ adr x0, el1_entry
+ msr elr_el2, x0
+ eret
+
+el1_entry:
+ /* stack for the bootloader, grows down from the image end */
+ ldr x0, =__image_end
+ mov sp, x0
+
+ /* clear bss */
+ ldr x0, =__bss_start
+ ldr x1, =__bss_end
+1: cmp x0, x1
+ b.hs 2f
+ str xzr, [x0], #8
+ b 1b
+2:
+
+ /* dtb pointer into C arg 0 */
+ mov x0, x19
+ bl tashaboot_main
+
+ /* if main returns there is nothing sensible to do */
+park:
+ wfe
+ b park