head.S 4.24 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0-only */
Palmer Dabbelt's avatar
Palmer Dabbelt committed
2
3
4
5
6
7
8
9
10
11
12
13
/*
 * Copyright (C) 2012 Regents of the University of California
 */

#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
#include <asm/asm.h>
#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/page.h>
#include <asm/csr.h>
14
#include <asm/image.h>
Palmer Dabbelt's avatar
Palmer Dabbelt committed
15
16
17

__INIT
ENTRY(_start)
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
	/*
	 * Image header expected by Linux boot-loaders. The image header data
	 * structure is described in asm/image.h.
	 * Do not modify it without modifying the structure and all bootloaders
	 * that expects this header format!!
	 */
	/* jump to start kernel */
	j _start_kernel
	/* reserved */
	.word 0
	.balign 8
#if __riscv_xlen == 64
	/* Image load offset(2MB) from start of RAM */
	.dword 0x200000
#else
	/* Image load offset(4MB) from start of RAM */
	.dword 0x400000
#endif
	/* Effective size of kernel image */
	.dword _end - _start
	.dword __HEAD_FLAGS
	.word RISCV_HEADER_VERSION
	.word 0
	.dword 0
42
	.ascii RISCV_IMAGE_MAGIC
43
	.balign 4
44
	.ascii RISCV_IMAGE_MAGIC2
45
46
47
48
	.word 0

.global _start_kernel
_start_kernel:
49
50
51
	/* Mask all interrupts */
	csrw CSR_SIE, zero
	csrw CSR_SIP, zero
Palmer Dabbelt's avatar
Palmer Dabbelt committed
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

	/* Load the global pointer */
.option push
.option norelax
	la gp, __global_pointer$
.option pop

	/*
	 * Disable FPU to detect illegal usage of
	 * floating point in kernel space
	 */
	li t0, SR_FS
	csrc sstatus, t0

	/* Pick one hart to run the main boot sequence */
	la a3, hart_lottery
	li a2, 1
	amoadd.w a3, a2, (a3)
	bnez a3, .Lsecondary_start

72
73
74
75
76
77
78
79
80
81
	/* Clear BSS for flat non-ELF images */
	la a3, __bss_start
	la a4, __bss_stop
	ble a4, a3, clear_bss_done
clear_bss:
	REG_S zero, (a3)
	add a3, a3, RISCV_SZPTR
	blt a3, a4, clear_bss
clear_bss_done:

Palmer Dabbelt's avatar
Palmer Dabbelt committed
82
83
84
	/* Save hart ID and DTB physical address */
	mv s0, a0
	mv s1, a1
85
86
	la a2, boot_cpu_hartid
	REG_S a0, (a2)
Palmer Dabbelt's avatar
Palmer Dabbelt committed
87
88
89

	/* Initialize page tables and relocate to virtual addresses */
	la sp, init_thread_union + THREAD_SIZE
90
	mv a0, s1
Palmer Dabbelt's avatar
Palmer Dabbelt committed
91
	call setup_vm
92
	la a0, early_pg_dir
Palmer Dabbelt's avatar
Palmer Dabbelt committed
93
94
95
96
	call relocate

	/* Restore C environment */
	la tp, init_task
97
	sw zero, TASK_TI_CPU(tp)
98
	la sp, init_thread_union + THREAD_SIZE
Palmer Dabbelt's avatar
Palmer Dabbelt committed
99
100

	/* Start the kernel */
101
	call parse_dtb
Palmer Dabbelt's avatar
Palmer Dabbelt committed
102
103
104
105
106
	tail start_kernel

relocate:
	/* Relocate return address */
	li a1, PAGE_OFFSET
107
108
	la a2, _start
	sub a1, a1, a2
Palmer Dabbelt's avatar
Palmer Dabbelt committed
109
110
	add ra, ra, a1

111
	/* Point stvec to virtual address of intruction after satp write */
112
113
114
	la a2, 1f
	add a2, a2, a1
	csrw CSR_STVEC, a2
Palmer Dabbelt's avatar
Palmer Dabbelt committed
115

116
	/* Compute satp for kernel page tables, but don't load it yet */
117
	srl a2, a0, PAGE_SHIFT
118
	li a1, SATP_MODE
Palmer Dabbelt's avatar
Palmer Dabbelt committed
119
120
121
122
	or a2, a2, a1

	/*
	 * Load trampoline page directory, which will cause us to trap to
123
124
125
	 * stvec if VA != PA, or simply fall through if VA == PA.  We need a
	 * full fence here because setup_vm() just wrote these PTEs and we need
	 * to ensure the new translations are in use.
Palmer Dabbelt's avatar
Palmer Dabbelt committed
126
127
128
129
130
	 */
	la a0, trampoline_pg_dir
	srl a0, a0, PAGE_SHIFT
	or a0, a0, a1
	sfence.vma
131
	csrw CSR_SATP, a0
132
.align 2
Palmer Dabbelt's avatar
Palmer Dabbelt committed
133
134
135
1:
	/* Set trap vector to spin forever to help debug */
	la a0, .Lsecondary_park
136
	csrw CSR_STVEC, a0
Palmer Dabbelt's avatar
Palmer Dabbelt committed
137
138
139
140
141
142
143

	/* Reload the global pointer */
.option push
.option norelax
	la gp, __global_pointer$
.option pop

144
145
146
147
148
149
	/*
	 * Switch to kernel page tables.  A full fence is necessary in order to
	 * avoid using the trampoline translations, which are only correct for
	 * the first superpage.  Fetching the fence is guarnteed to work
	 * because that first superpage is translated the same way.
	 */
150
	csrw CSR_SATP, a2
151
	sfence.vma
Palmer Dabbelt's avatar
Palmer Dabbelt committed
152
153
154
155
156
157
158
159
160
161

	ret

.Lsecondary_start:
#ifdef CONFIG_SMP
	li a1, CONFIG_NR_CPUS
	bgeu a0, a1, .Lsecondary_park

	/* Set trap vector to spin forever to help debug */
	la a3, .Lsecondary_park
162
	csrw CSR_STVEC, a3
Palmer Dabbelt's avatar
Palmer Dabbelt committed
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

	slli a3, a0, LGREG
	la a1, __cpu_up_stack_pointer
	la a2, __cpu_up_task_pointer
	add a1, a3, a1
	add a2, a3, a2

	/*
	 * This hart didn't win the lottery, so we wait for the winning hart to
	 * get far enough along the boot process that it should continue.
	 */
.Lwait_for_cpu_up:
	/* FIXME: We should WFI to save some energy here. */
	REG_L sp, (a1)
	REG_L tp, (a2)
	beqz sp, .Lwait_for_cpu_up
	beqz tp, .Lwait_for_cpu_up
	fence

	/* Enable virtual memory and relocate to virtual address */
183
	la a0, swapper_pg_dir
Palmer Dabbelt's avatar
Palmer Dabbelt committed
184
185
186
187
188
	call relocate

	tail smp_callin
#endif

189
.align 2
Palmer Dabbelt's avatar
Palmer Dabbelt committed
190
191
192
193
194
195
196
197
198
.Lsecondary_park:
	/* We lack SMP support or have too many harts, so park this hart */
	wfi
	j .Lsecondary_park
END(_start)

__PAGE_ALIGNED_BSS
	/* Empty zero page */
	.balign PAGE_SIZE