xref: /openbmc/linux/arch/riscv/kernel/head.S (revision aa5b395b)
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (C) 2012 Regents of the University of California
4 */
5
6#include <asm/thread_info.h>
7#include <asm/asm-offsets.h>
8#include <asm/asm.h>
9#include <linux/init.h>
10#include <linux/linkage.h>
11#include <asm/thread_info.h>
12#include <asm/page.h>
13#include <asm/csr.h>
14#include <asm/hwcap.h>
15#include <asm/image.h>
16
17__INIT
18ENTRY(_start)
19	/*
20	 * Image header expected by Linux boot-loaders. The image header data
21	 * structure is described in asm/image.h.
22	 * Do not modify it without modifying the structure and all bootloaders
23	 * that expects this header format!!
24	 */
25	/* jump to start kernel */
26	j _start_kernel
27	/* reserved */
28	.word 0
29	.balign 8
30#if __riscv_xlen == 64
31	/* Image load offset(2MB) from start of RAM */
32	.dword 0x200000
33#else
34	/* Image load offset(4MB) from start of RAM */
35	.dword 0x400000
36#endif
37	/* Effective size of kernel image */
38	.dword _end - _start
39	.dword __HEAD_FLAGS
40	.word RISCV_HEADER_VERSION
41	.word 0
42	.dword 0
43	.ascii RISCV_IMAGE_MAGIC
44	.balign 4
45	.ascii RISCV_IMAGE_MAGIC2
46	.word 0
47
48.global _start_kernel
49_start_kernel:
50	/* Mask all interrupts */
51	csrw CSR_IE, zero
52	csrw CSR_IP, zero
53
54#ifdef CONFIG_RISCV_M_MODE
55	/* flush the instruction cache */
56	fence.i
57
58	/* Reset all registers except ra, a0, a1 */
59	call reset_regs
60
61	/*
62	 * The hartid in a0 is expected later on, and we have no firmware
63	 * to hand it to us.
64	 */
65	csrr a0, CSR_MHARTID
66#endif /* CONFIG_RISCV_M_MODE */
67
68	/* Load the global pointer */
69.option push
70.option norelax
71	la gp, __global_pointer$
72.option pop
73
74	/*
75	 * Disable FPU to detect illegal usage of
76	 * floating point in kernel space
77	 */
78	li t0, SR_FS
79	csrc CSR_STATUS, t0
80
81#ifdef CONFIG_SMP
82	li t0, CONFIG_NR_CPUS
83	blt a0, t0, .Lgood_cores
84	tail .Lsecondary_park
85.Lgood_cores:
86#endif
87
88	/* Pick one hart to run the main boot sequence */
89	la a3, hart_lottery
90	li a2, 1
91	amoadd.w a3, a2, (a3)
92	bnez a3, .Lsecondary_start
93
94	/* Clear BSS for flat non-ELF images */
95	la a3, __bss_start
96	la a4, __bss_stop
97	ble a4, a3, clear_bss_done
98clear_bss:
99	REG_S zero, (a3)
100	add a3, a3, RISCV_SZPTR
101	blt a3, a4, clear_bss
102clear_bss_done:
103
104	/* Save hart ID and DTB physical address */
105	mv s0, a0
106	mv s1, a1
107	la a2, boot_cpu_hartid
108	REG_S a0, (a2)
109
110	/* Initialize page tables and relocate to virtual addresses */
111	la sp, init_thread_union + THREAD_SIZE
112	mv a0, s1
113	call setup_vm
114#ifdef CONFIG_MMU
115	la a0, early_pg_dir
116	call relocate
117#endif /* CONFIG_MMU */
118
119	/* Restore C environment */
120	la tp, init_task
121	sw zero, TASK_TI_CPU(tp)
122	la sp, init_thread_union + THREAD_SIZE
123
124	/* Start the kernel */
125	call parse_dtb
126	tail start_kernel
127
128#ifdef CONFIG_MMU
129relocate:
130	/* Relocate return address */
131	li a1, PAGE_OFFSET
132	la a2, _start
133	sub a1, a1, a2
134	add ra, ra, a1
135
136	/* Point stvec to virtual address of intruction after satp write */
137	la a2, 1f
138	add a2, a2, a1
139	csrw CSR_TVEC, a2
140
141	/* Compute satp for kernel page tables, but don't load it yet */
142	srl a2, a0, PAGE_SHIFT
143	li a1, SATP_MODE
144	or a2, a2, a1
145
146	/*
147	 * Load trampoline page directory, which will cause us to trap to
148	 * stvec if VA != PA, or simply fall through if VA == PA.  We need a
149	 * full fence here because setup_vm() just wrote these PTEs and we need
150	 * to ensure the new translations are in use.
151	 */
152	la a0, trampoline_pg_dir
153	srl a0, a0, PAGE_SHIFT
154	or a0, a0, a1
155	sfence.vma
156	csrw CSR_SATP, a0
157.align 2
1581:
159	/* Set trap vector to spin forever to help debug */
160	la a0, .Lsecondary_park
161	csrw CSR_TVEC, a0
162
163	/* Reload the global pointer */
164.option push
165.option norelax
166	la gp, __global_pointer$
167.option pop
168
169	/*
170	 * Switch to kernel page tables.  A full fence is necessary in order to
171	 * avoid using the trampoline translations, which are only correct for
172	 * the first superpage.  Fetching the fence is guarnteed to work
173	 * because that first superpage is translated the same way.
174	 */
175	csrw CSR_SATP, a2
176	sfence.vma
177
178	ret
179#endif /* CONFIG_MMU */
180
181.Lsecondary_start:
182#ifdef CONFIG_SMP
183	/* Set trap vector to spin forever to help debug */
184	la a3, .Lsecondary_park
185	csrw CSR_TVEC, a3
186
187	slli a3, a0, LGREG
188	la a1, __cpu_up_stack_pointer
189	la a2, __cpu_up_task_pointer
190	add a1, a3, a1
191	add a2, a3, a2
192
193	/*
194	 * This hart didn't win the lottery, so we wait for the winning hart to
195	 * get far enough along the boot process that it should continue.
196	 */
197.Lwait_for_cpu_up:
198	/* FIXME: We should WFI to save some energy here. */
199	REG_L sp, (a1)
200	REG_L tp, (a2)
201	beqz sp, .Lwait_for_cpu_up
202	beqz tp, .Lwait_for_cpu_up
203	fence
204
205#ifdef CONFIG_MMU
206	/* Enable virtual memory and relocate to virtual address */
207	la a0, swapper_pg_dir
208	call relocate
209#endif
210
211	tail smp_callin
212#endif
213
214END(_start)
215
216#ifdef CONFIG_RISCV_M_MODE
217ENTRY(reset_regs)
218	li	sp, 0
219	li	gp, 0
220	li	tp, 0
221	li	t0, 0
222	li	t1, 0
223	li	t2, 0
224	li	s0, 0
225	li	s1, 0
226	li	a2, 0
227	li	a3, 0
228	li	a4, 0
229	li	a5, 0
230	li	a6, 0
231	li	a7, 0
232	li	s2, 0
233	li	s3, 0
234	li	s4, 0
235	li	s5, 0
236	li	s6, 0
237	li	s7, 0
238	li	s8, 0
239	li	s9, 0
240	li	s10, 0
241	li	s11, 0
242	li	t3, 0
243	li	t4, 0
244	li	t5, 0
245	li	t6, 0
246	csrw	CSR_SCRATCH, 0
247
248#ifdef CONFIG_FPU
249	csrr	t0, CSR_MISA
250	andi	t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)
251	beqz	t0, .Lreset_regs_done
252
253	li	t1, SR_FS
254	csrs	CSR_STATUS, t1
255	fmv.s.x	f0, zero
256	fmv.s.x	f1, zero
257	fmv.s.x	f2, zero
258	fmv.s.x	f3, zero
259	fmv.s.x	f4, zero
260	fmv.s.x	f5, zero
261	fmv.s.x	f6, zero
262	fmv.s.x	f7, zero
263	fmv.s.x	f8, zero
264	fmv.s.x	f9, zero
265	fmv.s.x	f10, zero
266	fmv.s.x	f11, zero
267	fmv.s.x	f12, zero
268	fmv.s.x	f13, zero
269	fmv.s.x	f14, zero
270	fmv.s.x	f15, zero
271	fmv.s.x	f16, zero
272	fmv.s.x	f17, zero
273	fmv.s.x	f18, zero
274	fmv.s.x	f19, zero
275	fmv.s.x	f20, zero
276	fmv.s.x	f21, zero
277	fmv.s.x	f22, zero
278	fmv.s.x	f23, zero
279	fmv.s.x	f24, zero
280	fmv.s.x	f25, zero
281	fmv.s.x	f26, zero
282	fmv.s.x	f27, zero
283	fmv.s.x	f28, zero
284	fmv.s.x	f29, zero
285	fmv.s.x	f30, zero
286	fmv.s.x	f31, zero
287	csrw	fcsr, 0
288	/* note that the caller must clear SR_FS */
289#endif /* CONFIG_FPU */
290.Lreset_regs_done:
291	ret
292END(reset_regs)
293#endif /* CONFIG_RISCV_M_MODE */
294
295.section ".text", "ax",@progbits
296.align 2
297.Lsecondary_park:
298	/* We lack SMP support or have too many harts, so park this hart */
299	wfi
300	j .Lsecondary_park
301
302__PAGE_ALIGNED_BSS
303	/* Empty zero page */
304	.balign PAGE_SIZE
305