summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel/start.S
blob: 776744c6c11bc22998faede54f6e132644f7df58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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